@google/gemini-cli 0.42.0-preview.2 → 0.43.0-preview.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-FIIOJPLW.js → chunk-43AGRA7S.js} +3 -3
- package/bundle/{chunk-M6ZQAQKH.js → chunk-46T44JOY.js} +1 -1
- package/bundle/{chunk-OFOKTVUH.js → chunk-4TLQKGTR.js} +1 -1
- package/bundle/{chunk-4NXNVHPO.js → chunk-6XOSIMPZ.js} +8 -9
- package/bundle/{chunk-AAU5XCLJ.js → chunk-HQXINMBL.js} +2 -2
- package/bundle/{chunk-QM234EIA.js → chunk-JENIU3E3.js} +1 -1
- package/bundle/{chunk-R7BHIYZD.js → chunk-LBQFRHYD.js} +1 -1
- package/bundle/{chunk-WLPWIJ3Y.js → chunk-LFGJVOVZ.js} +486 -381
- package/bundle/{chunk-DEKZKOVU.js → chunk-MRHFLHPJ.js} +2 -2
- package/bundle/{chunk-ODIOD5TJ.js → chunk-MXKXLNQD.js} +3 -3
- package/bundle/{chunk-ECNYAST2.js → chunk-N6QYTC2T.js} +5417 -5376
- package/bundle/{chunk-WOGMVEEF.js → chunk-NBRZ4A3S.js} +2170 -791
- package/bundle/{chunk-Q24MYLMP.js → chunk-P4UQCQUB.js} +3 -3
- package/bundle/{chunk-S3WIE72K.js → chunk-PGJUNQPO.js} +34 -16
- package/bundle/{chunk-THNM4JU6.js → chunk-PSWUV2OO.js} +3 -3
- package/bundle/{chunk-6QBZKEWW.js → chunk-PYLHDAUK.js} +3 -3
- package/bundle/{chunk-2KRAWFEQ.js → chunk-Q23X5R4A.js} +486 -381
- package/bundle/{chunk-SJ6AOVZF.js → chunk-QYUN3J2L.js} +533 -441
- package/bundle/{chunk-77HSANAH.js → chunk-SAISHGWW.js} +1907 -716
- package/bundle/{chunk-I6IY72IP.js → chunk-SYD5SJFT.js} +38 -23
- package/bundle/{chunk-JW36FWGZ.js → chunk-T3SUXLQQ.js} +2 -2
- package/bundle/{chunk-BLNG7CSO.js → chunk-UIG2IVPJ.js} +34 -16
- package/bundle/{chunk-JEW7ZIWE.js → chunk-UJ26GAE5.js} +5326 -5290
- package/bundle/{chunk-E54WEGH3.js → chunk-UNAVBUTP.js} +14729 -7452
- package/bundle/{chunk-LYMYMKWM.js → chunk-WQOLTO3C.js} +1 -1
- package/bundle/{chunk-WFKT4UTI.js → chunk-X26T73X6.js} +3 -3
- package/bundle/{cleanup-5FPOUEHR.js → cleanup-EIZJH2E3.js} +3 -3
- package/bundle/{cleanup-G7DNOS4V.js → cleanup-MI76P55B.js} +3 -3
- package/bundle/{cleanup-GZM5KIZA.js → cleanup-NZBQYB7U.js} +3 -3
- package/bundle/{core-IYSSLWMM.js → core-ERSGIOMQ.js} +30 -2
- package/bundle/{dist-D7FZVGG3.js → core-T2TBFAYG.js} +30 -2
- package/bundle/{devtoolsService-UADEEKOH.js → devtoolsService-7KZDSYEF.js} +3 -3
- package/bundle/{devtoolsService-3XOQOECV.js → devtoolsService-FYTOIC37.js} +3 -3
- package/bundle/{devtoolsService-7ZN7CSSO.js → devtoolsService-LV5NJ2BT.js} +4 -5
- package/bundle/{dist-GF2RNVWZ.js → dist-ETX67B7P.js} +30 -2
- package/bundle/docs/changelogs/index.md +14 -0
- package/bundle/docs/changelogs/latest.md +108 -166
- package/bundle/docs/changelogs/preview.md +227 -103
- package/bundle/docs/cli/auto-memory.md +60 -38
- package/bundle/docs/cli/settings.md +1 -1
- package/bundle/docs/cli/tutorials/memory-management.md +1 -1
- package/bundle/docs/extensions/releasing.md +58 -24
- package/bundle/docs/reference/configuration.md +14 -1
- package/bundle/docs/reference/keyboard-shortcuts.md +23 -0
- package/bundle/{gemini-IRKIMLB4.js → gemini-IVKBXHDT.js} +160 -60
- package/bundle/{gemini-MWN2MSYV.js → gemini-JKWQQTKP.js} +160 -60
- package/bundle/{gemini-IMX43TZ4.js → gemini-Z77GAAR6.js} +331 -245
- package/bundle/gemini.js +8 -8
- package/bundle/{interactiveCli-SAMKYHUU.js → interactiveCli-36WZS6KT.js} +1704 -1457
- package/bundle/{interactiveCli-752P4PTI.js → interactiveCli-BQ36B66Z.js} +1703 -1457
- package/bundle/{interactiveCli-VX6GBWOV.js → interactiveCli-SME5QTEN.js} +1967 -1739
- package/bundle/{liteRtServerManager-CDLVKT7N.js → liteRtServerManager-2QD4R3A3.js} +5 -5
- package/bundle/{liteRtServerManager-FPYU5KEK.js → liteRtServerManager-ISYDOBNC.js} +5 -5
- package/bundle/{liteRtServerManager-OWPZ35U6.js → liteRtServerManager-N6OMT6W5.js} +5 -5
- package/bundle/{memoryDiscovery-FB7MMKTA.js → memoryDiscovery-LLSKN6HL.js} +1 -1
- package/bundle/{memoryDiscovery-KSYZVCWF.js → memoryDiscovery-SJ7P6RCN.js} +1 -1
- package/bundle/node_modules/@google/gemini-cli-devtools/package.json +1 -1
- package/bundle/{oauth2-provider-446FDCUW.js → oauth2-provider-DOSIH6VE.js} +2 -2
- package/bundle/{oauth2-provider-RQNNLGWV.js → oauth2-provider-TZF6EZRX.js} +2 -2
- package/bundle/{oauth2-provider-6W4IY3LC.js → oauth2-provider-VFOABWBW.js} +73 -39
- package/bundle/{start-6U3XBAVH.js → start-3GPIRK3E.js} +7 -7
- package/bundle/{start-KUNHDGRA.js → start-6NONW677.js} +7 -7
- package/bundle/{start-TTLMBKNX.js → start-M6MUPEJS.js} +7 -7
- package/package.json +1 -1
- package/bundle/chunk-76KOJPMV.js +0 -391
- package/bundle/chunk-LHVIO4J4.js +0 -81544
- package/bundle/chunk-OP6THN3K.js +0 -118
- package/bundle/chunk-RO2XVFEU.js +0 -512
- package/bundle/chunk-WRDVEMWE.js +0 -1571
- package/bundle/chunk-YDC4M26X.js +0 -156
- package/bundle/chunk-ZDP2ZWKG.js +0 -17230
- package/bundle/chunk-ZFOGBX2H.js +0 -356008
- package/bundle/cleanup-J6AUEKWI.js +0 -33
- package/bundle/devtoolsService-KTUMQHXG.js +0 -857
- package/bundle/dist-HBMVDPXB.js +0 -2096
- package/bundle/gemini-SYFUC6XO.js +0 -16256
- package/bundle/interactiveCli-37SKHAKX.js +0 -34505
- package/bundle/liteRtServerManager-OWTQEYE6.js +0 -66
- package/bundle/oauth2-provider-TITPL3DN.js +0 -237
- package/bundle/start-TZXEJLTH.js +0 -19
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
# Release extensions
|
|
2
2
|
|
|
3
3
|
Release Gemini CLI extensions to your users through a Git repository or GitHub
|
|
4
|
-
Releases.
|
|
4
|
+
Releases. This guide explains how to share your work, list it in the gallery,
|
|
5
|
+
and manage updates.
|
|
5
6
|
|
|
6
7
|
Git repository releases are the simplest approach and offer the most flexibility
|
|
7
8
|
for managing development branches. GitHub Releases are more efficient for
|
|
@@ -153,29 +154,62 @@ jobs:
|
|
|
153
154
|
release/win32.arm64.my-tool.zip
|
|
154
155
|
```
|
|
155
156
|
|
|
156
|
-
##
|
|
157
|
+
## Migrate an extension repository
|
|
157
158
|
|
|
158
|
-
If you
|
|
159
|
-
|
|
160
|
-
property in your `gemini-extension.json` file to seamlessly transition your
|
|
159
|
+
If you move your extension to a new repository or rename it, use the
|
|
160
|
+
`migratedTo` property in `gemini-extension.json` to seamlessly transition your
|
|
161
161
|
users.
|
|
162
162
|
|
|
163
|
-
1.
|
|
164
|
-
2.
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
163
|
+
1. **Create the new repository:** Set up your extension in its new location.
|
|
164
|
+
2. **Update the old repository:** In your original repository, update the
|
|
165
|
+
`gemini-extension.json` file to include the `migratedTo` property pointing
|
|
166
|
+
to the new repository URL, and increment the version number.
|
|
167
|
+
```json
|
|
168
|
+
{
|
|
169
|
+
"name": "my-extension",
|
|
170
|
+
"version": "1.1.0",
|
|
171
|
+
"migratedTo": "https://github.com/new-owner/new-extension-repo"
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
3. **Release the update:** Publish this new version in your old repository.
|
|
175
|
+
|
|
176
|
+
When users check for updates, Gemini CLI detects the `migratedTo` field,
|
|
177
|
+
verifies the new repository, and automatically updates their local installation
|
|
178
|
+
to track the new source. All settings migrate automatically.
|
|
179
|
+
|
|
180
|
+
## How updates work
|
|
181
|
+
|
|
182
|
+
Gemini CLI automatically checks for extension updates based on the installation
|
|
183
|
+
method. Understanding these mechanisms helps you ensure your users always have
|
|
184
|
+
the latest version.
|
|
185
|
+
|
|
186
|
+
### Sync manifest and tags
|
|
187
|
+
|
|
188
|
+
For GitHub releases, always ensure the `version` in `gemini-extension.json`
|
|
189
|
+
matches your GitHub release tag. While the CLI uses tags for update detection,
|
|
190
|
+
it displays the manifest version in the UI. Keeping them in sync prevents
|
|
191
|
+
confusion.
|
|
192
|
+
|
|
193
|
+
### Update mechanisms
|
|
194
|
+
|
|
195
|
+
<details>
|
|
196
|
+
<summary>Technical update details</summary>
|
|
197
|
+
|
|
198
|
+
The CLI uses different strategies depending on the installation type:
|
|
199
|
+
|
|
200
|
+
- **GitHub releases:** The CLI queries the GitHub API for the latest release
|
|
201
|
+
tag. It ignores the `version` field in the manifest for detection.
|
|
202
|
+
- **Git clones:** The CLI runs `git ls-remote` to compare the latest remote
|
|
203
|
+
commit hash with your local `HEAD`.
|
|
204
|
+
- **Local extensions:** The CLI compares the `version` field in the source
|
|
205
|
+
directory's manifest with the installed version.
|
|
206
|
+
|
|
207
|
+
To verify an extension's installation type, inspect the `type` field in the
|
|
208
|
+
metadata file at `~/.gemini/extensions/<name>/.gemini-extension-install.json`.
|
|
209
|
+
|
|
210
|
+
</details>
|
|
211
|
+
|
|
212
|
+
<!-- prettier-ignore -->
|
|
213
|
+
> [!IMPORTANT]
|
|
214
|
+
> The `migratedTo` flow requires at least one release on the new repository for
|
|
215
|
+
> the CLI to recognize it as a valid update source.
|
|
@@ -700,6 +700,19 @@ their corresponding top-level category object in your `settings.json` file.
|
|
|
700
700
|
"extends": "gemini-3-flash-base",
|
|
701
701
|
"modelConfig": {}
|
|
702
702
|
},
|
|
703
|
+
"context-snapshotter": {
|
|
704
|
+
"extends": "gemini-3-flash-base",
|
|
705
|
+
"modelConfig": {
|
|
706
|
+
"generateContentConfig": {
|
|
707
|
+
"thinkingConfig": {
|
|
708
|
+
"thinkingLevel": "HIGH"
|
|
709
|
+
},
|
|
710
|
+
"temperature": 1,
|
|
711
|
+
"topP": 0.95,
|
|
712
|
+
"topK": 64
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
},
|
|
703
716
|
"chat-compression-3-pro": {
|
|
704
717
|
"modelConfig": {
|
|
705
718
|
"model": "gemini-3-pro-preview"
|
|
@@ -1795,7 +1808,7 @@ their corresponding top-level category object in your `settings.json` file.
|
|
|
1795
1808
|
- **`experimental.voice.stopGracePeriodMs`** (number):
|
|
1796
1809
|
- **Description:** How long to wait for final transcription after stopping
|
|
1797
1810
|
recording.
|
|
1798
|
-
- **Default:** `
|
|
1811
|
+
- **Default:** `4000`
|
|
1799
1812
|
|
|
1800
1813
|
- **`experimental.adk.agentSessionNoninteractiveEnabled`** (boolean):
|
|
1801
1814
|
- **Description:** Enable non-interactive agent sessions.
|
|
@@ -326,6 +326,29 @@ lines and `3w` moves forward three words.
|
|
|
326
326
|
Counts are also supported for editing commands. For example, `3dd` deletes three
|
|
327
327
|
lines and `2cw` changes two words.
|
|
328
328
|
|
|
329
|
+
### Find, replace, yank, and paste in NORMAL mode
|
|
330
|
+
|
|
331
|
+
| Action | Keys |
|
|
332
|
+
| ----------------------------------------- | ----------- |
|
|
333
|
+
| Find next matching character | `f{char}` |
|
|
334
|
+
| Find previous matching character | `F{char}` |
|
|
335
|
+
| Move until before next matching character | `t{char}` |
|
|
336
|
+
| Move until after previous matching char | `T{char}` |
|
|
337
|
+
| Repeat latest character find | `;` |
|
|
338
|
+
| Repeat latest character find in reverse | `,` |
|
|
339
|
+
| Delete character before cursor | `X` |
|
|
340
|
+
| Toggle case under cursor | `~` |
|
|
341
|
+
| Replace character under cursor | `r{char}` |
|
|
342
|
+
| Yank line | `yy` |
|
|
343
|
+
| Yank to end of line | `Y` or `y$` |
|
|
344
|
+
| Yank word / WORD | `yw`, `yW` |
|
|
345
|
+
| Yank to end of word / WORD | `ye`, `yE` |
|
|
346
|
+
| Paste after cursor | `p` |
|
|
347
|
+
| Paste before cursor | `P` |
|
|
348
|
+
|
|
349
|
+
Delete and change operators also compose with character-find motions, so
|
|
350
|
+
commands such as `dfx`, `dtx`, `cFx`, and `cTx` are supported.
|
|
351
|
+
|
|
329
352
|
## Limitations
|
|
330
353
|
|
|
331
354
|
- On [Windows Terminal](https://en.wikipedia.org/wiki/Windows_Terminal):
|
|
@@ -41,18 +41,18 @@ import {
|
|
|
41
41
|
updateAllUpdatableExtensions,
|
|
42
42
|
updateExtension,
|
|
43
43
|
validateAuthMethod
|
|
44
|
-
} from "./chunk-
|
|
44
|
+
} from "./chunk-Q23X5R4A.js";
|
|
45
45
|
import {
|
|
46
46
|
appEvents
|
|
47
47
|
} from "./chunk-5PS3AYFU.js";
|
|
48
48
|
import {
|
|
49
49
|
startCommand,
|
|
50
50
|
startServer
|
|
51
|
-
} from "./chunk-
|
|
51
|
+
} from "./chunk-X26T73X6.js";
|
|
52
52
|
import {
|
|
53
53
|
exitCli,
|
|
54
54
|
require_source
|
|
55
|
-
} from "./chunk-
|
|
55
|
+
} from "./chunk-4TLQKGTR.js";
|
|
56
56
|
import {
|
|
57
57
|
DEFAULT_PORT,
|
|
58
58
|
GEMMA_MODEL_NAME,
|
|
@@ -86,11 +86,11 @@ import {
|
|
|
86
86
|
readServerProcessInfo,
|
|
87
87
|
resolveGemmaConfig,
|
|
88
88
|
saveModelChange
|
|
89
|
-
} from "./chunk-
|
|
89
|
+
} from "./chunk-PGJUNQPO.js";
|
|
90
90
|
import {
|
|
91
91
|
RELAUNCH_EXIT_CODE
|
|
92
|
-
} from "./chunk-
|
|
93
|
-
import "./chunk-
|
|
92
|
+
} from "./chunk-PYLHDAUK.js";
|
|
93
|
+
import "./chunk-6XOSIMPZ.js";
|
|
94
94
|
import {
|
|
95
95
|
cleanupCheckpoints,
|
|
96
96
|
registerCleanup,
|
|
@@ -99,7 +99,7 @@ import {
|
|
|
99
99
|
runExitCleanup,
|
|
100
100
|
runSyncCleanup,
|
|
101
101
|
setupSignalHandlers
|
|
102
|
-
} from "./chunk-
|
|
102
|
+
} from "./chunk-MRHFLHPJ.js";
|
|
103
103
|
import {
|
|
104
104
|
AuthType,
|
|
105
105
|
ChatRecordingService,
|
|
@@ -166,6 +166,7 @@ import {
|
|
|
166
166
|
listInboxPatches,
|
|
167
167
|
listInboxSkills,
|
|
168
168
|
listMemoryFiles,
|
|
169
|
+
loadConversationRecord,
|
|
169
170
|
logToolCall,
|
|
170
171
|
logUserPrompt,
|
|
171
172
|
parseAndFormatApiError,
|
|
@@ -189,7 +190,7 @@ import {
|
|
|
189
190
|
updatePolicy,
|
|
190
191
|
writeToStderr,
|
|
191
192
|
writeToStdout
|
|
192
|
-
} from "./chunk-
|
|
193
|
+
} from "./chunk-NBRZ4A3S.js";
|
|
193
194
|
import {
|
|
194
195
|
ASK_USER_TOOL_NAME,
|
|
195
196
|
DEFAULT_FILE_FILTERING_OPTIONS,
|
|
@@ -227,13 +228,14 @@ import {
|
|
|
227
228
|
getDisplayString,
|
|
228
229
|
getErrorMessage,
|
|
229
230
|
getErrorType,
|
|
231
|
+
getProjectHash,
|
|
230
232
|
homedir,
|
|
231
233
|
isFatalToolError,
|
|
232
234
|
isNodeError,
|
|
233
235
|
loadServerHierarchicalMemory,
|
|
234
236
|
resolveToRealPath,
|
|
235
237
|
setGeminiMdFilename
|
|
236
|
-
} from "./chunk-
|
|
238
|
+
} from "./chunk-N6QYTC2T.js";
|
|
237
239
|
import "./chunk-664ZODQF.js";
|
|
238
240
|
import "./chunk-RJTRUG2J.js";
|
|
239
241
|
import "./chunk-IUUIT4SU.js";
|
|
@@ -1518,11 +1520,11 @@ var parser = new YargsParser({
|
|
|
1518
1520
|
resolve: resolve2,
|
|
1519
1521
|
// TODO: figure out a way to combine ESM and CJS coverage, such that
|
|
1520
1522
|
// we can exercise all the lines below:
|
|
1521
|
-
require: (
|
|
1523
|
+
require: (path16) => {
|
|
1522
1524
|
if (typeof __require !== "undefined") {
|
|
1523
|
-
return __require(
|
|
1524
|
-
} else if (
|
|
1525
|
-
return JSON.parse(readFileSync(
|
|
1525
|
+
return __require(path16);
|
|
1526
|
+
} else if (path16.match(/\.json$/)) {
|
|
1527
|
+
return JSON.parse(readFileSync(path16, "utf8"));
|
|
1526
1528
|
} else {
|
|
1527
1529
|
throw Error("only .json config files are supported in ESM");
|
|
1528
1530
|
}
|
|
@@ -5433,12 +5435,16 @@ async function getServerStatus(serverName, server, isTrusted, activeSettings) {
|
|
|
5433
5435
|
}
|
|
5434
5436
|
return "disabled" /* DISABLED */;
|
|
5435
5437
|
}
|
|
5438
|
+
if (!isTrusted) {
|
|
5439
|
+
return "disabled" /* DISABLED */;
|
|
5440
|
+
}
|
|
5436
5441
|
return testMCPConnection(serverName, server, isTrusted, activeSettings);
|
|
5437
5442
|
}
|
|
5438
5443
|
async function listMcpServers(loadedSettingsArg) {
|
|
5439
5444
|
const loadedSettings = loadedSettingsArg ?? loadSettings();
|
|
5440
5445
|
const activeSettings = loadedSettings.merged;
|
|
5441
|
-
const
|
|
5446
|
+
const allSettings = !loadedSettings.isTrusted ? loadedSettings.getMergedSettingsAsIfTrusted() : activeSettings;
|
|
5447
|
+
const { mcpServers, blockedServerNames } = await getMcpServersFromConfig(allSettings);
|
|
5442
5448
|
const serverNames = Object.keys(mcpServers);
|
|
5443
5449
|
if (blockedServerNames.length > 0) {
|
|
5444
5450
|
const message = getAdminBlockedMcpServersMessage(
|
|
@@ -5453,6 +5459,13 @@ async function listMcpServers(loadedSettingsArg) {
|
|
|
5453
5459
|
}
|
|
5454
5460
|
return;
|
|
5455
5461
|
}
|
|
5462
|
+
if (!loadedSettings.isTrusted) {
|
|
5463
|
+
debugLogger.log(
|
|
5464
|
+
import_chalk.default.yellow(
|
|
5465
|
+
"Warning: MCP servers are configured but disabled because this folder is untrusted.\nUser-level servers are also suppressed in untrusted folders to prevent accidental side-effects.\n"
|
|
5466
|
+
)
|
|
5467
|
+
);
|
|
5468
|
+
}
|
|
5456
5469
|
debugLogger.log("Configured MCP servers:\n");
|
|
5457
5470
|
for (const serverName of serverNames) {
|
|
5458
5471
|
const server = mcpServers[serverName];
|
|
@@ -6292,27 +6305,27 @@ import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
|
6292
6305
|
var __filename = fileURLToPath2(import.meta.url);
|
|
6293
6306
|
var __dirname2 = dirname3(__filename);
|
|
6294
6307
|
var EXAMPLES_PATH = join(__dirname2, "examples");
|
|
6295
|
-
async function pathExists(
|
|
6308
|
+
async function pathExists(path16) {
|
|
6296
6309
|
try {
|
|
6297
|
-
await access(
|
|
6310
|
+
await access(path16);
|
|
6298
6311
|
return true;
|
|
6299
6312
|
} catch {
|
|
6300
6313
|
return false;
|
|
6301
6314
|
}
|
|
6302
6315
|
}
|
|
6303
|
-
async function createDirectory(
|
|
6304
|
-
if (await pathExists(
|
|
6305
|
-
throw new Error(`Path already exists: ${
|
|
6316
|
+
async function createDirectory(path16) {
|
|
6317
|
+
if (await pathExists(path16)) {
|
|
6318
|
+
throw new Error(`Path already exists: ${path16}`);
|
|
6306
6319
|
}
|
|
6307
|
-
await mkdir(
|
|
6320
|
+
await mkdir(path16, { recursive: true });
|
|
6308
6321
|
}
|
|
6309
|
-
async function copyDirectory(template,
|
|
6310
|
-
await createDirectory(
|
|
6322
|
+
async function copyDirectory(template, path16) {
|
|
6323
|
+
await createDirectory(path16);
|
|
6311
6324
|
const examplePath = join(EXAMPLES_PATH, template);
|
|
6312
6325
|
const entries = await readdir(examplePath, { withFileTypes: true });
|
|
6313
6326
|
for (const entry of entries) {
|
|
6314
6327
|
const srcPath = join(examplePath, entry.name);
|
|
6315
|
-
const destPath = join(
|
|
6328
|
+
const destPath = join(path16, entry.name);
|
|
6316
6329
|
await cp(srcPath, destPath, { recursive: true });
|
|
6317
6330
|
}
|
|
6318
6331
|
}
|
|
@@ -6587,7 +6600,7 @@ async function handleEnable3(args) {
|
|
|
6587
6600
|
const result = enableSkill(settings, name);
|
|
6588
6601
|
const feedback = renderSkillActionFeedback(
|
|
6589
6602
|
result,
|
|
6590
|
-
(label,
|
|
6603
|
+
(label, path16) => `${import_chalk5.default.bold(label)} (${import_chalk5.default.dim(path16)})`
|
|
6591
6604
|
);
|
|
6592
6605
|
debugLogger.log(feedback);
|
|
6593
6606
|
}
|
|
@@ -6617,7 +6630,7 @@ async function handleDisable3(args) {
|
|
|
6617
6630
|
const result = disableSkill(settings, name, scope);
|
|
6618
6631
|
const feedback = renderSkillActionFeedback(
|
|
6619
6632
|
result,
|
|
6620
|
-
(label,
|
|
6633
|
+
(label, path16) => `${import_chalk6.default.bold(label)} (${import_chalk6.default.dim(path16)})`
|
|
6621
6634
|
);
|
|
6622
6635
|
debugLogger.log(feedback);
|
|
6623
6636
|
}
|
|
@@ -7812,7 +7825,7 @@ async function loadSandboxConfig(settings, argv) {
|
|
|
7812
7825
|
}
|
|
7813
7826
|
const command2 = getSandboxCommand(sandboxValue);
|
|
7814
7827
|
const packageJson = await getPackageJson(__dirname3);
|
|
7815
|
-
const image = process.env["GEMINI_SANDBOX_IMAGE"] ?? "us-docker.pkg.dev/gemini-code-dev/gemini-cli/sandbox:0.
|
|
7828
|
+
const image = process.env["GEMINI_SANDBOX_IMAGE"] ?? "us-docker.pkg.dev/gemini-code-dev/gemini-cli/sandbox:0.43.0-preview.0" ?? customImage ?? packageJson?.config?.sandboxImageUri;
|
|
7816
7829
|
const isNative = command2 === "windows-native" || command2 === "sandbox-exec" || command2 === "lxc";
|
|
7817
7830
|
return command2 && (image || isNative) ? { enabled: true, allowedPaths, networkAccess, command: command2, image } : void 0;
|
|
7818
7831
|
}
|
|
@@ -7980,8 +7993,13 @@ async function parseArguments(settings) {
|
|
|
7980
7993
|
const queryArg2 = argv["query"];
|
|
7981
7994
|
const query = typeof queryArg2 === "string" || Array.isArray(queryArg2) ? queryArg2 : void 0;
|
|
7982
7995
|
const hasPositionalQuery = Array.isArray(query) ? query.length > 0 : !!query;
|
|
7983
|
-
|
|
7984
|
-
|
|
7996
|
+
const sessionFlags = [
|
|
7997
|
+
argv["resume"] !== void 0,
|
|
7998
|
+
argv["session-id"] !== void 0,
|
|
7999
|
+
argv["session-file"] !== void 0
|
|
8000
|
+
].filter(Boolean).length;
|
|
8001
|
+
if (sessionFlags > 1) {
|
|
8002
|
+
return "The flags --resume, --session-id, and --session-file are mutually exclusive. Please provide only one.";
|
|
7985
8003
|
}
|
|
7986
8004
|
if (argv["prompt"] && hasPositionalQuery) {
|
|
7987
8005
|
return "Cannot use both a positional prompt and the --prompt (-p) flag together";
|
|
@@ -8112,6 +8130,10 @@ async function parseArguments(settings) {
|
|
|
8112
8130
|
}
|
|
8113
8131
|
return trimmed;
|
|
8114
8132
|
}
|
|
8133
|
+
}).option("session-file", {
|
|
8134
|
+
type: "string",
|
|
8135
|
+
nargs: 1,
|
|
8136
|
+
description: "Load a session from a JSON file"
|
|
8115
8137
|
}).option("session-id", {
|
|
8116
8138
|
type: "string",
|
|
8117
8139
|
nargs: 1,
|
|
@@ -8596,7 +8618,11 @@ async function loadCliConfig(settings, sessionId, argv, options = {}) {
|
|
|
8596
8618
|
shellBackgroundCompletionBehavior: settings.tools?.shell?.backgroundCompletionBehavior,
|
|
8597
8619
|
shellToolInactivityTimeout: settings.tools?.shell?.inactivityTimeout,
|
|
8598
8620
|
enableShellOutputEfficiency: settings.tools?.shell?.enableShellOutputEfficiency ?? true,
|
|
8599
|
-
|
|
8621
|
+
// In ACP mode, always skip the next-speaker check. This check triggers
|
|
8622
|
+
// recursive continuation turns inside GeminiClient.processTurn() that
|
|
8623
|
+
// conflict with ACP's explicit turn management via session/prompt,
|
|
8624
|
+
// causing infinite agent_thought_chunk loops.
|
|
8625
|
+
skipNextSpeakerCheck: isAcpMode || settings.model?.skipNextSpeakerCheck,
|
|
8600
8626
|
truncateToolOutputThreshold: settings.tools?.truncateToolOutputThreshold,
|
|
8601
8627
|
eventEmitter: coreEvents,
|
|
8602
8628
|
useWriteTodos: argv.useWriteTodos ?? settings.useWriteTodos,
|
|
@@ -8755,6 +8781,8 @@ import { createHash as createHash2 } from "node:crypto";
|
|
|
8755
8781
|
import v8 from "node:v8";
|
|
8756
8782
|
import os6 from "node:os";
|
|
8757
8783
|
import dns from "node:dns";
|
|
8784
|
+
import * as path15 from "node:path";
|
|
8785
|
+
import * as fsPromises from "node:fs/promises";
|
|
8758
8786
|
|
|
8759
8787
|
// packages/cli/src/utils/sandbox.ts
|
|
8760
8788
|
var import_shell_quote2 = __toESM(require_shell_quote(), 1);
|
|
@@ -9215,21 +9243,11 @@ async function start_sandbox(config, nodeArgs = [], cliConfig, cliArgs = []) {
|
|
|
9215
9243
|
}
|
|
9216
9244
|
const imageName = parseImageName(image);
|
|
9217
9245
|
const isIntegrationTest = process.env["GEMINI_CLI_INTEGRATION_TEST"] === "true";
|
|
9218
|
-
|
|
9219
|
-
|
|
9220
|
-
|
|
9221
|
-
|
|
9222
|
-
|
|
9223
|
-
debugLogger.log(`ContainerName: ${containerName}`);
|
|
9224
|
-
} else {
|
|
9225
|
-
let index = 0;
|
|
9226
|
-
const containerNameCheck = (await execAsync(`${command2} ps -a --format "{{.Names}}"`)).stdout.trim();
|
|
9227
|
-
while (containerNameCheck.includes(`${imageName}-${index}`)) {
|
|
9228
|
-
index++;
|
|
9229
|
-
}
|
|
9230
|
-
containerName = `${imageName}-${index}`;
|
|
9231
|
-
debugLogger.log(`ContainerName (regular): ${containerName}`);
|
|
9232
|
-
}
|
|
9246
|
+
const containerNamePrefix = isIntegrationTest ? "gemini-cli-integration-test" : imageName;
|
|
9247
|
+
const containerName = `${containerNamePrefix}-${randomBytes(6).toString(
|
|
9248
|
+
"hex"
|
|
9249
|
+
)}`;
|
|
9250
|
+
debugLogger.log(`ContainerName: ${containerName}`);
|
|
9233
9251
|
args.push("--name", containerName, "--hostname", containerName);
|
|
9234
9252
|
if (process.env["GEMINI_CLI_TEST_VAR"]) {
|
|
9235
9253
|
args.push(
|
|
@@ -10215,7 +10233,7 @@ async function runNonInteractive({
|
|
|
10215
10233
|
}
|
|
10216
10234
|
});
|
|
10217
10235
|
if (process.env["GEMINI_CLI_ACTIVITY_LOG_TARGET"]) {
|
|
10218
|
-
const { setupInitialActivityLogger } = await import("./devtoolsService-
|
|
10236
|
+
const { setupInitialActivityLogger } = await import("./devtoolsService-LV5NJ2BT.js");
|
|
10219
10237
|
setupInitialActivityLogger(config);
|
|
10220
10238
|
}
|
|
10221
10239
|
const { stdout: workingStdout } = createWorkingStdio();
|
|
@@ -10670,6 +10688,9 @@ async function runNonInteractive({
|
|
|
10670
10688
|
async function runNonInteractive2(params) {
|
|
10671
10689
|
const useAgentSession = params.config.getAgentSessionNoninteractiveEnabled();
|
|
10672
10690
|
if (useAgentSession) {
|
|
10691
|
+
debugLogger.debug(
|
|
10692
|
+
"[ADK] Running non-interactive mode with ADK agent session"
|
|
10693
|
+
);
|
|
10673
10694
|
return runNonInteractive(params);
|
|
10674
10695
|
}
|
|
10675
10696
|
const { config, settings, input, prompt_id, resumedSessionData } = params;
|
|
@@ -10683,7 +10704,7 @@ async function runNonInteractive2(params) {
|
|
|
10683
10704
|
}
|
|
10684
10705
|
});
|
|
10685
10706
|
if (process.env["GEMINI_CLI_ACTIVITY_LOG_TARGET"]) {
|
|
10686
|
-
const { setupInitialActivityLogger } = await import("./devtoolsService-
|
|
10707
|
+
const { setupInitialActivityLogger } = await import("./devtoolsService-LV5NJ2BT.js");
|
|
10687
10708
|
setupInitialActivityLogger(config);
|
|
10688
10709
|
}
|
|
10689
10710
|
const { stdout: workingStdout } = createWorkingStdio();
|
|
@@ -10917,6 +10938,20 @@ async function runNonInteractive2(params) {
|
|
|
10917
10938
|
durationMs
|
|
10918
10939
|
)
|
|
10919
10940
|
});
|
|
10941
|
+
} else if (config.getOutputFormat() === "json" /* JSON */) {
|
|
10942
|
+
const formatter = new JsonFormatter();
|
|
10943
|
+
const stats = uiTelemetryService.getMetrics();
|
|
10944
|
+
textOutput.write(
|
|
10945
|
+
formatter.format(
|
|
10946
|
+
config.getSessionId(),
|
|
10947
|
+
responseText,
|
|
10948
|
+
stats,
|
|
10949
|
+
void 0,
|
|
10950
|
+
[...warnings, stopMessage]
|
|
10951
|
+
)
|
|
10952
|
+
);
|
|
10953
|
+
} else {
|
|
10954
|
+
textOutput.ensureTrailingNewline();
|
|
10920
10955
|
}
|
|
10921
10956
|
return;
|
|
10922
10957
|
} else if (event.type === "agent_execution_blocked" /* AgentExecutionBlocked */) {
|
|
@@ -14179,12 +14214,6 @@ ${event.value.description}`;
|
|
|
14179
14214
|
const invocation = tool.build(args);
|
|
14180
14215
|
const displayTitle = typeof invocation.getDisplayTitle === "function" ? invocation.getDisplayTitle() : invocation.getDescription();
|
|
14181
14216
|
const explanation = typeof invocation.getExplanation === "function" ? invocation.getExplanation() : "";
|
|
14182
|
-
if (explanation) {
|
|
14183
|
-
await this.sendUpdate({
|
|
14184
|
-
sessionUpdate: "agent_thought_chunk",
|
|
14185
|
-
content: { type: "text", text: explanation }
|
|
14186
|
-
});
|
|
14187
|
-
}
|
|
14188
14217
|
const confirmationDetails = await invocation.shouldConfirmExecute(abortSignal);
|
|
14189
14218
|
if (confirmationDetails) {
|
|
14190
14219
|
const content2 = [];
|
|
@@ -14199,6 +14228,12 @@ ${event.value.description}`;
|
|
|
14199
14228
|
}
|
|
14200
14229
|
});
|
|
14201
14230
|
}
|
|
14231
|
+
if (content2.length === 0 && explanation) {
|
|
14232
|
+
content2.push({
|
|
14233
|
+
type: "content",
|
|
14234
|
+
content: { type: "text", text: explanation }
|
|
14235
|
+
});
|
|
14236
|
+
}
|
|
14202
14237
|
const params = {
|
|
14203
14238
|
sessionId: this.id,
|
|
14204
14239
|
options: toPermissionOptions(
|
|
@@ -14247,6 +14282,12 @@ ${event.value.description}`;
|
|
|
14247
14282
|
}
|
|
14248
14283
|
} else {
|
|
14249
14284
|
const content2 = [];
|
|
14285
|
+
if (explanation) {
|
|
14286
|
+
content2.push({
|
|
14287
|
+
type: "content",
|
|
14288
|
+
content: { type: "text", text: explanation }
|
|
14289
|
+
});
|
|
14290
|
+
}
|
|
14250
14291
|
await this.sendUpdate({
|
|
14251
14292
|
sessionUpdate: "tool_call",
|
|
14252
14293
|
toolCallId: callId,
|
|
@@ -15706,13 +15747,69 @@ ${reason.stack}` : ""}`;
|
|
|
15706
15747
|
}
|
|
15707
15748
|
});
|
|
15708
15749
|
}
|
|
15709
|
-
async function resolveSessionId(resumeArg, sessionIdArg) {
|
|
15710
|
-
if (!resumeArg && !sessionIdArg) {
|
|
15750
|
+
async function resolveSessionId(resumeArg, sessionIdArg, sessionFileArg) {
|
|
15751
|
+
if (!resumeArg && !sessionIdArg && !sessionFileArg) {
|
|
15711
15752
|
return { sessionId: createSessionId() };
|
|
15712
15753
|
}
|
|
15713
15754
|
const storage = new Storage(process.cwd());
|
|
15714
15755
|
await storage.initialize();
|
|
15715
15756
|
const sessionSelector = new SessionSelector(storage);
|
|
15757
|
+
if (sessionFileArg) {
|
|
15758
|
+
try {
|
|
15759
|
+
const sessionData = await loadConversationRecord(sessionFileArg);
|
|
15760
|
+
if (!sessionData) {
|
|
15761
|
+
throw new Error(`File not found or invalid format: ${sessionFileArg}`);
|
|
15762
|
+
}
|
|
15763
|
+
const now = Date.now();
|
|
15764
|
+
const isoNow = new Date(now).toISOString();
|
|
15765
|
+
sessionData.messages = (sessionData.messages || []).filter(
|
|
15766
|
+
(m) => typeof m === "object" && m !== null && (m.type === "user" || m.type === "gemini") && m.content !== void 0
|
|
15767
|
+
);
|
|
15768
|
+
sessionData.messages.unshift({
|
|
15769
|
+
id: `import-${now}`,
|
|
15770
|
+
type: "info",
|
|
15771
|
+
content: `Imported session from ${sessionFileArg}`,
|
|
15772
|
+
timestamp: isoNow
|
|
15773
|
+
});
|
|
15774
|
+
const newSessionId = createSessionId();
|
|
15775
|
+
sessionData.sessionId = newSessionId;
|
|
15776
|
+
sessionData.projectHash = getProjectHash(storage.getProjectRoot());
|
|
15777
|
+
sessionData.startTime = isoNow;
|
|
15778
|
+
sessionData.lastUpdated = isoNow;
|
|
15779
|
+
const chatsDir = path15.join(storage.getProjectTempDir(), "chats");
|
|
15780
|
+
const newSessionPath = path15.join(
|
|
15781
|
+
chatsDir,
|
|
15782
|
+
`session-${now}-${newSessionId.slice(0, 8)}.jsonl`
|
|
15783
|
+
);
|
|
15784
|
+
const { messages: _messages, ...initialMetadata } = sessionData;
|
|
15785
|
+
const lines = [JSON.stringify(initialMetadata)];
|
|
15786
|
+
if (sessionData.messages) {
|
|
15787
|
+
for (const msg of sessionData.messages) {
|
|
15788
|
+
lines.push(JSON.stringify(msg));
|
|
15789
|
+
}
|
|
15790
|
+
}
|
|
15791
|
+
await fsPromises.mkdir(chatsDir, { recursive: true });
|
|
15792
|
+
await fsPromises.writeFile(
|
|
15793
|
+
newSessionPath,
|
|
15794
|
+
lines.join("\n") + "\n",
|
|
15795
|
+
"utf-8"
|
|
15796
|
+
);
|
|
15797
|
+
return {
|
|
15798
|
+
sessionId: newSessionId,
|
|
15799
|
+
resumedSessionData: {
|
|
15800
|
+
conversation: sessionData,
|
|
15801
|
+
filePath: newSessionPath
|
|
15802
|
+
}
|
|
15803
|
+
};
|
|
15804
|
+
} catch (error) {
|
|
15805
|
+
coreEvents.emitFeedback(
|
|
15806
|
+
"error",
|
|
15807
|
+
`Error importing session from file: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
15808
|
+
);
|
|
15809
|
+
await runExitCleanup();
|
|
15810
|
+
process.exit(ExitCodes.FATAL_INPUT_ERROR);
|
|
15811
|
+
}
|
|
15812
|
+
}
|
|
15716
15813
|
if (sessionIdArg) {
|
|
15717
15814
|
if (await sessionSelector.sessionExists(sessionIdArg)) {
|
|
15718
15815
|
coreEvents.emitFeedback(
|
|
@@ -15734,8 +15831,10 @@ async function resolveSessionId(resumeArg, sessionIdArg) {
|
|
|
15734
15831
|
};
|
|
15735
15832
|
} catch (error) {
|
|
15736
15833
|
if (error instanceof SessionError && error.code === "NO_SESSIONS_FOUND") {
|
|
15737
|
-
|
|
15738
|
-
|
|
15834
|
+
if (resumeArg === RESUME_LATEST) {
|
|
15835
|
+
coreEvents.emitFeedback("warning", error.message);
|
|
15836
|
+
return { sessionId: createSessionId() };
|
|
15837
|
+
}
|
|
15739
15838
|
}
|
|
15740
15839
|
coreEvents.emitFeedback(
|
|
15741
15840
|
"error",
|
|
@@ -15746,7 +15845,7 @@ async function resolveSessionId(resumeArg, sessionIdArg) {
|
|
|
15746
15845
|
}
|
|
15747
15846
|
}
|
|
15748
15847
|
async function startInteractiveUI(config, settings, startupWarnings, workspaceRoot = process.cwd(), resumedSessionData, initializationResult) {
|
|
15749
|
-
const { startInteractiveUI: doStartUI } = await import("./interactiveCli-
|
|
15848
|
+
const { startInteractiveUI: doStartUI } = await import("./interactiveCli-BQ36B66Z.js");
|
|
15750
15849
|
await doStartUI(
|
|
15751
15850
|
config,
|
|
15752
15851
|
settings,
|
|
@@ -15809,7 +15908,8 @@ async function main() {
|
|
|
15809
15908
|
const argv = await argvPromise;
|
|
15810
15909
|
const { sessionId, resumedSessionData } = await resolveSessionId(
|
|
15811
15910
|
argv.resume,
|
|
15812
|
-
argv.sessionId
|
|
15911
|
+
argv.sessionId,
|
|
15912
|
+
argv.sessionFile
|
|
15813
15913
|
);
|
|
15814
15914
|
if (argv.allowedTools && argv.allowedTools.length > 0 || settings.merged.tools?.allowed && settings.merged.tools.allowed.length > 0) {
|
|
15815
15915
|
coreEvents.emitFeedback(
|
|
@@ -15953,7 +16053,7 @@ ${finalArgs[promptIndex + 1]}`;
|
|
|
15953
16053
|
await config.storage.initialize();
|
|
15954
16054
|
adminControlsListner.setConfig(config);
|
|
15955
16055
|
if (config.isInteractive() && settings.merged.general.devtools) {
|
|
15956
|
-
const { setupInitialActivityLogger } = await import("./devtoolsService-
|
|
16056
|
+
const { setupInitialActivityLogger } = await import("./devtoolsService-LV5NJ2BT.js");
|
|
15957
16057
|
setupInitialActivityLogger(config);
|
|
15958
16058
|
}
|
|
15959
16059
|
registerTelemetryConfig(config);
|
|
@@ -16012,7 +16112,7 @@ ${finalArgs[promptIndex + 1]}`;
|
|
|
16012
16112
|
const initAppHandle = startupProfiler.start("initialize_app");
|
|
16013
16113
|
const initializationResult = await initializeApp(config, settings);
|
|
16014
16114
|
initAppHandle?.end();
|
|
16015
|
-
import("./liteRtServerManager-
|
|
16115
|
+
import("./liteRtServerManager-ISYDOBNC.js").then(({ LiteRtServerManager }) => {
|
|
16016
16116
|
const mergedGemma = settings.merged.experimental?.gemmaModelRouter;
|
|
16017
16117
|
if (!mergedGemma) return;
|
|
16018
16118
|
const userGemma = settings.forScope("User" /* User */).settings.experimental?.gemmaModelRouter;
|