@google/gemini-cli 0.64.0-preview.0 → 0.64.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundle/{chunk-EDYPRCAA.js → chunk-5XKZL6EB.js} +2 -2
- package/bundle/{chunk-EDVFNWRG.js → chunk-7H3F2KUX.js} +1 -1
- package/bundle/{chunk-EFX5XL6M.js → chunk-DPNFVVVC.js} +2 -2
- package/bundle/{chunk-QUCRASYB.js → chunk-ENBP32XB.js} +1 -1
- package/bundle/{chunk-UFQDAROY.js → chunk-EV5MQULH.js} +1 -1
- package/bundle/{chunk-HSZIYPL6.js → chunk-FCPMU3HO.js} +3 -3
- package/bundle/{chunk-MLSLNORV.js → chunk-FJUB4QHG.js} +3 -3
- package/bundle/{chunk-HN74ORTP.js → chunk-FLKY6NH5.js} +15 -3
- package/bundle/{chunk-SDWOC67Z.js → chunk-HHALNKOO.js} +1 -1
- package/bundle/{chunk-NX7TO2DU.js → chunk-IESQO4NS.js} +1 -1
- package/bundle/{chunk-6OFXOGEG.js → chunk-J7SXW2FI.js} +458 -96
- package/bundle/{chunk-KCCVXZ52.js → chunk-KJWA3D3G.js} +25 -9
- package/bundle/{chunk-EBP6K2WG.js → chunk-MA35JFUP.js} +25 -9
- package/bundle/{chunk-ZQW7OGUO.js → chunk-NR7L3FXV.js} +427 -92
- package/bundle/{chunk-ZOHM7BPT.js → chunk-OQYJODOA.js} +1 -1
- package/bundle/{chunk-VBVCLWLA.js → chunk-P7ZJXXPR.js} +2 -2
- package/bundle/{chunk-2NQXIWQK.js → chunk-PS4UL4AP.js} +15 -3
- package/bundle/{chunk-A4TO2DY2.js → chunk-PZ4GDG24.js} +458 -96
- package/bundle/{chunk-ZPLFLZQA.js → chunk-QCHFD56F.js} +15 -3
- package/bundle/{chunk-Y2HXXBXI.js → chunk-QLNDNLK5.js} +1 -1
- package/bundle/{chunk-2VN53SWW.js → chunk-QSLJVHXU.js} +1 -1
- package/bundle/{chunk-U76XPSKR.js → chunk-V7G7CIBW.js} +25 -9
- package/bundle/{chunk-UBGF6JU5.js → chunk-VOLZQW4I.js} +1 -1
- package/bundle/{chunk-VJYKQD5D.js → chunk-WLZT2COY.js} +3 -3
- package/bundle/{cleanup-GGCB2LVD.js → cleanup-K7PKM5O3.js} +2 -2
- package/bundle/{cleanup-JRDG3OTL.js → cleanup-NAOD2SQV.js} +2 -2
- package/bundle/{cleanup-SSW6IXTR.js → cleanup-QRBWTWKF.js} +2 -2
- package/bundle/{core-IUIZE6JW.js → core-4P3HPH34.js} +11 -1
- package/bundle/{dist-7L3BRW6V.js → core-ICFDSJL3.js} +11 -1
- package/bundle/{devtoolsService-3SADPKKB.js → devtoolsService-4MGN7S5K.js} +2 -2
- package/bundle/{devtoolsService-MF6JKRUV.js → devtoolsService-7CS2YIL6.js} +2 -2
- package/bundle/{devtoolsService-XZCKFZP5.js → devtoolsService-LKOU7QN7.js} +2 -2
- package/bundle/{core-6HRWFQZW.js → dist-YMXCTNJD.js} +11 -1
- package/bundle/docs/tools/mcp-server.md +41 -12
- package/bundle/{gemini-QOQNG5VY.js → gemini-6ESINPDZ.js} +14 -14
- package/bundle/{gemini-ZMMDUAQJ.js → gemini-IPXWMEB5.js} +14 -14
- package/bundle/{gemini-JPMMQ3KA.js → gemini-Q2GRYIAK.js} +14 -14
- package/bundle/gemini.js +7 -7
- package/bundle/{interactiveCli-R3P4A3FC.js → interactiveCli-2T27ZS4G.js} +9 -20
- package/bundle/{interactiveCli-UDWGRVJL.js → interactiveCli-66E5CZDR.js} +9 -20
- package/bundle/{interactiveCli-3I4TG5SK.js → interactiveCli-IX4FVS6G.js} +9 -20
- package/bundle/{liteRtServerManager-OVPUSK2T.js → liteRtServerManager-BFSWF4GA.js} +4 -4
- package/bundle/{liteRtServerManager-RAV63AGE.js → liteRtServerManager-CU5D7FDE.js} +4 -4
- package/bundle/{liteRtServerManager-4MWCEVVM.js → liteRtServerManager-JJZYMP2G.js} +4 -4
- package/bundle/{oauth2-provider-XFP63FGJ.js → oauth2-provider-65ILSORU.js} +1 -1
- package/bundle/{oauth2-provider-FVTRRJZR.js → oauth2-provider-CHSEPLKC.js} +1 -1
- package/bundle/{oauth2-provider-EWOA64PR.js → oauth2-provider-N73PS5ZT.js} +1 -1
- package/bundle/{start-DJAIXPPY.js → start-6JMUZJ7T.js} +6 -6
- package/bundle/{start-VQQ2Q5KT.js → start-6KYN7M6S.js} +6 -6
- package/bundle/{start-5O7TBK5L.js → start-YI7IUIYU.js} +6 -6
- package/package.json +1 -1
|
@@ -283844,8 +283844,8 @@ function isValidToolName(name3, options = {}) {
|
|
|
283844
283844
|
}
|
|
283845
283845
|
|
|
283846
283846
|
// packages/core/src/generated/git-commit.ts
|
|
283847
|
-
var GIT_COMMIT_INFO = "
|
|
283848
|
-
var CLI_VERSION = "0.64.0-preview.
|
|
283847
|
+
var GIT_COMMIT_INFO = "90997f398";
|
|
283848
|
+
var CLI_VERSION = "0.64.0-preview.1";
|
|
283849
283849
|
|
|
283850
283850
|
// packages/core/src/ide/detect-ide.ts
|
|
283851
283851
|
var IDE_DEFINITIONS = {
|
|
@@ -307961,7 +307961,7 @@ function getVersion() {
|
|
|
307961
307961
|
}
|
|
307962
307962
|
versionPromise = (async () => {
|
|
307963
307963
|
const pkgJson = await getPackageJson(__dirname4);
|
|
307964
|
-
return "0.64.0-preview.
|
|
307964
|
+
return "0.64.0-preview.1";
|
|
307965
307965
|
})();
|
|
307966
307966
|
return versionPromise;
|
|
307967
307967
|
}
|
|
@@ -310443,6 +310443,144 @@ var BENIGN_SUBCOMMAND_TOKENS = /* @__PURE__ */ new Set([
|
|
|
310443
310443
|
"restart",
|
|
310444
310444
|
"status"
|
|
310445
310445
|
]);
|
|
310446
|
+
var SAFE_SHORT_FLAGS = /* @__PURE__ */ new Set([
|
|
310447
|
+
"-a",
|
|
310448
|
+
"-A",
|
|
310449
|
+
"-b",
|
|
310450
|
+
"-B",
|
|
310451
|
+
"-C",
|
|
310452
|
+
"-d",
|
|
310453
|
+
"-D",
|
|
310454
|
+
"-E",
|
|
310455
|
+
"-F",
|
|
310456
|
+
"-g",
|
|
310457
|
+
"-G",
|
|
310458
|
+
"-h",
|
|
310459
|
+
"-H",
|
|
310460
|
+
"-i",
|
|
310461
|
+
"-I",
|
|
310462
|
+
"-l",
|
|
310463
|
+
"-L",
|
|
310464
|
+
"-m",
|
|
310465
|
+
"-n",
|
|
310466
|
+
"-N",
|
|
310467
|
+
"-p",
|
|
310468
|
+
"-P",
|
|
310469
|
+
"-q",
|
|
310470
|
+
"-r",
|
|
310471
|
+
"-R",
|
|
310472
|
+
"-s",
|
|
310473
|
+
"-S",
|
|
310474
|
+
"-t",
|
|
310475
|
+
"-T",
|
|
310476
|
+
"-u",
|
|
310477
|
+
"-U",
|
|
310478
|
+
"-v",
|
|
310479
|
+
"-V",
|
|
310480
|
+
"-w",
|
|
310481
|
+
"-W",
|
|
310482
|
+
"-x",
|
|
310483
|
+
"-z",
|
|
310484
|
+
"-1",
|
|
310485
|
+
// Common combined POSIX inspection flags (ls, grep, ps, git)
|
|
310486
|
+
"-la",
|
|
310487
|
+
"-al",
|
|
310488
|
+
"-ld",
|
|
310489
|
+
"-dl",
|
|
310490
|
+
"-lh",
|
|
310491
|
+
"-hl",
|
|
310492
|
+
"-lah",
|
|
310493
|
+
"-alh",
|
|
310494
|
+
"-lrt",
|
|
310495
|
+
"-ltr",
|
|
310496
|
+
"-rn",
|
|
310497
|
+
"-nr",
|
|
310498
|
+
"-ri",
|
|
310499
|
+
"-ir",
|
|
310500
|
+
"-rni",
|
|
310501
|
+
"-rin",
|
|
310502
|
+
"-ni",
|
|
310503
|
+
"-in",
|
|
310504
|
+
"-ef",
|
|
310505
|
+
"-aux"
|
|
310506
|
+
]);
|
|
310507
|
+
var SAFE_LONG_FLAGS = /* @__PURE__ */ new Set([
|
|
310508
|
+
"--all",
|
|
310509
|
+
"--oneline",
|
|
310510
|
+
"--stat",
|
|
310511
|
+
"--numstat",
|
|
310512
|
+
"--shortstat",
|
|
310513
|
+
"--name-only",
|
|
310514
|
+
"--name-status",
|
|
310515
|
+
"--graph",
|
|
310516
|
+
"--decorate",
|
|
310517
|
+
"--no-pager",
|
|
310518
|
+
"--color",
|
|
310519
|
+
"--no-color",
|
|
310520
|
+
"--grep",
|
|
310521
|
+
"--author",
|
|
310522
|
+
"--since",
|
|
310523
|
+
"--until",
|
|
310524
|
+
"--before",
|
|
310525
|
+
"--after",
|
|
310526
|
+
"--pretty",
|
|
310527
|
+
"--format",
|
|
310528
|
+
"--abbrev-commit",
|
|
310529
|
+
"--max-count",
|
|
310530
|
+
"--cached",
|
|
310531
|
+
"--staged",
|
|
310532
|
+
"--short",
|
|
310533
|
+
"--branch",
|
|
310534
|
+
"--porcelain",
|
|
310535
|
+
"--help",
|
|
310536
|
+
"--version",
|
|
310537
|
+
"--quiet",
|
|
310538
|
+
"--verbose",
|
|
310539
|
+
"--dry-run",
|
|
310540
|
+
"--ignore-case",
|
|
310541
|
+
"--line-number",
|
|
310542
|
+
"--recursive",
|
|
310543
|
+
"--extended-regexp",
|
|
310544
|
+
"--fixed-strings",
|
|
310545
|
+
"--files-with-matches",
|
|
310546
|
+
"--count",
|
|
310547
|
+
"--context",
|
|
310548
|
+
"--before-context",
|
|
310549
|
+
"--after-context"
|
|
310550
|
+
]);
|
|
310551
|
+
var HIGH_RISK_VALUE_FLAGS = /* @__PURE__ */ new Set([
|
|
310552
|
+
"-c",
|
|
310553
|
+
"-e",
|
|
310554
|
+
"--eval",
|
|
310555
|
+
"--exec",
|
|
310556
|
+
"-exec",
|
|
310557
|
+
"-execdir",
|
|
310558
|
+
"--run_under",
|
|
310559
|
+
"--test_strategy",
|
|
310560
|
+
"--test_arg",
|
|
310561
|
+
"--test_env",
|
|
310562
|
+
"--action_env",
|
|
310563
|
+
"--jvmopt",
|
|
310564
|
+
"--host_jvm_args",
|
|
310565
|
+
"--wrapper_script_flag",
|
|
310566
|
+
"--upload-pack",
|
|
310567
|
+
"--receive-pack",
|
|
310568
|
+
"--require",
|
|
310569
|
+
"--import",
|
|
310570
|
+
"--loader"
|
|
310571
|
+
]);
|
|
310572
|
+
var FILE_MODE_STRING_REGEX = /^[dcbpsl-][rwxstST-]{9}[+@.]?$/i;
|
|
310573
|
+
var BARE_DASHES_REGEX = /^--+$/;
|
|
310574
|
+
var BARE_SHELL_VARIABLE_REGEX = /^\$(?:[a-zA-Z_][a-zA-Z0-9_]*|\{[a-zA-Z_][a-zA-Z0-9_]*\})$/;
|
|
310575
|
+
function isHighRiskPatternToken(token2) {
|
|
310576
|
+
return token2.startsWith("http://") || token2.startsWith("https://") || token2.startsWith("/") || token2.startsWith("\\") || token2.startsWith("./") || token2.startsWith("../") || /^[a-zA-Z]:[\\/]/.test(token2) || /\.(sh|bash|zsh|ps1|bat|cmd|exe)$/i.test(token2);
|
|
310577
|
+
}
|
|
310578
|
+
function hasUntrustedSubstring(untrustedContext, value) {
|
|
310579
|
+
const normalized2 = value.toLowerCase().replace(/\\/g, "/");
|
|
310580
|
+
return untrustedContext.untrustedTexts.some(
|
|
310581
|
+
(text) => text.toLowerCase().includes(normalized2)
|
|
310582
|
+
);
|
|
310583
|
+
}
|
|
310446
310584
|
function extractUntrustedContext(history) {
|
|
310447
310585
|
const untrustedTexts = [];
|
|
310448
310586
|
const untrustedTokens = /* @__PURE__ */ new Set();
|
|
@@ -310471,35 +310609,24 @@ function extractUntrustedContext(history) {
|
|
|
310471
310609
|
if (untrustedContent) {
|
|
310472
310610
|
const normalizedContent = untrustedContent.replace(/\\/g, "/");
|
|
310473
310611
|
untrustedTexts.push(normalizedContent);
|
|
310474
|
-
const
|
|
310612
|
+
const contentWithoutShellMetadata = normalizedContent.replace(/^\s*Output:\s*(\(empty\))?\s*/i, "").replace(
|
|
310613
|
+
/\n(?:Exit Code|Signal|Background PIDs|Process Group PGID):.*$/gim,
|
|
310614
|
+
""
|
|
310615
|
+
);
|
|
310616
|
+
const tokens = contentWithoutShellMetadata.split(/[\s,`"';()|&[\]{}<>]+/).map((t2) => t2.trim()).filter((t2) => t2.length > 1).filter((t2) => !BARE_DASHES_REGEX.test(t2)).filter((t2) => !FILE_MODE_STRING_REGEX.test(t2)).filter((t2) => !BENIGN_SUBCOMMAND_TOKENS.has(t2.toLowerCase())).filter((t2) => !SAFE_SHORT_FLAGS.has(t2)).filter((t2) => !SAFE_LONG_FLAGS.has(t2.toLowerCase()));
|
|
310475
310617
|
for (const token2 of tokens) {
|
|
310476
|
-
const
|
|
310477
|
-
|
|
310478
|
-
|
|
310479
|
-
|
|
310480
|
-
|
|
310481
|
-
untrustedTokens.add(lowerToken.substring(1));
|
|
310482
|
-
}
|
|
310483
|
-
if (lowerToken.includes("=")) {
|
|
310484
|
-
const eqParts = lowerToken.split("=");
|
|
310618
|
+
const isShortFlag = token2.startsWith("-") && !token2.startsWith("--");
|
|
310619
|
+
const tokenToStore = isShortFlag ? token2 : token2.toLowerCase();
|
|
310620
|
+
untrustedTokens.add(tokenToStore);
|
|
310621
|
+
if (token2.includes("=")) {
|
|
310622
|
+
const eqParts = token2.split("=");
|
|
310485
310623
|
for (const eqPart of eqParts) {
|
|
310486
310624
|
const trimmedPart = eqPart.trim();
|
|
310487
|
-
if (trimmedPart.length > 1) {
|
|
310488
|
-
|
|
310489
|
-
|
|
310490
|
-
|
|
310491
|
-
|
|
310492
|
-
untrustedTokens.add(trimmedPart.substring(1));
|
|
310493
|
-
}
|
|
310494
|
-
}
|
|
310495
|
-
}
|
|
310496
|
-
}
|
|
310497
|
-
if (lowerToken.includes("/")) {
|
|
310498
|
-
const pathParts = lowerToken.split("/");
|
|
310499
|
-
for (const part2 of pathParts) {
|
|
310500
|
-
const trimmedPart = part2.trim();
|
|
310501
|
-
if (trimmedPart.length > 1) {
|
|
310502
|
-
untrustedTokens.add(trimmedPart);
|
|
310625
|
+
if (trimmedPart.length > 1 && !BARE_DASHES_REGEX.test(trimmedPart) && !SAFE_SHORT_FLAGS.has(trimmedPart) && !SAFE_LONG_FLAGS.has(trimmedPart.toLowerCase())) {
|
|
310626
|
+
const isPartShortFlag = trimmedPart.startsWith("-") && !trimmedPart.startsWith("--");
|
|
310627
|
+
untrustedTokens.add(
|
|
310628
|
+
isPartShortFlag ? trimmedPart : trimmedPart.toLowerCase()
|
|
310629
|
+
);
|
|
310503
310630
|
}
|
|
310504
310631
|
}
|
|
310505
310632
|
}
|
|
@@ -310518,7 +310645,7 @@ function findUntrustedFlags(command, untrustedContext) {
|
|
|
310518
310645
|
let parsed;
|
|
310519
310646
|
try {
|
|
310520
310647
|
const normalizedCommand = process.platform === "win32" ? command.replace(/\\(?!")/g, "/") : command;
|
|
310521
|
-
parsed = (0, import_shell_quote5.parse)(normalizedCommand);
|
|
310648
|
+
parsed = (0, import_shell_quote5.parse)(normalizedCommand, (key) => `$${key}`);
|
|
310522
310649
|
} catch {
|
|
310523
310650
|
parsed = command.trim().split(/\s+/);
|
|
310524
310651
|
}
|
|
@@ -310540,45 +310667,57 @@ function findUntrustedFlags(command, untrustedContext) {
|
|
|
310540
310667
|
const token2 = rawTokens[i3];
|
|
310541
310668
|
const lowerToken = token2.toLowerCase();
|
|
310542
310669
|
if (token2.startsWith("-")) {
|
|
310670
|
+
if (/^--?$/.test(token2)) {
|
|
310671
|
+
continue;
|
|
310672
|
+
}
|
|
310673
|
+
let rawFlagName = token2;
|
|
310543
310674
|
let flagToCheck = lowerToken;
|
|
310675
|
+
let rawValToCheck;
|
|
310544
310676
|
let valToCheck;
|
|
310545
310677
|
if (token2.includes("=")) {
|
|
310546
|
-
const eqIdx =
|
|
310678
|
+
const eqIdx = token2.indexOf("=");
|
|
310679
|
+
rawFlagName = token2.substring(0, eqIdx);
|
|
310547
310680
|
flagToCheck = lowerToken.substring(0, eqIdx);
|
|
310681
|
+
rawValToCheck = token2.substring(eqIdx + 1);
|
|
310548
310682
|
valToCheck = lowerToken.substring(eqIdx + 1);
|
|
310549
310683
|
}
|
|
310550
|
-
|
|
310684
|
+
const isSafeFlag = SAFE_SHORT_FLAGS.has(rawFlagName) || SAFE_LONG_FLAGS.has(flagToCheck);
|
|
310685
|
+
const isHighRiskFlag = HIGH_RISK_VALUE_FLAGS.has(rawFlagName) || rawFlagName.startsWith("--") && HIGH_RISK_VALUE_FLAGS.has(flagToCheck);
|
|
310686
|
+
const isShortFlag = rawFlagName.startsWith("-") && !rawFlagName.startsWith("--");
|
|
310687
|
+
const tokenToLookup = isShortFlag ? rawFlagName : lowerToken;
|
|
310688
|
+
const flagToLookup = isShortFlag ? rawFlagName : flagToCheck;
|
|
310689
|
+
if (!isSafeFlag && (untrustedContext.untrustedTokens.has(tokenToLookup) || untrustedContext.untrustedTokens.has(flagToLookup))) {
|
|
310551
310690
|
detected.add(token2);
|
|
310552
|
-
|
|
310691
|
+
if (token2.includes("=") || !isHighRiskFlag) {
|
|
310692
|
+
continue;
|
|
310693
|
+
}
|
|
310553
310694
|
}
|
|
310554
|
-
if (valToCheck &&
|
|
310555
|
-
|
|
310556
|
-
|
|
310695
|
+
if (valToCheck && rawValToCheck) {
|
|
310696
|
+
const isValUntrusted = untrustedContext.untrustedTokens.has(valToCheck) && (isHighRiskFlag || !isSafeFlag && isHighRiskPatternToken(rawValToCheck));
|
|
310697
|
+
const isHighRiskValSubstring = (!isSafeFlag || isHighRiskFlag) && isHighRiskPatternToken(rawValToCheck) && hasUntrustedSubstring(untrustedContext, valToCheck);
|
|
310698
|
+
if (isValUntrusted || isHighRiskValSubstring) {
|
|
310699
|
+
detected.add(token2);
|
|
310700
|
+
continue;
|
|
310701
|
+
}
|
|
310557
310702
|
}
|
|
310558
|
-
|
|
310559
|
-
|
|
310560
|
-
|
|
310561
|
-
|
|
310703
|
+
if (!token2.includes("=") && isHighRiskFlag) {
|
|
310704
|
+
const nextToken = rawTokens[i3 + 1];
|
|
310705
|
+
if (nextToken && !nextToken.startsWith("-") && !BARE_SHELL_VARIABLE_REGEX.test(nextToken) && !BENIGN_SUBCOMMAND_TOKENS.has(nextToken.toLowerCase()) && (untrustedContext.untrustedTokens.has(nextToken.toLowerCase()) || isHighRiskPatternToken(nextToken) && hasUntrustedSubstring(untrustedContext, nextToken))) {
|
|
310706
|
+
detected.add(token2);
|
|
310707
|
+
detected.add(nextToken);
|
|
310708
|
+
}
|
|
310562
310709
|
}
|
|
310563
310710
|
} else {
|
|
310564
|
-
if (token2.length <= 1) {
|
|
310711
|
+
if (token2.length <= 1 || BARE_SHELL_VARIABLE_REGEX.test(token2)) {
|
|
310565
310712
|
continue;
|
|
310566
310713
|
}
|
|
310567
|
-
|
|
310568
|
-
const isHighRiskPattern = token2.startsWith("http://") || token2.startsWith("https://") || token2.startsWith("/") || token2.startsWith("\\") || /^[a-zA-Z]:[\\/]/.test(token2);
|
|
310569
|
-
if (isSensitiveWord) {
|
|
310714
|
+
if (isHighRiskPatternToken(token2)) {
|
|
310570
310715
|
if (untrustedContext.untrustedTokens.has(lowerToken)) {
|
|
310571
310716
|
detected.add(token2);
|
|
310572
310717
|
continue;
|
|
310573
310718
|
}
|
|
310574
|
-
if (
|
|
310575
|
-
|
|
310576
|
-
for (const text of untrustedContext.untrustedTexts) {
|
|
310577
|
-
if (text.toLowerCase().includes(normalizedLowerToken)) {
|
|
310578
|
-
detected.add(token2);
|
|
310579
|
-
break;
|
|
310580
|
-
}
|
|
310581
|
-
}
|
|
310719
|
+
if (hasUntrustedSubstring(untrustedContext, lowerToken)) {
|
|
310720
|
+
detected.add(token2);
|
|
310582
310721
|
}
|
|
310583
310722
|
}
|
|
310584
310723
|
}
|
|
@@ -335229,6 +335368,9 @@ function scrubPart(part) {
|
|
|
335229
335368
|
if (part.functionResponse.id) {
|
|
335230
335369
|
scrubbedResp["id"] = part.functionResponse.id;
|
|
335231
335370
|
}
|
|
335371
|
+
if ("parts" in part.functionResponse && Array.isArray(part.functionResponse.parts)) {
|
|
335372
|
+
scrubbedResp["parts"] = part.functionResponse.parts.map(scrubPart);
|
|
335373
|
+
}
|
|
335232
335374
|
scrubbed["functionResponse"] = scrubbedResp;
|
|
335233
335375
|
}
|
|
335234
335376
|
if ("fileData" in part) {
|
|
@@ -335259,6 +335401,8 @@ var MID_STREAM_RETRY_OPTIONS = {
|
|
|
335259
335401
|
};
|
|
335260
335402
|
var SYNTHETIC_THOUGHT_SIGNATURE2 = "skip_thought_signature_validator";
|
|
335261
335403
|
var INTERRUPTED_RESPONSE_PLACEHOLDER = "[The previous response was interrupted before it completed.]";
|
|
335404
|
+
var INTERRUPTED_TOOL_RESPONSE_ERROR = "Response was lost or interrupted.";
|
|
335405
|
+
var CONTINUE_PROMPT_TEXT = "Please continue.";
|
|
335262
335406
|
function isIndexedPart(part) {
|
|
335263
335407
|
return "callIndex" in part;
|
|
335264
335408
|
}
|
|
@@ -335503,6 +335647,7 @@ var GeminiChat = class {
|
|
|
335503
335647
|
let userContent = createUserContent(message);
|
|
335504
335648
|
const isOriginalFunctionResponse = isFunctionResponse(userContent);
|
|
335505
335649
|
if (!isOriginalFunctionResponse) {
|
|
335650
|
+
this.closeUnansweredToolCallsTurn();
|
|
335506
335651
|
this.closeUnansweredToolResponseTurn();
|
|
335507
335652
|
}
|
|
335508
335653
|
const { model } = this.context.config.modelConfigService.getResolvedConfig(modelConfigKey);
|
|
@@ -335531,7 +335676,7 @@ var GeminiChat = class {
|
|
|
335531
335676
|
} else {
|
|
335532
335677
|
const history = this.agentHistory.get();
|
|
335533
335678
|
const lastTurn = history[history.length - 1];
|
|
335534
|
-
if (!lastTurn || partListUnionToString(lastTurn.content.parts || []) !== userMessageContent) {
|
|
335679
|
+
if (!lastTurn || lastTurn.content.role !== "user" || partListUnionToString(lastTurn.content.parts || []) !== userMessageContent) {
|
|
335535
335680
|
const id = this.chatRecordingService.recordMessage({
|
|
335536
335681
|
model,
|
|
335537
335682
|
type: "user",
|
|
@@ -335588,11 +335733,12 @@ var GeminiChat = class {
|
|
|
335588
335733
|
} else {
|
|
335589
335734
|
const history = this.agentHistory.get();
|
|
335590
335735
|
const lastTurn = history[history.length - 1];
|
|
335591
|
-
if (!lastTurn || partListUnionToString(lastTurn.content.parts || []) !== partListUnionToString(userContent.parts || [])) {
|
|
335736
|
+
if (!lastTurn || lastTurn.content.role !== "user" || partListUnionToString(lastTurn.content.parts || []) !== partListUnionToString(userContent.parts || [])) {
|
|
335592
335737
|
this.agentHistory.push({ id, content: userContent });
|
|
335593
335738
|
}
|
|
335594
335739
|
}
|
|
335595
335740
|
}
|
|
335741
|
+
this.replaceEmptyTrailingUserTurn();
|
|
335596
335742
|
const requestHistory = this.getHistoryTurns(true);
|
|
335597
335743
|
const streamWithRetries = async function* () {
|
|
335598
335744
|
let isSuccess = false;
|
|
@@ -335734,23 +335880,84 @@ var GeminiChat = class {
|
|
|
335734
335880
|
return streamWithRetries.call(this);
|
|
335735
335881
|
}
|
|
335736
335882
|
/**
|
|
335737
|
-
* Appends a
|
|
335738
|
-
*
|
|
335883
|
+
* Appends a dedicated synthetic user turn with matching functionResponse
|
|
335884
|
+
* parts when history ends with an unclosed model functionCall. The
|
|
335885
|
+
* subsequent user prompt is then recorded as a clean turn of its own (after
|
|
335886
|
+
* `closeUnansweredToolResponseTurn` adds the closing model turn).
|
|
335739
335887
|
*/
|
|
335740
|
-
|
|
335888
|
+
closeUnansweredToolCallsTurn() {
|
|
335741
335889
|
const turns = this.agentHistory.get();
|
|
335742
335890
|
const last2 = turns[turns.length - 1];
|
|
335743
|
-
if (last2?.content.role !== "
|
|
335891
|
+
if (last2?.content.role !== "model") {
|
|
335744
335892
|
return;
|
|
335745
335893
|
}
|
|
335894
|
+
const missingResponses = buildInterruptedToolResponseParts(
|
|
335895
|
+
last2.content.parts ?? []
|
|
335896
|
+
);
|
|
335897
|
+
if (missingResponses.length === 0) {
|
|
335898
|
+
return;
|
|
335899
|
+
}
|
|
335900
|
+
const id = this.chatRecordingService.recordSyntheticMessage(
|
|
335901
|
+
"user",
|
|
335902
|
+
missingResponses
|
|
335903
|
+
);
|
|
335746
335904
|
this.agentHistory.push({
|
|
335747
|
-
id
|
|
335748
|
-
content: {
|
|
335749
|
-
role: "model",
|
|
335750
|
-
parts: [{ text: INTERRUPTED_RESPONSE_PLACEHOLDER }]
|
|
335751
|
-
}
|
|
335905
|
+
id,
|
|
335906
|
+
content: { role: "user", parts: missingResponses }
|
|
335752
335907
|
});
|
|
335753
335908
|
}
|
|
335909
|
+
/**
|
|
335910
|
+
* Replaces the parts of a trailing user turn that carries no content (e.g.
|
|
335911
|
+
* only empty text parts) with a continuation prompt, keeping the in-memory
|
|
335912
|
+
* history and the session log in sync. Runs once per send so that the
|
|
335913
|
+
* persisted history never keeps an empty user turn between model turns.
|
|
335914
|
+
*/
|
|
335915
|
+
replaceEmptyTrailingUserTurn() {
|
|
335916
|
+
const turns = this.agentHistory.get();
|
|
335917
|
+
const last2 = turns[turns.length - 1];
|
|
335918
|
+
if (last2?.content.role !== "user" || hasNonEmptyParts(last2.content)) {
|
|
335919
|
+
return;
|
|
335920
|
+
}
|
|
335921
|
+
this.agentHistory.set([
|
|
335922
|
+
...turns.slice(0, -1),
|
|
335923
|
+
{
|
|
335924
|
+
id: last2.id,
|
|
335925
|
+
content: { ...last2.content, parts: [{ text: CONTINUE_PROMPT_TEXT }] }
|
|
335926
|
+
}
|
|
335927
|
+
]);
|
|
335928
|
+
this.chatRecordingService.updateMessagesFromHistory(
|
|
335929
|
+
this.agentHistory.get()
|
|
335930
|
+
);
|
|
335931
|
+
}
|
|
335932
|
+
/**
|
|
335933
|
+
* Appends a closing model turn when history ends with an unanswered tool
|
|
335934
|
+
* response, so the next user message stays a turn of its own.
|
|
335935
|
+
*/
|
|
335936
|
+
closeUnansweredToolResponseTurn() {
|
|
335937
|
+
const turns = this.agentHistory.get();
|
|
335938
|
+
let targetTurn = turns[turns.length - 1];
|
|
335939
|
+
let hadEmptyTrailingModelTurn = false;
|
|
335940
|
+
if (targetTurn?.content.role === "model" && (!targetTurn.content.parts || targetTurn.content.parts.length === 0)) {
|
|
335941
|
+
hadEmptyTrailingModelTurn = true;
|
|
335942
|
+
targetTurn = turns[turns.length - 2];
|
|
335943
|
+
}
|
|
335944
|
+
if (targetTurn?.content.role !== "user" || !targetTurn.content.parts?.some((part) => !!part.functionResponse)) {
|
|
335945
|
+
return;
|
|
335946
|
+
}
|
|
335947
|
+
if (hadEmptyTrailingModelTurn) {
|
|
335948
|
+
const lastTurn = turns[turns.length - 1];
|
|
335949
|
+
lastTurn.content.parts = [{ text: INTERRUPTED_RESPONSE_PLACEHOLDER }];
|
|
335950
|
+
this.chatRecordingService.updateMessagesFromHistory(turns);
|
|
335951
|
+
} else {
|
|
335952
|
+
this.agentHistory.push({
|
|
335953
|
+
id: randomUUID6(),
|
|
335954
|
+
content: {
|
|
335955
|
+
role: "model",
|
|
335956
|
+
parts: [{ text: INTERRUPTED_RESPONSE_PLACEHOLDER }]
|
|
335957
|
+
}
|
|
335958
|
+
});
|
|
335959
|
+
}
|
|
335960
|
+
}
|
|
335754
335961
|
extractBinaryInjections(parts2) {
|
|
335755
335962
|
const binaryParts = [];
|
|
335756
335963
|
if (parts2) {
|
|
@@ -335900,10 +336107,16 @@ var GeminiChat = class {
|
|
|
335900
336107
|
if (this.onModelChanged) {
|
|
335901
336108
|
this.tools = await this.onModelChanged(modelToUse);
|
|
335902
336109
|
}
|
|
336110
|
+
const normalizedContents = ensureTerminalUserTurn(contentsToUse);
|
|
336111
|
+
if (normalizedContents !== contentsToUse) {
|
|
336112
|
+
debugLogger.warn(
|
|
336113
|
+
"Final contents do not end with a valid user turn. Normalizing contents to satisfy Gemini API invariant."
|
|
336114
|
+
);
|
|
336115
|
+
}
|
|
335903
336116
|
lastModelToUse = modelToUse;
|
|
335904
336117
|
lastConfig = config2;
|
|
335905
|
-
lastContentsToUse =
|
|
335906
|
-
const finalContents = stripToolCallIdPrefixes(
|
|
336118
|
+
lastContentsToUse = normalizedContents;
|
|
336119
|
+
const finalContents = stripToolCallIdPrefixes(normalizedContents);
|
|
335907
336120
|
return this.context.config.getContentGenerator().generateContentStream(
|
|
335908
336121
|
{
|
|
335909
336122
|
model: modelToUse,
|
|
@@ -336017,6 +336230,29 @@ var GeminiChat = class {
|
|
|
336017
336230
|
}
|
|
336018
336231
|
ensureStableToolIds(this.agentHistory.get());
|
|
336019
336232
|
}
|
|
336233
|
+
/**
|
|
336234
|
+
* Removes the trailing model turn when it holds function calls that were
|
|
336235
|
+
* never answered (e.g. every call in the batch was declined). Earlier
|
|
336236
|
+
* completed tool rounds and the originating user prompt are kept, and the
|
|
336237
|
+
* durable IDs of the remaining turns are preserved.
|
|
336238
|
+
*
|
|
336239
|
+
* @returns true when a turn was removed.
|
|
336240
|
+
*/
|
|
336241
|
+
discardTrailingUnansweredToolCallTurn() {
|
|
336242
|
+
const turns = this.agentHistory.get();
|
|
336243
|
+
const last2 = turns[turns.length - 1];
|
|
336244
|
+
if (last2?.content.role !== "model" || !last2.content.parts?.some((part) => !!part.functionCall)) {
|
|
336245
|
+
return false;
|
|
336246
|
+
}
|
|
336247
|
+
this.agentHistory.rollback(turns.length - 1);
|
|
336248
|
+
this.lastPromptTokenCount = estimateTokenCountSync(
|
|
336249
|
+
this.agentHistory.flatMap((c4) => c4.content.parts || [])
|
|
336250
|
+
);
|
|
336251
|
+
this.chatRecordingService.updateMessagesFromHistory(
|
|
336252
|
+
this.agentHistory.get()
|
|
336253
|
+
);
|
|
336254
|
+
return true;
|
|
336255
|
+
}
|
|
336020
336256
|
setHistory(history) {
|
|
336021
336257
|
const wrappedHistory = history.map((item) => {
|
|
336022
336258
|
if ("id" in item && "content" in item) {
|
|
@@ -336422,8 +336658,43 @@ function isSchemaDepthError(errorMessage) {
|
|
|
336422
336658
|
function isInvalidArgumentError(errorMessage) {
|
|
336423
336659
|
return errorMessage.includes("Request contains an invalid argument");
|
|
336424
336660
|
}
|
|
336661
|
+
function isEmptyTextPart(part) {
|
|
336662
|
+
if (part.text !== "") {
|
|
336663
|
+
return false;
|
|
336664
|
+
}
|
|
336665
|
+
return !Object.keys(part).some(
|
|
336666
|
+
(key) => key !== "text" && key !== "thought" && key !== "callIndex"
|
|
336667
|
+
);
|
|
336668
|
+
}
|
|
336669
|
+
function hasNonEmptyParts(content) {
|
|
336670
|
+
return (content.parts ?? []).some((part) => !isEmptyTextPart(part));
|
|
336671
|
+
}
|
|
336672
|
+
function buildInterruptedToolResponseParts(parts2) {
|
|
336673
|
+
return parts2.filter((part) => !!part?.functionCall).map((part) => ({
|
|
336674
|
+
functionResponse: {
|
|
336675
|
+
name: part.functionCall.name?.trim() || "generic_tool",
|
|
336676
|
+
id: part.functionCall.id,
|
|
336677
|
+
response: { error: INTERRUPTED_TOOL_RESPONSE_ERROR }
|
|
336678
|
+
}
|
|
336679
|
+
}));
|
|
336680
|
+
}
|
|
336681
|
+
function ensureTerminalUserTurn(contents) {
|
|
336682
|
+
const last2 = contents.at(-1);
|
|
336683
|
+
if (last2?.role === "user" && hasNonEmptyParts(last2)) {
|
|
336684
|
+
return contents;
|
|
336685
|
+
}
|
|
336686
|
+
if (last2?.role === "user") {
|
|
336687
|
+
return [
|
|
336688
|
+
...contents.slice(0, -1),
|
|
336689
|
+
{ ...last2, parts: [{ text: CONTINUE_PROMPT_TEXT }] }
|
|
336690
|
+
];
|
|
336691
|
+
}
|
|
336692
|
+
const missingResponses = buildInterruptedToolResponseParts(last2?.parts ?? []);
|
|
336693
|
+
const parts2 = missingResponses.length > 0 ? missingResponses : [{ text: CONTINUE_PROMPT_TEXT }];
|
|
336694
|
+
return [...contents, { role: "user", parts: parts2 }];
|
|
336695
|
+
}
|
|
336425
336696
|
function stripToolCallIdPrefixes(contents) {
|
|
336426
|
-
|
|
336697
|
+
const stripped = contents.map((content) => {
|
|
336427
336698
|
const parts2 = (content.parts || []).map((part) => {
|
|
336428
336699
|
const newPart = { ...part };
|
|
336429
336700
|
if (newPart.functionCall) {
|
|
@@ -336431,8 +336702,7 @@ function stripToolCallIdPrefixes(contents) {
|
|
|
336431
336702
|
const name3 = fc.name?.trim() || "generic_tool";
|
|
336432
336703
|
if (fc.id && fc.id.startsWith(`${name3}__`)) {
|
|
336433
336704
|
newPart.functionCall = {
|
|
336434
|
-
|
|
336435
|
-
args: fc.args,
|
|
336705
|
+
...fc,
|
|
336436
336706
|
id: fc.id.substring(name3.length + 2)
|
|
336437
336707
|
};
|
|
336438
336708
|
}
|
|
@@ -336442,8 +336712,9 @@ function stripToolCallIdPrefixes(contents) {
|
|
|
336442
336712
|
const name3 = fr.name?.trim() || "generic_tool";
|
|
336443
336713
|
if (fr.id && fr.id.startsWith(`${name3}__`)) {
|
|
336444
336714
|
newPart.functionResponse = {
|
|
336445
|
-
|
|
336446
|
-
|
|
336715
|
+
// History parts are plain JSON objects, not class instances.
|
|
336716
|
+
// eslint-disable-next-line @typescript-eslint/no-misused-spread
|
|
336717
|
+
...fr,
|
|
336447
336718
|
id: fr.id.substring(name3.length + 2)
|
|
336448
336719
|
};
|
|
336449
336720
|
}
|
|
@@ -336455,20 +336726,30 @@ function stripToolCallIdPrefixes(contents) {
|
|
|
336455
336726
|
delete newPart.text;
|
|
336456
336727
|
}
|
|
336457
336728
|
return newPart;
|
|
336458
|
-
}).filter((part) =>
|
|
336459
|
-
const hasOtherKeys = Object.keys(part).some(
|
|
336460
|
-
(key) => key !== "text" && key !== "thought" && key !== "callIndex"
|
|
336461
|
-
);
|
|
336462
|
-
if (part.text !== void 0 && part.text === "" && !hasOtherKeys) {
|
|
336463
|
-
return false;
|
|
336464
|
-
}
|
|
336465
|
-
return true;
|
|
336466
|
-
});
|
|
336729
|
+
}).filter((part) => !isEmptyTextPart(part));
|
|
336467
336730
|
return {
|
|
336468
336731
|
...content,
|
|
336469
336732
|
parts: parts2
|
|
336470
336733
|
};
|
|
336471
|
-
});
|
|
336734
|
+
}).filter((content) => content.parts.length > 0);
|
|
336735
|
+
return coalesceConsecutiveContents(stripped);
|
|
336736
|
+
}
|
|
336737
|
+
function coalesceConsecutiveContents(contents) {
|
|
336738
|
+
const result2 = [];
|
|
336739
|
+
for (const item of contents) {
|
|
336740
|
+
const lastIdx = result2.length - 1;
|
|
336741
|
+
const last2 = result2[lastIdx];
|
|
336742
|
+
if (last2 && last2.role && last2.role === item.role) {
|
|
336743
|
+
const hasParts = last2.parts || item.parts;
|
|
336744
|
+
result2[lastIdx] = {
|
|
336745
|
+
...last2,
|
|
336746
|
+
parts: hasParts ? [...last2.parts || [], ...item.parts || []] : void 0
|
|
336747
|
+
};
|
|
336748
|
+
} else {
|
|
336749
|
+
result2.push({ ...item });
|
|
336750
|
+
}
|
|
336751
|
+
}
|
|
336752
|
+
return result2;
|
|
336472
336753
|
}
|
|
336473
336754
|
function coalesceConsecutiveRoles(history) {
|
|
336474
336755
|
const result2 = [];
|
|
@@ -344038,7 +344319,13 @@ var OAuthUtils = class {
|
|
|
344038
344319
|
issuer: metadata2.issuer,
|
|
344039
344320
|
tokenUrl: metadata2.token_endpoint,
|
|
344040
344321
|
scopes: metadata2.scopes_supported || [],
|
|
344041
|
-
registrationUrl: metadata2.registration_endpoint
|
|
344322
|
+
registrationUrl: metadata2.registration_endpoint,
|
|
344323
|
+
// RFC 9207 Section 3: the flag defaults to false when omitted. Discovered
|
|
344324
|
+
// configurations therefore always carry an explicit boolean, which lets
|
|
344325
|
+
// the callback policy distinguish them from an explicitly configured issuer.
|
|
344326
|
+
// Only a literal boolean `true` enables the flag, so loosely typed values
|
|
344327
|
+
// returned by some servers (e.g. "false" or "0") are not coerced to true.
|
|
344328
|
+
authorizationResponseIssParameterSupported: metadata2.authorization_response_iss_parameter_supported === true
|
|
344042
344329
|
};
|
|
344043
344330
|
}
|
|
344044
344331
|
/**
|
|
@@ -344439,7 +344726,7 @@ var A2AAuthProviderFactory = class _A2AAuthProviderFactory {
|
|
|
344439
344726
|
return provider;
|
|
344440
344727
|
}
|
|
344441
344728
|
case "oauth2": {
|
|
344442
|
-
const { OAuth2AuthProvider } = await import("./oauth2-provider-
|
|
344729
|
+
const { OAuth2AuthProvider } = await import("./oauth2-provider-65ILSORU.js");
|
|
344443
344730
|
const provider = new OAuth2AuthProvider(
|
|
344444
344731
|
authConfig,
|
|
344445
344732
|
options.agentName ?? "unknown",
|
|
@@ -351215,6 +351502,21 @@ var GeminiClient = class {
|
|
|
351215
351502
|
this.updateTelemetryTokenCount();
|
|
351216
351503
|
this.forceFullIdeContext = true;
|
|
351217
351504
|
}
|
|
351505
|
+
/**
|
|
351506
|
+
* Removes the trailing model turn when it only holds unanswered function
|
|
351507
|
+
* calls. See {@link GeminiChat.discardTrailingUnansweredToolCallTurn}.
|
|
351508
|
+
* Returns false without side effects when the chat is not initialized.
|
|
351509
|
+
*/
|
|
351510
|
+
discardTrailingUnansweredToolCallTurn() {
|
|
351511
|
+
if (!this.isInitialized()) {
|
|
351512
|
+
return false;
|
|
351513
|
+
}
|
|
351514
|
+
const removed = this.getChat().discardTrailingUnansweredToolCallTurn();
|
|
351515
|
+
if (removed) {
|
|
351516
|
+
this.updateTelemetryTokenCount();
|
|
351517
|
+
}
|
|
351518
|
+
return removed;
|
|
351519
|
+
}
|
|
351218
351520
|
lastUsedModelId;
|
|
351219
351521
|
async setTools(modelId) {
|
|
351220
351522
|
if (!this.chat) {
|
|
@@ -368993,7 +369295,7 @@ var PolicyEngine = class {
|
|
|
368993
369295
|
}
|
|
368994
369296
|
return decision;
|
|
368995
369297
|
}
|
|
368996
|
-
async checkShellCommand(toolName, command, ruleDecision, serverName, dir_path, allowRedirection, rule, toolAnnotations, subagent) {
|
|
369298
|
+
async checkShellCommand(toolName, command, ruleDecision, serverName, dir_path, allowRedirection, rule, toolAnnotations, subagent, hasTopLevelHeuristicDowngrade = false) {
|
|
368997
369299
|
if (!command) {
|
|
368998
369300
|
return {
|
|
368999
369301
|
decision: ruleDecision,
|
|
@@ -369035,7 +369337,12 @@ var PolicyEngine = class {
|
|
|
369035
369337
|
}
|
|
369036
369338
|
let aggregateDecision = ruleDecision;
|
|
369037
369339
|
let responsibleRule = rule && ruleDecision === rule.decision ? rule : void 0;
|
|
369038
|
-
|
|
369340
|
+
const hasTopLevelRedirectionDowngrade = this.shouldDowngradeForRedirection(
|
|
369341
|
+
command,
|
|
369342
|
+
allowRedirection,
|
|
369343
|
+
rule
|
|
369344
|
+
);
|
|
369345
|
+
if (hasTopLevelRedirectionDowngrade) {
|
|
369039
369346
|
if (aggregateDecision === "allow" /* ALLOW */) {
|
|
369040
369347
|
debugLogger.debug(
|
|
369041
369348
|
`[PolicyEngine.check] Downgrading ALLOW to ASK_USER for redirected command: ${command}`
|
|
@@ -369044,6 +369351,9 @@ var PolicyEngine = class {
|
|
|
369044
369351
|
responsibleRule = void 0;
|
|
369045
369352
|
}
|
|
369046
369353
|
}
|
|
369354
|
+
let evaluatedSubCommands = 0;
|
|
369355
|
+
let allSubCommandsExplicitlyAllowed = true;
|
|
369356
|
+
let lastAllowedSubRule;
|
|
369047
369357
|
for (const detail of subCommands) {
|
|
369048
369358
|
if (REDIRECTION_NAMES.has(detail.name)) {
|
|
369049
369359
|
continue;
|
|
@@ -369052,6 +369362,7 @@ var PolicyEngine = class {
|
|
|
369052
369362
|
const isAtomic = subCmd === command || detail.startIndex === 0 && detail.text.length === command.length;
|
|
369053
369363
|
const stripped = stripShellWrapper(subCmd);
|
|
369054
369364
|
if (stripped !== subCmd) {
|
|
369365
|
+
evaluatedSubCommands++;
|
|
369055
369366
|
const wrapperResult = await this.check(
|
|
369056
369367
|
{ name: toolName, args: { command: stripped, dir_path } },
|
|
369057
369368
|
serverName,
|
|
@@ -369062,15 +369373,21 @@ var PolicyEngine = class {
|
|
|
369062
369373
|
if (wrapperResult.decision === "deny" /* DENY */)
|
|
369063
369374
|
return wrapperResult;
|
|
369064
369375
|
if (wrapperResult.decision === "ask_user" /* ASK_USER */) {
|
|
369376
|
+
allSubCommandsExplicitlyAllowed = false;
|
|
369065
369377
|
if (aggregateDecision === "allow" /* ALLOW */) {
|
|
369066
369378
|
responsibleRule = wrapperResult.rule;
|
|
369067
369379
|
} else {
|
|
369068
369380
|
responsibleRule ??= wrapperResult.rule;
|
|
369069
369381
|
}
|
|
369070
369382
|
aggregateDecision = "ask_user" /* ASK_USER */;
|
|
369383
|
+
} else if (wrapperResult.decision === "allow" /* ALLOW */ && wrapperResult.rule?.decision === "allow" /* ALLOW */ && Boolean(wrapperResult.rule?.argsPattern)) {
|
|
369384
|
+
lastAllowedSubRule = wrapperResult.rule;
|
|
369385
|
+
} else {
|
|
369386
|
+
allSubCommandsExplicitlyAllowed = false;
|
|
369071
369387
|
}
|
|
369072
369388
|
}
|
|
369073
369389
|
if (!isAtomic) {
|
|
369390
|
+
evaluatedSubCommands++;
|
|
369074
369391
|
const subResult = await this.check(
|
|
369075
369392
|
{ name: toolName, args: { command: subCmd, dir_path } },
|
|
369076
369393
|
serverName,
|
|
@@ -369080,6 +369397,7 @@ var PolicyEngine = class {
|
|
|
369080
369397
|
);
|
|
369081
369398
|
if (subResult.decision === "deny" /* DENY */) return subResult;
|
|
369082
369399
|
if (subResult.decision === "ask_user" /* ASK_USER */) {
|
|
369400
|
+
allSubCommandsExplicitlyAllowed = false;
|
|
369083
369401
|
if (aggregateDecision === "allow" /* ALLOW */) {
|
|
369084
369402
|
responsibleRule = subResult.rule;
|
|
369085
369403
|
} else {
|
|
@@ -369092,13 +369410,31 @@ var PolicyEngine = class {
|
|
|
369092
369410
|
subResult.rule?.allowRedirection ?? allowRedirection,
|
|
369093
369411
|
subResult.rule
|
|
369094
369412
|
)) {
|
|
369413
|
+
allSubCommandsExplicitlyAllowed = false;
|
|
369095
369414
|
if (aggregateDecision === "allow" /* ALLOW */) {
|
|
369096
369415
|
aggregateDecision = "ask_user" /* ASK_USER */;
|
|
369097
369416
|
responsibleRule = void 0;
|
|
369098
369417
|
}
|
|
369418
|
+
} else if (subResult.decision === "allow" /* ALLOW */ && subResult.rule?.decision === "allow" /* ALLOW */ && Boolean(subResult.rule?.argsPattern)) {
|
|
369419
|
+
lastAllowedSubRule = subResult.rule;
|
|
369420
|
+
} else {
|
|
369421
|
+
allSubCommandsExplicitlyAllowed = false;
|
|
369099
369422
|
}
|
|
369423
|
+
} else if (stripped === subCmd) {
|
|
369424
|
+
allSubCommandsExplicitlyAllowed = false;
|
|
369100
369425
|
}
|
|
369101
369426
|
}
|
|
369427
|
+
const workspace = typeof this.sandboxManager.getWorkspace === "function" ? this.sandboxManager.getWorkspace() : process.cwd();
|
|
369428
|
+
const effectiveCwd = dir_path ? path83.resolve(workspace, dir_path) : workspace;
|
|
369429
|
+
const isOutsideWorkspace = effectiveCwd !== workspace && !isSubpath(workspace, effectiveCwd) && this.approvalMode !== "yolo" /* YOLO */;
|
|
369430
|
+
const parsedObjArgs = (0, import_shell_quote7.parse)(command);
|
|
369431
|
+
const parsedArgs = parsedObjArgs.map(extractStringFromParseEntry);
|
|
369432
|
+
const isUntrustedGit = containsGitCommand(parsedArgs) && !this.isTrustedFolder();
|
|
369433
|
+
const isDangerous = this.approvalMode !== "yolo" /* YOLO */ && this.sandboxManager.isDangerousCommand(parsedArgs, effectiveCwd);
|
|
369434
|
+
if (aggregateDecision === "ask_user" /* ASK_USER */ && !rule?.argsPattern && !hasTopLevelRedirectionDowngrade && !hasTopLevelHeuristicDowngrade && !isOutsideWorkspace && !isUntrustedGit && !isDangerous && evaluatedSubCommands > 0 && allSubCommandsExplicitlyAllowed) {
|
|
369435
|
+
aggregateDecision = "allow" /* ALLOW */;
|
|
369436
|
+
responsibleRule = lastAllowedSubRule;
|
|
369437
|
+
}
|
|
369102
369438
|
return {
|
|
369103
369439
|
decision: aggregateDecision,
|
|
369104
369440
|
rule: aggregateDecision === ruleDecision ? rule : responsibleRule
|
|
@@ -369171,12 +369507,17 @@ var PolicyEngine = class {
|
|
|
369171
369507
|
`[PolicyEngine.check] MATCHED rule: toolName=${rule.toolName}, decision=${rule.decision}, priority=${rule.priority}, argsPattern=${rule.argsPattern?.source || "none"}`
|
|
369172
369508
|
);
|
|
369173
369509
|
let ruleDecision = rule.decision;
|
|
369510
|
+
let hasTopLevelHeuristicDowngrade = false;
|
|
369174
369511
|
if (!skipHeuristics && isShellCommand && command && !("commandPrefix" in rule) && !rule.argsPattern) {
|
|
369512
|
+
const prevDecision = ruleDecision;
|
|
369175
369513
|
ruleDecision = await this.applyShellHeuristics(
|
|
369176
369514
|
command,
|
|
369177
369515
|
ruleDecision,
|
|
369178
369516
|
shellDirPath
|
|
369179
369517
|
);
|
|
369518
|
+
if (prevDecision === "allow" /* ALLOW */ && ruleDecision === "ask_user" /* ASK_USER */) {
|
|
369519
|
+
hasTopLevelHeuristicDowngrade = true;
|
|
369520
|
+
}
|
|
369180
369521
|
}
|
|
369181
369522
|
if (isShellCommand && toolName) {
|
|
369182
369523
|
const shellResult = await this.checkShellCommand(
|
|
@@ -369188,7 +369529,8 @@ var PolicyEngine = class {
|
|
|
369188
369529
|
rule.allowRedirection,
|
|
369189
369530
|
rule,
|
|
369190
369531
|
toolAnnotations,
|
|
369191
|
-
subagent
|
|
369532
|
+
subagent,
|
|
369533
|
+
hasTopLevelHeuristicDowngrade
|
|
369192
369534
|
);
|
|
369193
369535
|
decision = shellResult.decision;
|
|
369194
369536
|
matchedRule = shellResult.rule;
|
|
@@ -369212,12 +369554,17 @@ var PolicyEngine = class {
|
|
|
369212
369554
|
);
|
|
369213
369555
|
if (toolName && SHELL_TOOL_NAMES.includes(toolName)) {
|
|
369214
369556
|
let heuristicDecision = this.defaultDecision;
|
|
369557
|
+
let hasTopLevelHeuristicDowngrade = false;
|
|
369215
369558
|
if (!skipHeuristics && command) {
|
|
369559
|
+
const prevDecision = heuristicDecision;
|
|
369216
369560
|
heuristicDecision = await this.applyShellHeuristics(
|
|
369217
369561
|
command,
|
|
369218
369562
|
heuristicDecision,
|
|
369219
369563
|
shellDirPath
|
|
369220
369564
|
);
|
|
369565
|
+
if (prevDecision === "allow" /* ALLOW */ && heuristicDecision === "ask_user" /* ASK_USER */) {
|
|
369566
|
+
hasTopLevelHeuristicDowngrade = true;
|
|
369567
|
+
}
|
|
369221
369568
|
}
|
|
369222
369569
|
const shellResult = await this.checkShellCommand(
|
|
369223
369570
|
toolName,
|
|
@@ -369228,7 +369575,8 @@ var PolicyEngine = class {
|
|
|
369228
369575
|
false,
|
|
369229
369576
|
void 0,
|
|
369230
369577
|
toolAnnotations,
|
|
369231
|
-
subagent
|
|
369578
|
+
subagent,
|
|
369579
|
+
hasTopLevelHeuristicDowngrade
|
|
369232
369580
|
);
|
|
369233
369581
|
decision = shellResult.decision;
|
|
369234
369582
|
matchedRule = shellResult.rule;
|
|
@@ -375428,7 +375776,7 @@ function areIssuersEqual(issuerA, issuerB) {
|
|
|
375428
375776
|
}
|
|
375429
375777
|
return normA === normB;
|
|
375430
375778
|
}
|
|
375431
|
-
function startCallbackServer(expectedState, port, expectedIssuer) {
|
|
375779
|
+
function startCallbackServer(expectedState, port, expectedIssuer, requireIssInResponse) {
|
|
375432
375780
|
let portResolve;
|
|
375433
375781
|
let portReject;
|
|
375434
375782
|
const portPromise = new Promise((resolve29, reject) => {
|
|
@@ -375488,9 +375836,10 @@ function startCallbackServer(expectedState, port, expectedIssuer) {
|
|
|
375488
375836
|
return;
|
|
375489
375837
|
}
|
|
375490
375838
|
if (expectedIssuer) {
|
|
375491
|
-
|
|
375839
|
+
const requireIss = requireIssInResponse ?? true;
|
|
375840
|
+
if (requireIss && !iss) {
|
|
375492
375841
|
debugLogger.error(
|
|
375493
|
-
'OAuth callback rejected: Missing required "iss" parameter
|
|
375842
|
+
'OAuth callback rejected: Missing required "iss" parameter for the expected authorization server (RFC 9207).'
|
|
375494
375843
|
);
|
|
375495
375844
|
res.writeHead(400, { "Content-Type": "text/html" });
|
|
375496
375845
|
res.end(`
|
|
@@ -375510,7 +375859,7 @@ function startCallbackServer(expectedState, port, expectedIssuer) {
|
|
|
375510
375859
|
);
|
|
375511
375860
|
return;
|
|
375512
375861
|
}
|
|
375513
|
-
if (!areIssuersEqual(iss, expectedIssuer)) {
|
|
375862
|
+
if (iss && !areIssuersEqual(iss, expectedIssuer)) {
|
|
375514
375863
|
debugLogger.error(
|
|
375515
375864
|
"OAuth callback rejected: Issuer mismatch between authorization response and expected authorization server. Possible IdP mix-up attack (RFC 9207)."
|
|
375516
375865
|
);
|
|
@@ -375532,9 +375881,11 @@ function startCallbackServer(expectedState, port, expectedIssuer) {
|
|
|
375532
375881
|
);
|
|
375533
375882
|
return;
|
|
375534
375883
|
}
|
|
375535
|
-
|
|
375536
|
-
|
|
375537
|
-
|
|
375884
|
+
if (iss) {
|
|
375885
|
+
debugLogger.debug(
|
|
375886
|
+
"\u2713 OAuth callback issuer validated successfully."
|
|
375887
|
+
);
|
|
375888
|
+
}
|
|
375538
375889
|
} else if (iss) {
|
|
375539
375890
|
debugLogger.debug(
|
|
375540
375891
|
'OAuth callback received "iss" parameter (no expected issuer was configured).'
|
|
@@ -375980,6 +376331,7 @@ var MCPOAuthProvider = class {
|
|
|
375980
376331
|
issuer: discoveredConfig.issuer,
|
|
375981
376332
|
tokenUrl: discoveredConfig.tokenUrl,
|
|
375982
376333
|
scopes: config2.scopes || discoveredConfig.scopes || [],
|
|
376334
|
+
authorizationResponseIssParameterSupported: config2.authorizationResponseIssParameterSupported ?? discoveredConfig.authorizationResponseIssParameterSupported,
|
|
375983
376335
|
// Preserve existing client credentials
|
|
375984
376336
|
clientId: config2.clientId,
|
|
375985
376337
|
clientSecret: config2.clientSecret
|
|
@@ -376005,6 +376357,7 @@ var MCPOAuthProvider = class {
|
|
|
376005
376357
|
issuer: discoveredConfig.issuer,
|
|
376006
376358
|
scopes: config2.scopes || discoveredConfig.scopes || [],
|
|
376007
376359
|
registrationUrl: discoveredConfig.registrationUrl,
|
|
376360
|
+
authorizationResponseIssParameterSupported: config2.authorizationResponseIssParameterSupported ?? discoveredConfig.authorizationResponseIssParameterSupported,
|
|
376008
376361
|
// Preserve existing client credentials
|
|
376009
376362
|
clientId: config2.clientId,
|
|
376010
376363
|
clientSecret: config2.clientSecret
|
|
@@ -376021,10 +376374,12 @@ var MCPOAuthProvider = class {
|
|
|
376021
376374
|
debugLogger.debug(
|
|
376022
376375
|
`Starting callback server for "${serverName}" (expected issuer: ${config2.issuer || "none"})...`
|
|
376023
376376
|
);
|
|
376377
|
+
const requireIssInResponse = config2.authorizationResponseIssParameterSupported ?? Boolean(config2.issuer);
|
|
376024
376378
|
const callbackServer = startCallbackServer(
|
|
376025
376379
|
pkceParams.state,
|
|
376026
376380
|
preferredPort,
|
|
376027
|
-
config2.issuer
|
|
376381
|
+
config2.issuer,
|
|
376382
|
+
requireIssInResponse
|
|
376028
376383
|
);
|
|
376029
376384
|
const redirectPort = await callbackServer.port;
|
|
376030
376385
|
debugLogger.debug(`Callback server listening on port ${redirectPort}`);
|
|
@@ -376980,7 +377335,8 @@ async function handleAutomaticOAuth(mcpServerName, mcpServerConfig, wwwAuthentic
|
|
|
376980
377335
|
authorizationUrl: oauthConfig.authorizationUrl,
|
|
376981
377336
|
issuer: oauthConfig.issuer,
|
|
376982
377337
|
tokenUrl: oauthConfig.tokenUrl,
|
|
376983
|
-
scopes: oauthConfig.scopes || []
|
|
377338
|
+
scopes: oauthConfig.scopes || [],
|
|
377339
|
+
authorizationResponseIssParameterSupported: mcpServerConfig.oauth?.authorizationResponseIssParameterSupported ?? oauthConfig.authorizationResponseIssParameterSupported
|
|
376984
377340
|
};
|
|
376985
377341
|
debugLogger.log(
|
|
376986
377342
|
`Starting OAuth authentication for server '${mcpServerName}'...`
|
|
@@ -377714,7 +378070,8 @@ async function connectToMcpServer(clientVersion, mcpServerName, mcpServerConfig,
|
|
|
377714
378070
|
authorizationUrl: oauthConfig.authorizationUrl,
|
|
377715
378071
|
issuer: oauthConfig.issuer,
|
|
377716
378072
|
tokenUrl: oauthConfig.tokenUrl,
|
|
377717
|
-
scopes: oauthConfig.scopes || []
|
|
378073
|
+
scopes: oauthConfig.scopes || [],
|
|
378074
|
+
authorizationResponseIssParameterSupported: mcpServerConfig.oauth?.authorizationResponseIssParameterSupported ?? oauthConfig.authorizationResponseIssParameterSupported
|
|
377718
378075
|
};
|
|
377719
378076
|
const authServerUrl = mcpServerConfig.httpUrl || mcpServerConfig.url;
|
|
377720
378077
|
debugLogger.log(
|
|
@@ -407214,6 +407571,8 @@ export {
|
|
|
407214
407571
|
StreamEventType,
|
|
407215
407572
|
SYNTHETIC_THOUGHT_SIGNATURE2 as SYNTHETIC_THOUGHT_SIGNATURE,
|
|
407216
407573
|
INTERRUPTED_RESPONSE_PLACEHOLDER,
|
|
407574
|
+
INTERRUPTED_TOOL_RESPONSE_ERROR,
|
|
407575
|
+
CONTINUE_PROMPT_TEXT,
|
|
407217
407576
|
isValidNonThoughtTextPart,
|
|
407218
407577
|
THINKING_ONLY_NUDGE_MESSAGE,
|
|
407219
407578
|
NO_RESPONSE_TEXT_NUDGE_MESSAGE,
|
|
@@ -407224,7 +407583,10 @@ export {
|
|
|
407224
407583
|
GeminiChat,
|
|
407225
407584
|
isSchemaDepthError,
|
|
407226
407585
|
isInvalidArgumentError,
|
|
407586
|
+
buildInterruptedToolResponseParts,
|
|
407587
|
+
ensureTerminalUserTurn,
|
|
407227
407588
|
stripToolCallIdPrefixes,
|
|
407589
|
+
coalesceConsecutiveContents,
|
|
407228
407590
|
coalesceConsecutiveRoles,
|
|
407229
407591
|
stripThoughts2 as stripThoughts,
|
|
407230
407592
|
populateToolDisplay,
|