mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-04-28 03:30:40 +00:00
refactor: unify sandbox configuration naming and improve telemetry config
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
parent
66f754e203
commit
8b3aeb4550
24 changed files with 141 additions and 143 deletions
|
|
@ -42,11 +42,11 @@ steps:
|
|||
args:
|
||||
- '-c'
|
||||
- |-
|
||||
export GEMINI_SANDBOX_IMAGE_TAG=$$(cat /workspace/image_tag.txt)
|
||||
echo "Using Docker image tag for build: $$GEMINI_SANDBOX_IMAGE_TAG"
|
||||
export QWEN_SANDBOX_IMAGE_TAG=$$(cat /workspace/image_tag.txt)
|
||||
echo "Using Docker image tag for build: $$QWEN_SANDBOX_IMAGE_TAG"
|
||||
npm run build:sandbox -- --output-file /workspace/final_image_uri.txt
|
||||
env:
|
||||
- 'GEMINI_SANDBOX=$_CONTAINER_TOOL'
|
||||
- 'QWEN_SANDBOX=$_CONTAINER_TOOL'
|
||||
|
||||
# Step 8: Publish sandbox container image
|
||||
- name: 'us-west1-docker.pkg.dev/gemini-code-dev/gemini-code-containers/gemini-code-builder'
|
||||
|
|
@ -61,7 +61,7 @@ steps:
|
|||
echo "Pushing sandbox image: $${FINAL_IMAGE_URI}"
|
||||
$_CONTAINER_TOOL push "$${FINAL_IMAGE_URI}"
|
||||
env:
|
||||
- 'GEMINI_SANDBOX=$_CONTAINER_TOOL'
|
||||
- 'QWEN_SANDBOX=$_CONTAINER_TOOL'
|
||||
|
||||
options:
|
||||
defaultLogsBucketBehavior: 'REGIONAL_USER_OWNED_BUCKET'
|
||||
|
|
|
|||
6
.vscode/launch.json
vendored
6
.vscode/launch.json
vendored
|
|
@ -14,7 +14,7 @@
|
|||
"cwd": "${workspaceFolder}",
|
||||
"console": "integratedTerminal",
|
||||
"env": {
|
||||
"GEMINI_SANDBOX": "false"
|
||||
"QWEN_SANDBOX": "false"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -86,7 +86,7 @@
|
|||
"cwd": "${workspaceFolder}",
|
||||
"console": "integratedTerminal",
|
||||
"env": {
|
||||
"GEMINI_SANDBOX": "false"
|
||||
"QWEN_SANDBOX": "false"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -107,7 +107,7 @@
|
|||
"internalConsoleOptions": "neverOpen",
|
||||
"skipFiles": ["<node_internals>/**"],
|
||||
"env": {
|
||||
"GEMINI_SANDBOX": "false"
|
||||
"QWEN_SANDBOX": "false"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# Example Proxy Script
|
||||
|
||||
The following is an example of a proxy script that can be used with the `GEMINI_SANDBOX_PROXY_COMMAND` environment variable. This script only allows `HTTPS` connections to `example.com:443` and declines all other requests.
|
||||
The following is an example of a proxy script that can be used with the `QWEN_SANDBOX_PROXY_COMMAND` environment variable. This script only allows `HTTPS` connections to `example.com:443` and declines all other requests.
|
||||
|
||||
```javascript
|
||||
#!/usr/bin/env node
|
||||
|
|
@ -12,7 +12,7 @@ The following is an example of a proxy script that can be used with the `GEMINI_
|
|||
*/
|
||||
|
||||
// Example proxy server that listens on :::8877 and only allows HTTPS connections to example.com.
|
||||
// Set `GEMINI_SANDBOX_PROXY_COMMAND=scripts/example-proxy.js` to run proxy alongside sandbox
|
||||
// Set `QWEN_SANDBOX_PROXY_COMMAND=scripts/example-proxy.js` to run proxy alongside sandbox
|
||||
// Test via `curl https://example.com` inside sandbox (in shell mode or via shell tool)
|
||||
|
||||
import http from 'node:http';
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ RUN apt-get update && apt-get install -y \
|
|||
#### 4、Create the first sandbox image under the root directory of your project
|
||||
|
||||
```bash
|
||||
GEMINI_SANDBOX=docker BUILD_SANDBOX=1 qwen -s
|
||||
QWEN_SANDBOX=docker BUILD_SANDBOX=1 qwen -s
|
||||
# Observe whether the sandbox version of the tool you launched is consistent with the version of your custom image. If they are consistent, the startup will be successful
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -481,22 +481,22 @@ For authentication-related variables (like `OPENAI_*`) and the recommended `.qwe
|
|||
|
||||
### Environment Variables Table
|
||||
|
||||
| Variable | Description | Notes |
|
||||
| -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `GEMINI_TELEMETRY_ENABLED` | Set to `true` or `1` to enable telemetry. Any other value is treated as disabling it. | Overrides the `telemetry.enabled` setting. |
|
||||
| `GEMINI_TELEMETRY_TARGET` | Sets the telemetry target (`local` or `gcp`). | Overrides the `telemetry.target` setting. |
|
||||
| `GEMINI_TELEMETRY_OTLP_ENDPOINT` | Sets the OTLP endpoint for telemetry. | Overrides the `telemetry.otlpEndpoint` setting. |
|
||||
| `GEMINI_TELEMETRY_OTLP_PROTOCOL` | Sets the OTLP protocol (`grpc` or `http`). | Overrides the `telemetry.otlpProtocol` setting. |
|
||||
| `GEMINI_TELEMETRY_LOG_PROMPTS` | Set to `true` or `1` to enable or disable logging of user prompts. Any other value is treated as disabling it. | Overrides the `telemetry.logPrompts` setting. |
|
||||
| `GEMINI_TELEMETRY_OUTFILE` | Sets the file path to write telemetry to when the target is `local`. | Overrides the `telemetry.outfile` setting. |
|
||||
| `GEMINI_TELEMETRY_USE_COLLECTOR` | Set to `true` or `1` to enable or disable using an external OTLP collector. Any other value is treated as disabling it. | Overrides the `telemetry.useCollector` setting. |
|
||||
| `GEMINI_SANDBOX` | Alternative to the `sandbox` setting in `settings.json`. | Accepts `true`, `false`, `docker`, `podman`, or a custom command string. |
|
||||
| `SEATBELT_PROFILE` | (macOS specific) Switches the Seatbelt (`sandbox-exec`) profile on macOS. | `permissive-open`: (Default) Restricts writes to the project folder (and a few other folders, see `packages/cli/src/utils/sandbox-macos-permissive-open.sb`) but allows other operations. `strict`: Uses a strict profile that declines operations by default. `<profile_name>`: Uses a custom profile. To define a custom profile, create a file named `sandbox-macos-<profile_name>.sb` in your project's `.qwen/` directory (e.g., `my-project/.qwen/sandbox-macos-custom.sb`). |
|
||||
| `DEBUG` or `DEBUG_MODE` | (often used by underlying libraries or the CLI itself) Set to `true` or `1` to enable verbose debug logging, which can be helpful for troubleshooting. | **Note:** These variables are automatically excluded from project `.env` files by default to prevent interference with the CLI behavior. Use `.qwen/.env` files if you need to set these for Qwen Code specifically. |
|
||||
| `NO_COLOR` | Set to any value to disable all color output in the CLI. | |
|
||||
| `CLI_TITLE` | Set to a string to customize the title of the CLI. | |
|
||||
| `CODE_ASSIST_ENDPOINT` | Specifies the endpoint for the code assist server. | This is useful for development and testing. |
|
||||
| `TAVILY_API_KEY` | Your API key for the Tavily web search service. | Used to enable the `web_search` tool functionality. Example: `export TAVILY_API_KEY="tvly-your-api-key-here"` |
|
||||
| Variable | Description | Notes |
|
||||
| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `QWEN_TELEMETRY_ENABLED` | Set to `true` or `1` to enable telemetry. Any other value is treated as disabling it. | Overrides the `telemetry.enabled` setting. |
|
||||
| `QWEN_TELEMETRY_TARGET` | Sets the telemetry target (`local` or `gcp`). | Overrides the `telemetry.target` setting. |
|
||||
| `QWEN_TELEMETRY_OTLP_ENDPOINT` | Sets the OTLP endpoint for telemetry. | Overrides the `telemetry.otlpEndpoint` setting. |
|
||||
| `QWEN_TELEMETRY_OTLP_PROTOCOL` | Sets the OTLP protocol (`grpc` or `http`). | Overrides the `telemetry.otlpProtocol` setting. |
|
||||
| `QWEN_TELEMETRY_LOG_PROMPTS` | Set to `true` or `1` to enable or disable logging of user prompts. Any other value is treated as disabling it. | Overrides the `telemetry.logPrompts` setting. |
|
||||
| `QWEN_TELEMETRY_OUTFILE` | Sets the file path to write telemetry to when the target is `local`. | Overrides the `telemetry.outfile` setting. |
|
||||
| `QWEN_TELEMETRY_USE_COLLECTOR` | Set to `true` or `1` to enable or disable using an external OTLP collector. Any other value is treated as disabling it. | Overrides the `telemetry.useCollector` setting. |
|
||||
| `QWEN_SANDBOX` | Alternative to the `sandbox` setting in `settings.json`. | Accepts `true`, `false`, `docker`, `podman`, or a custom command string. |
|
||||
| `SEATBELT_PROFILE` | (macOS specific) Switches the Seatbelt (`sandbox-exec`) profile on macOS. | `permissive-open`: (Default) Restricts writes to the project folder (and a few other folders, see `packages/cli/src/utils/sandbox-macos-permissive-open.sb`) but allows other operations. `strict`: Uses a strict profile that declines operations by default. `<profile_name>`: Uses a custom profile. To define a custom profile, create a file named `sandbox-macos-<profile_name>.sb` in your project's `.qwen/` directory (e.g., `my-project/.qwen/sandbox-macos-custom.sb`). |
|
||||
| `DEBUG` or `DEBUG_MODE` | (often used by underlying libraries or the CLI itself) Set to `true` or `1` to enable verbose debug logging, which can be helpful for troubleshooting. | **Note:** These variables are automatically excluded from project `.env` files by default to prevent interference with the CLI behavior. Use `.qwen/.env` files if you need to set these for Qwen Code specifically. |
|
||||
| `NO_COLOR` | Set to any value to disable all color output in the CLI. | |
|
||||
| `CLI_TITLE` | Set to a string to customize the title of the CLI. | |
|
||||
| `CODE_ASSIST_ENDPOINT` | Specifies the endpoint for the code assist server. | This is useful for development and testing. |
|
||||
| `TAVILY_API_KEY` | Your API key for the Tavily web search service. | Used to enable the `web_search` tool functionality. Example: `export TAVILY_API_KEY="tvly-your-api-key-here"` |
|
||||
|
||||
## Command-Line Arguments
|
||||
|
||||
|
|
@ -599,7 +599,7 @@ Qwen Code can execute potentially unsafe operations (like shell commands and fil
|
|||
[Sandbox](../features/sandbox) is disabled by default, but you can enable it in a few ways:
|
||||
|
||||
- Using `--sandbox` or `-s` flag.
|
||||
- Setting `GEMINI_SANDBOX` environment variable.
|
||||
- Setting `QWEN_SANDBOX` environment variable.
|
||||
- Sandbox is enabled when using `--yolo` or `--approval-mode=yolo` by default.
|
||||
|
||||
By default, it uses a pre-built `qwen-code-sandbox` Docker image.
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ The benefits of sandboxing include:
|
|||
|
||||
> [!note]
|
||||
>
|
||||
> **Naming note:** Some sandbox-related environment variables still use the `GEMINI_*` prefix for backwards compatibility.
|
||||
> **Naming note:** Some sandbox-related environment variables may have used the `GEMINI_*` prefix historically. All new environment variables use the `QWEN_*` prefix.
|
||||
|
||||
## Sandboxing methods
|
||||
|
||||
|
|
@ -68,7 +68,7 @@ The container sandbox mounts your workspace and your `~/.qwen` directory into th
|
|||
qwen -s -p "analyze the code structure"
|
||||
|
||||
# Or enable sandboxing for your shell session (recommended for CI / scripts)
|
||||
export GEMINI_SANDBOX=true # true auto-picks a provider (see notes below)
|
||||
export QWEN_SANDBOX=true # true auto-picks a provider (see notes below)
|
||||
qwen -p "run the test suite"
|
||||
|
||||
# Configure in settings.json
|
||||
|
|
@ -83,26 +83,26 @@ qwen -p "run the test suite"
|
|||
>
|
||||
> **Provider selection notes:**
|
||||
>
|
||||
> - On **macOS**, `GEMINI_SANDBOX=true` typically selects `sandbox-exec` (Seatbelt) if available.
|
||||
> - On **Linux/Windows**, `GEMINI_SANDBOX=true` requires `docker` or `podman` to be installed.
|
||||
> - To force a provider, set `GEMINI_SANDBOX=docker|podman|sandbox-exec`.
|
||||
> - On **macOS**, `QWEN_SANDBOX=true` typically selects `sandbox-exec` (Seatbelt) if available.
|
||||
> - On **Linux/Windows**, `QWEN_SANDBOX=true` requires `docker` or `podman` to be installed.
|
||||
> - To force a provider, set `QWEN_SANDBOX=docker|podman|sandbox-exec`.
|
||||
|
||||
## Configuration
|
||||
|
||||
### Enable sandboxing (in order of precedence)
|
||||
|
||||
1. **Environment variable**: `GEMINI_SANDBOX=true|false|docker|podman|sandbox-exec`
|
||||
1. **Environment variable**: `QWEN_SANDBOX=true|false|docker|podman|sandbox-exec`
|
||||
2. **Command flag / argument**: `-s`, `--sandbox`, or `--sandbox=<provider>`
|
||||
3. **Settings file**: `tools.sandbox` in your `settings.json` (e.g., `{"tools": {"sandbox": true}}`).
|
||||
|
||||
> [!important]
|
||||
>
|
||||
> If `GEMINI_SANDBOX` is set, it **overrides** the CLI flag and `settings.json`.
|
||||
> If `QWEN_SANDBOX` is set, it **overrides** the CLI flag and `settings.json`.
|
||||
|
||||
### Configure the sandbox image (Docker/Podman)
|
||||
|
||||
- **CLI flag**: `--sandbox-image <image>`
|
||||
- **Environment variable**: `GEMINI_SANDBOX_IMAGE=<image>`
|
||||
- **Environment variable**: `QWEN_SANDBOX_IMAGE=<image>`
|
||||
|
||||
If you don’t set either, Qwen Code uses the default image configured in the CLI package (for example `ghcr.io/qwenlm/qwen-code:<version>`).
|
||||
|
||||
|
|
@ -150,7 +150,7 @@ export SANDBOX_FLAGS="--flag1 --flag2=value"
|
|||
|
||||
If you want to restrict outbound network access to an allowlist, you can run a local proxy alongside the sandbox:
|
||||
|
||||
- Set `GEMINI_SANDBOX_PROXY_COMMAND=<command>`
|
||||
- Set `QWEN_SANDBOX_PROXY_COMMAND=<command>`
|
||||
- The command must start a proxy server that listens on `:::8877`
|
||||
|
||||
This is especially useful with `*-proxied` Seatbelt profiles.
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@ import { TestRig } from './test-helper.js';
|
|||
const REQUEST_TIMEOUT_MS = 60_000;
|
||||
const INITIAL_PROMPT = 'Create a quick note (smoke test).';
|
||||
const IS_SANDBOX =
|
||||
process.env['GEMINI_SANDBOX'] &&
|
||||
process.env['GEMINI_SANDBOX']!.toLowerCase() !== 'false';
|
||||
process.env['QWEN_SANDBOX'] &&
|
||||
process.env['QWEN_SANDBOX']!.toLowerCase() !== 'false';
|
||||
|
||||
type PendingRequest = {
|
||||
resolve: (value: unknown) => void;
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ export async function setup() {
|
|||
|
||||
// Environment variables for CLI integration tests
|
||||
process.env['INTEGRATION_TEST_FILE_DIR'] = runDir;
|
||||
process.env['GEMINI_CLI_INTEGRATION_TEST'] = 'true';
|
||||
process.env['QWEN_CODE_INTEGRATION_TEST'] = 'true';
|
||||
process.env['TELEMETRY_LOG_FILE'] = join(runDir, 'telemetry.log');
|
||||
|
||||
// Environment variables for SDK E2E tests
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ describe('run_shell_command', () => {
|
|||
const rig = new TestRig();
|
||||
await rig.setup('should propagate environment variables');
|
||||
|
||||
const varName = 'GEMINI_CLI_TEST_VAR';
|
||||
const varName = 'QWEN_CODE_TEST_VAR';
|
||||
const varValue = `test-value-${Math.random().toString(36).substring(7)}`;
|
||||
process.env[varName] = varValue;
|
||||
|
||||
|
|
|
|||
|
|
@ -154,7 +154,7 @@ export class TestRig {
|
|||
// Get timeout based on environment
|
||||
getDefaultTimeout() {
|
||||
if (env['CI']) return 60000; // 1 minute in CI
|
||||
if (env['GEMINI_SANDBOX']) return 30000; // 30s in containers
|
||||
if (env['QWEN_SANDBOX']) return 30000; // 30s in containers
|
||||
return 15000; // 15s locally
|
||||
}
|
||||
|
||||
|
|
@ -181,7 +181,7 @@ export class TestRig {
|
|||
otlpEndpoint: '',
|
||||
outfile: telemetryPath,
|
||||
},
|
||||
sandbox: env.GEMINI_SANDBOX !== 'false' ? env.GEMINI_SANDBOX : false,
|
||||
sandbox: env.QWEN_SANDBOX !== 'false' ? env.QWEN_SANDBOX : false,
|
||||
...options.settings, // Allow tests to override/add settings
|
||||
};
|
||||
writeFileSync(
|
||||
|
|
@ -301,7 +301,7 @@ export class TestRig {
|
|||
// Filter out telemetry output when running with Podman
|
||||
// Podman seems to output telemetry to stdout even when writing to file
|
||||
let result = stdout;
|
||||
if (env['GEMINI_SANDBOX'] === 'podman') {
|
||||
if (env['QWEN_SANDBOX'] === 'podman') {
|
||||
// Remove telemetry JSON objects from output
|
||||
// They are multi-line JSON objects that start with { and contain telemetry fields
|
||||
const lines = result.split(EOL);
|
||||
|
|
@ -727,7 +727,7 @@ export class TestRig {
|
|||
readToolLogs() {
|
||||
// For Podman, first check if telemetry file exists and has content
|
||||
// If not, fall back to parsing from stdout
|
||||
if (env['GEMINI_SANDBOX'] === 'podman') {
|
||||
if (env['QWEN_SANDBOX'] === 'podman') {
|
||||
// Try reading from file first
|
||||
const logFilePath = join(this.testDir!, 'telemetry.log');
|
||||
|
||||
|
|
|
|||
14
package.json
14
package.json
|
|
@ -32,13 +32,13 @@
|
|||
"test:scripts": "vitest run --config ./scripts/tests/vitest.config.ts",
|
||||
"test:e2e": "cross-env VERBOSE=true KEEP_OUTPUT=true npm run test:integration:sandbox:none",
|
||||
"test:integration:all": "npm run test:integration:sandbox:none && npm run test:integration:sandbox:docker && npm run test:integration:sandbox:podman",
|
||||
"test:integration:sandbox:none": "cross-env GEMINI_SANDBOX=false vitest run --root ./integration-tests",
|
||||
"test:integration:sandbox:docker": "cross-env GEMINI_SANDBOX=docker npm run build:sandbox && GEMINI_SANDBOX=docker vitest run --root ./integration-tests",
|
||||
"test:integration:sandbox:podman": "cross-env GEMINI_SANDBOX=podman vitest run --root ./integration-tests",
|
||||
"test:integration:sdk:sandbox:none": "cross-env GEMINI_SANDBOX=false vitest run --root ./integration-tests sdk-typescript",
|
||||
"test:integration:sdk:sandbox:docker": "cross-env GEMINI_SANDBOX=docker npm run build:sandbox && GEMINI_SANDBOX=docker vitest run --root ./integration-tests sdk-typescript",
|
||||
"test:integration:cli:sandbox:none": "cross-env GEMINI_SANDBOX=false vitest run --root ./integration-tests --exclude '**/sdk-typescript/**'",
|
||||
"test:integration:cli:sandbox:docker": "cross-env GEMINI_SANDBOX=docker npm run build:sandbox && GEMINI_SANDBOX=docker vitest run --root ./integration-tests --exclude '**/sdk-typescript/**'",
|
||||
"test:integration:sandbox:none": "cross-env QWEN_SANDBOX=false vitest run --root ./integration-tests",
|
||||
"test:integration:sandbox:docker": "cross-env QWEN_SANDBOX=docker npm run build:sandbox && QWEN_SANDBOX=docker vitest run --root ./integration-tests",
|
||||
"test:integration:sandbox:podman": "cross-env QWEN_SANDBOX=podman vitest run --root ./integration-tests",
|
||||
"test:integration:sdk:sandbox:none": "cross-env QWEN_SANDBOX=false vitest run --root ./integration-tests sdk-typescript",
|
||||
"test:integration:sdk:sandbox:docker": "cross-env QWEN_SANDBOX=docker npm run build:sandbox && QWEN_SANDBOX=docker vitest run --root ./integration-tests sdk-typescript",
|
||||
"test:integration:cli:sandbox:none": "cross-env QWEN_SANDBOX=false vitest run --root ./integration-tests --exclude '**/sdk-typescript/**'",
|
||||
"test:integration:cli:sandbox:docker": "cross-env QWEN_SANDBOX=docker npm run build:sandbox && QWEN_SANDBOX=docker vitest run --root ./integration-tests --exclude '**/sdk-typescript/**'",
|
||||
"test:terminal-bench": "cross-env VERBOSE=true KEEP_OUTPUT=true vitest run --config ./vitest.terminal-bench.config.ts --root ./integration-tests",
|
||||
"test:terminal-bench:oracle": "cross-env VERBOSE=true KEEP_OUTPUT=true vitest run --config ./vitest.terminal-bench.config.ts --root ./integration-tests -t 'oracle'",
|
||||
"test:terminal-bench:qwen": "cross-env VERBOSE=true KEEP_OUTPUT=true vitest run --config ./vitest.terminal-bench.config.ts --root ./integration-tests -t 'qwen'",
|
||||
|
|
|
|||
|
|
@ -2173,8 +2173,8 @@ describe('parseArguments with positional prompt', () => {
|
|||
});
|
||||
|
||||
describe('Telemetry configuration via environment variables', () => {
|
||||
it('should prioritize GEMINI_TELEMETRY_ENABLED over settings', async () => {
|
||||
vi.stubEnv('GEMINI_TELEMETRY_ENABLED', 'true');
|
||||
it('should prioritize QWEN_TELEMETRY_ENABLED over settings', async () => {
|
||||
vi.stubEnv('QWEN_TELEMETRY_ENABLED', 'true');
|
||||
process.argv = ['node', 'script.js'];
|
||||
const argv = await parseArguments();
|
||||
const settings: Settings = { telemetry: { enabled: false } };
|
||||
|
|
@ -2182,8 +2182,8 @@ describe('Telemetry configuration via environment variables', () => {
|
|||
expect(config.getTelemetryEnabled()).toBe(true);
|
||||
});
|
||||
|
||||
it('should prioritize GEMINI_TELEMETRY_TARGET over settings', async () => {
|
||||
vi.stubEnv('GEMINI_TELEMETRY_TARGET', 'gcp');
|
||||
it('should prioritize QWEN_TELEMETRY_TARGET over settings', async () => {
|
||||
vi.stubEnv('QWEN_TELEMETRY_TARGET', 'gcp');
|
||||
process.argv = ['node', 'script.js'];
|
||||
const argv = await parseArguments();
|
||||
const settings: Settings = {
|
||||
|
|
@ -2193,8 +2193,8 @@ describe('Telemetry configuration via environment variables', () => {
|
|||
expect(config.getTelemetryTarget()).toBe('gcp');
|
||||
});
|
||||
|
||||
it('should throw when GEMINI_TELEMETRY_TARGET is invalid', async () => {
|
||||
vi.stubEnv('GEMINI_TELEMETRY_TARGET', 'bogus');
|
||||
it('should throw when QWEN_TELEMETRY_TARGET is invalid', async () => {
|
||||
vi.stubEnv('QWEN_TELEMETRY_TARGET', 'bogus');
|
||||
process.argv = ['node', 'script.js'];
|
||||
const argv = await parseArguments();
|
||||
const settings: Settings = {
|
||||
|
|
@ -2206,9 +2206,9 @@ describe('Telemetry configuration via environment variables', () => {
|
|||
vi.unstubAllEnvs();
|
||||
});
|
||||
|
||||
it('should prioritize GEMINI_TELEMETRY_OTLP_ENDPOINT over settings and default env var', async () => {
|
||||
it('should prioritize QWEN_TELEMETRY_OTLP_ENDPOINT over settings and default env var', async () => {
|
||||
vi.stubEnv('OTEL_EXPORTER_OTLP_ENDPOINT', 'http://default.env.com');
|
||||
vi.stubEnv('GEMINI_TELEMETRY_OTLP_ENDPOINT', 'http://gemini.env.com');
|
||||
vi.stubEnv('QWEN_TELEMETRY_OTLP_ENDPOINT', 'http://gemini.env.com');
|
||||
process.argv = ['node', 'script.js'];
|
||||
const argv = await parseArguments();
|
||||
const settings: Settings = {
|
||||
|
|
@ -2218,8 +2218,8 @@ describe('Telemetry configuration via environment variables', () => {
|
|||
expect(config.getTelemetryOtlpEndpoint()).toBe('http://gemini.env.com');
|
||||
});
|
||||
|
||||
it('should prioritize GEMINI_TELEMETRY_OTLP_PROTOCOL over settings', async () => {
|
||||
vi.stubEnv('GEMINI_TELEMETRY_OTLP_PROTOCOL', 'http');
|
||||
it('should prioritize QWEN_TELEMETRY_OTLP_PROTOCOL over settings', async () => {
|
||||
vi.stubEnv('QWEN_TELEMETRY_OTLP_PROTOCOL', 'http');
|
||||
process.argv = ['node', 'script.js'];
|
||||
const argv = await parseArguments();
|
||||
const settings: Settings = { telemetry: { otlpProtocol: 'grpc' } };
|
||||
|
|
@ -2227,8 +2227,8 @@ describe('Telemetry configuration via environment variables', () => {
|
|||
expect(config.getTelemetryOtlpProtocol()).toBe('http');
|
||||
});
|
||||
|
||||
it('should prioritize GEMINI_TELEMETRY_LOG_PROMPTS over settings', async () => {
|
||||
vi.stubEnv('GEMINI_TELEMETRY_LOG_PROMPTS', 'false');
|
||||
it('should prioritize QWEN_TELEMETRY_LOG_PROMPTS over settings', async () => {
|
||||
vi.stubEnv('QWEN_TELEMETRY_LOG_PROMPTS', 'false');
|
||||
process.argv = ['node', 'script.js'];
|
||||
const argv = await parseArguments();
|
||||
const settings: Settings = { telemetry: { logPrompts: true } };
|
||||
|
|
@ -2236,8 +2236,8 @@ describe('Telemetry configuration via environment variables', () => {
|
|||
expect(config.getTelemetryLogPromptsEnabled()).toBe(false);
|
||||
});
|
||||
|
||||
it('should prioritize GEMINI_TELEMETRY_OUTFILE over settings', async () => {
|
||||
vi.stubEnv('GEMINI_TELEMETRY_OUTFILE', '/gemini/env/telemetry.log');
|
||||
it('should prioritize QWEN_TELEMETRY_OUTFILE over settings', async () => {
|
||||
vi.stubEnv('QWEN_TELEMETRY_OUTFILE', '/gemini/env/telemetry.log');
|
||||
process.argv = ['node', 'script.js'];
|
||||
const argv = await parseArguments();
|
||||
const settings: Settings = {
|
||||
|
|
@ -2247,8 +2247,8 @@ describe('Telemetry configuration via environment variables', () => {
|
|||
expect(config.getTelemetryOutfile()).toBe('/gemini/env/telemetry.log');
|
||||
});
|
||||
|
||||
it('should prioritize GEMINI_TELEMETRY_USE_COLLECTOR over settings', async () => {
|
||||
vi.stubEnv('GEMINI_TELEMETRY_USE_COLLECTOR', 'true');
|
||||
it('should prioritize QWEN_TELEMETRY_USE_COLLECTOR over settings', async () => {
|
||||
vi.stubEnv('QWEN_TELEMETRY_USE_COLLECTOR', 'true');
|
||||
process.argv = ['node', 'script.js'];
|
||||
const argv = await parseArguments();
|
||||
const settings: Settings = { telemetry: { useCollector: false } };
|
||||
|
|
@ -2256,8 +2256,8 @@ describe('Telemetry configuration via environment variables', () => {
|
|||
expect(config.getTelemetryUseCollector()).toBe(true);
|
||||
});
|
||||
|
||||
it('should use settings value when GEMINI_TELEMETRY_ENABLED is not set', async () => {
|
||||
vi.stubEnv('GEMINI_TELEMETRY_ENABLED', undefined);
|
||||
it('should use settings value when QWEN_TELEMETRY_ENABLED is not set', async () => {
|
||||
vi.stubEnv('QWEN_TELEMETRY_ENABLED', undefined);
|
||||
process.argv = ['node', 'script.js'];
|
||||
const argv = await parseArguments();
|
||||
const settings: Settings = { telemetry: { enabled: true } };
|
||||
|
|
@ -2265,8 +2265,8 @@ describe('Telemetry configuration via environment variables', () => {
|
|||
expect(config.getTelemetryEnabled()).toBe(true);
|
||||
});
|
||||
|
||||
it('should use settings value when GEMINI_TELEMETRY_TARGET is not set', async () => {
|
||||
vi.stubEnv('GEMINI_TELEMETRY_TARGET', undefined);
|
||||
it('should use settings value when QWEN_TELEMETRY_TARGET is not set', async () => {
|
||||
vi.stubEnv('QWEN_TELEMETRY_TARGET', undefined);
|
||||
process.argv = ['node', 'script.js'];
|
||||
const argv = await parseArguments();
|
||||
const settings: Settings = {
|
||||
|
|
@ -2276,16 +2276,16 @@ describe('Telemetry configuration via environment variables', () => {
|
|||
expect(config.getTelemetryTarget()).toBe('local');
|
||||
});
|
||||
|
||||
it("should treat GEMINI_TELEMETRY_ENABLED='1' as true", async () => {
|
||||
vi.stubEnv('GEMINI_TELEMETRY_ENABLED', '1');
|
||||
it("should treat QWEN_TELEMETRY_ENABLED='1' as true", async () => {
|
||||
vi.stubEnv('QWEN_TELEMETRY_ENABLED', '1');
|
||||
process.argv = ['node', 'script.js'];
|
||||
const argv = await parseArguments();
|
||||
const config = await loadCliConfig({}, argv, undefined, []);
|
||||
expect(config.getTelemetryEnabled()).toBe(true);
|
||||
});
|
||||
|
||||
it("should treat GEMINI_TELEMETRY_ENABLED='0' as false", async () => {
|
||||
vi.stubEnv('GEMINI_TELEMETRY_ENABLED', '0');
|
||||
it("should treat QWEN_TELEMETRY_ENABLED='0' as false", async () => {
|
||||
vi.stubEnv('QWEN_TELEMETRY_ENABLED', '0');
|
||||
process.argv = ['node', 'script.js'];
|
||||
const argv = await parseArguments();
|
||||
const config = await loadCliConfig(
|
||||
|
|
@ -2297,16 +2297,16 @@ describe('Telemetry configuration via environment variables', () => {
|
|||
expect(config.getTelemetryEnabled()).toBe(false);
|
||||
});
|
||||
|
||||
it("should treat GEMINI_TELEMETRY_LOG_PROMPTS='1' as true", async () => {
|
||||
vi.stubEnv('GEMINI_TELEMETRY_LOG_PROMPTS', '1');
|
||||
it("should treat QWEN_TELEMETRY_LOG_PROMPTS='1' as true", async () => {
|
||||
vi.stubEnv('QWEN_TELEMETRY_LOG_PROMPTS', '1');
|
||||
process.argv = ['node', 'script.js'];
|
||||
const argv = await parseArguments();
|
||||
const config = await loadCliConfig({}, argv, undefined, []);
|
||||
expect(config.getTelemetryLogPromptsEnabled()).toBe(true);
|
||||
});
|
||||
|
||||
it("should treat GEMINI_TELEMETRY_LOG_PROMPTS='false' as false", async () => {
|
||||
vi.stubEnv('GEMINI_TELEMETRY_LOG_PROMPTS', 'false');
|
||||
it("should treat QWEN_TELEMETRY_LOG_PROMPTS='false' as false", async () => {
|
||||
vi.stubEnv('QWEN_TELEMETRY_LOG_PROMPTS', 'false');
|
||||
process.argv = ['node', 'script.js'];
|
||||
const argv = await parseArguments();
|
||||
const config = await loadCliConfig(
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ function getSandboxCommand(
|
|||
|
||||
// note environment variable takes precedence over argument (from command line or settings)
|
||||
const environmentConfiguredSandbox =
|
||||
process.env['GEMINI_SANDBOX']?.toLowerCase().trim() ?? '';
|
||||
process.env['QWEN_SANDBOX']?.toLowerCase().trim() ?? '';
|
||||
sandbox =
|
||||
environmentConfiguredSandbox?.length > 0
|
||||
? environmentConfiguredSandbox
|
||||
|
|
@ -63,7 +63,7 @@ function getSandboxCommand(
|
|||
return sandbox;
|
||||
}
|
||||
throw new FatalSandboxError(
|
||||
`Missing sandbox command '${sandbox}' (from GEMINI_SANDBOX)`,
|
||||
`Missing sandbox command '${sandbox}' (from QWEN_SANDBOX)`,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -80,8 +80,8 @@ function getSandboxCommand(
|
|||
// throw an error if user requested sandbox but no command was found
|
||||
if (sandbox === true) {
|
||||
throw new FatalSandboxError(
|
||||
'GEMINI_SANDBOX is true but failed to determine command for sandbox; ' +
|
||||
'install docker or podman or specify command in GEMINI_SANDBOX',
|
||||
'QWEN_SANDBOX is true but failed to determine command for sandbox; ' +
|
||||
'install docker or podman or specify command in QWEN_SANDBOX',
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -98,7 +98,7 @@ export async function loadSandboxConfig(
|
|||
const packageJson = await getPackageJson();
|
||||
const image =
|
||||
argv.sandboxImage ??
|
||||
process.env['GEMINI_SANDBOX_IMAGE'] ??
|
||||
process.env['QWEN_SANDBOX_IMAGE'] ??
|
||||
packageJson?.config?.sandboxImageUri;
|
||||
|
||||
return command && image ? { command, image } : undefined;
|
||||
|
|
|
|||
|
|
@ -158,9 +158,9 @@ describe('Trusted Folders Loading', () => {
|
|||
expect(errors[0].message).toContain('Unexpected token');
|
||||
});
|
||||
|
||||
it('should use GEMINI_CLI_TRUSTED_FOLDERS_PATH env var if set', () => {
|
||||
it('should use QWEN_CODE_TRUSTED_FOLDERS_PATH env var if set', () => {
|
||||
const customPath = '/custom/path/to/trusted_folders.json';
|
||||
process.env['GEMINI_CLI_TRUSTED_FOLDERS_PATH'] = customPath;
|
||||
process.env['QWEN_CODE_TRUSTED_FOLDERS_PATH'] = customPath;
|
||||
|
||||
(mockFsExistsSync as Mock).mockImplementation((p) => p === customPath);
|
||||
const userContent = {
|
||||
|
|
@ -180,7 +180,7 @@ describe('Trusted Folders Loading', () => {
|
|||
]);
|
||||
expect(errors).toEqual([]);
|
||||
|
||||
delete process.env['GEMINI_CLI_TRUSTED_FOLDERS_PATH'];
|
||||
delete process.env['QWEN_CODE_TRUSTED_FOLDERS_PATH'];
|
||||
});
|
||||
|
||||
it('setValue should update the user config and save it', () => {
|
||||
|
|
|
|||
|
|
@ -22,8 +22,8 @@ export const SETTINGS_DIRECTORY_NAME = '.qwen';
|
|||
export const USER_SETTINGS_DIR = path.join(homedir(), SETTINGS_DIRECTORY_NAME);
|
||||
|
||||
export function getTrustedFoldersPath(): string {
|
||||
if (process.env['GEMINI_CLI_TRUSTED_FOLDERS_PATH']) {
|
||||
return process.env['GEMINI_CLI_TRUSTED_FOLDERS_PATH'];
|
||||
if (process.env['QWEN_CODE_TRUSTED_FOLDERS_PATH']) {
|
||||
return process.env['QWEN_CODE_TRUSTED_FOLDERS_PATH'];
|
||||
}
|
||||
return path.join(USER_SETTINGS_DIR, TRUSTED_FOLDERS_FILENAME);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -112,9 +112,9 @@ describe('gemini.tsx main function', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
// Store and clear sandbox-related env variables to ensure a consistent test environment
|
||||
originalEnvGeminiSandbox = process.env['GEMINI_SANDBOX'];
|
||||
originalEnvGeminiSandbox = process.env['QWEN_SANDBOX'];
|
||||
originalEnvSandbox = process.env['SANDBOX'];
|
||||
delete process.env['GEMINI_SANDBOX'];
|
||||
delete process.env['QWEN_SANDBOX'];
|
||||
delete process.env['SANDBOX'];
|
||||
|
||||
initialUnhandledRejectionListeners =
|
||||
|
|
@ -124,9 +124,9 @@ describe('gemini.tsx main function', () => {
|
|||
afterEach(() => {
|
||||
// Restore original env variables
|
||||
if (originalEnvGeminiSandbox !== undefined) {
|
||||
process.env['GEMINI_SANDBOX'] = originalEnvGeminiSandbox;
|
||||
process.env['QWEN_SANDBOX'] = originalEnvGeminiSandbox;
|
||||
} else {
|
||||
delete process.env['GEMINI_SANDBOX'];
|
||||
delete process.env['QWEN_SANDBOX'];
|
||||
}
|
||||
if (originalEnvSandbox !== undefined) {
|
||||
process.env['SANDBOX'] = originalEnvSandbox;
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
(allow network-inbound (local ip "localhost:9229"))
|
||||
|
||||
;; deny all outbound network traffic EXCEPT through proxy on localhost:8877
|
||||
;; set `GEMINI_SANDBOX_PROXY_COMMAND=<command>` to run proxy alongside sandbox
|
||||
;; set `QWEN_SANDBOX_PROXY_COMMAND=<command>` to run proxy alongside sandbox
|
||||
;; proxy must listen on :::8877 (see docs/examples/proxy-script.md)
|
||||
(deny network-outbound)
|
||||
(allow network-outbound (remote tcp "localhost:8877"))
|
||||
|
|
|
|||
|
|
@ -93,6 +93,6 @@
|
|||
(allow network-inbound (local ip "localhost:9229"))
|
||||
|
||||
;; allow outbound network traffic through proxy on localhost:8877
|
||||
;; set `GEMINI_SANDBOX_PROXY_COMMAND=<command>` to run proxy alongside sandbox
|
||||
;; set `QWEN_SANDBOX_PROXY_COMMAND=<command>` to run proxy alongside sandbox
|
||||
;; proxy must listen on :::8877 (see docs/examples/proxy-script.md)
|
||||
(allow network-outbound (remote tcp "localhost:8877"))
|
||||
|
|
|
|||
|
|
@ -263,8 +263,8 @@ export async function start_sandbox(
|
|||
...finalArgv.map((arg) => quote([arg])),
|
||||
].join(' '),
|
||||
);
|
||||
// start and set up proxy if GEMINI_SANDBOX_PROXY_COMMAND is set
|
||||
const proxyCommand = process.env['GEMINI_SANDBOX_PROXY_COMMAND'];
|
||||
// start and set up proxy if QWEN_SANDBOX_PROXY_COMMAND is set
|
||||
const proxyCommand = process.env['QWEN_SANDBOX_PROXY_COMMAND'];
|
||||
let proxyProcess: ChildProcess | undefined = undefined;
|
||||
let sandboxProcess: ChildProcess | undefined = undefined;
|
||||
const sandboxEnv = { ...process.env };
|
||||
|
|
@ -378,7 +378,7 @@ export async function start_sandbox(
|
|||
stdio: 'inherit',
|
||||
env: {
|
||||
...process.env,
|
||||
GEMINI_SANDBOX: config.command, // in case sandbox is enabled via flags (see config.ts under cli package)
|
||||
QWEN_SANDBOX: config.command, // in case sandbox is enabled via flags (see config.ts under cli package)
|
||||
},
|
||||
},
|
||||
);
|
||||
|
|
@ -498,8 +498,8 @@ export async function start_sandbox(
|
|||
|
||||
// copy proxy environment variables, replacing localhost with SANDBOX_PROXY_NAME
|
||||
// copy as both upper-case and lower-case as is required by some utilities
|
||||
// GEMINI_SANDBOX_PROXY_COMMAND implies HTTPS_PROXY unless HTTP_PROXY is set
|
||||
const proxyCommand = process.env['GEMINI_SANDBOX_PROXY_COMMAND'];
|
||||
// QWEN_SANDBOX_PROXY_COMMAND implies HTTPS_PROXY unless HTTP_PROXY is set
|
||||
const proxyCommand = process.env['QWEN_SANDBOX_PROXY_COMMAND'];
|
||||
|
||||
if (proxyCommand) {
|
||||
let proxy =
|
||||
|
|
@ -541,10 +541,10 @@ export async function start_sandbox(
|
|||
// name container after image, plus random suffix to avoid conflicts
|
||||
const imageName = parseImageName(image);
|
||||
const isIntegrationTest =
|
||||
process.env['GEMINI_CLI_INTEGRATION_TEST'] === 'true';
|
||||
process.env['QWEN_CODE_INTEGRATION_TEST'] === 'true';
|
||||
let containerName;
|
||||
if (isIntegrationTest) {
|
||||
containerName = `gemini-cli-integration-test-${randomBytes(4).toString(
|
||||
containerName = `qwen-code-integration-test-${randomBytes(4).toString(
|
||||
'hex',
|
||||
)}`;
|
||||
writeStderrLine(`ContainerName: ${containerName}`);
|
||||
|
|
@ -563,11 +563,11 @@ export async function start_sandbox(
|
|||
}
|
||||
args.push('--name', containerName, '--hostname', containerName);
|
||||
|
||||
// copy GEMINI_CLI_TEST_VAR for integration tests
|
||||
if (process.env['GEMINI_CLI_TEST_VAR']) {
|
||||
// copy QWEN_CODE_TEST_VAR for integration tests
|
||||
if (process.env['QWEN_CODE_TEST_VAR']) {
|
||||
args.push(
|
||||
'--env',
|
||||
`GEMINI_CLI_TEST_VAR=${process.env['GEMINI_CLI_TEST_VAR']}`,
|
||||
`QWEN_CODE_TEST_VAR=${process.env['QWEN_CODE_TEST_VAR']}`,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -716,7 +716,7 @@ export async function start_sandbox(
|
|||
let userFlag = '';
|
||||
const finalEntrypoint = entrypoint(workdir, cliArgs);
|
||||
|
||||
if (process.env['GEMINI_CLI_INTEGRATION_TEST'] === 'true') {
|
||||
if (process.env['QWEN_CODE_INTEGRATION_TEST'] === 'true') {
|
||||
args.push('--user', 'root');
|
||||
userFlag = '--user root';
|
||||
} else if (await shouldUseCurrentUserInSandbox()) {
|
||||
|
|
@ -763,7 +763,7 @@ export async function start_sandbox(
|
|||
// push container entrypoint (including args)
|
||||
args.push(...finalEntrypoint);
|
||||
|
||||
// start and set up proxy if GEMINI_SANDBOX_PROXY_COMMAND is set
|
||||
// start and set up proxy if QWEN_SANDBOX_PROXY_COMMAND is set
|
||||
let proxyProcess: ChildProcess | undefined = undefined;
|
||||
let sandboxProcess: ChildProcess | undefined = undefined;
|
||||
|
||||
|
|
|
|||
|
|
@ -79,13 +79,13 @@ describe('telemetry/config helpers', () => {
|
|||
useCollector: false,
|
||||
};
|
||||
const env = {
|
||||
GEMINI_TELEMETRY_ENABLED: '1',
|
||||
GEMINI_TELEMETRY_TARGET: 'gcp',
|
||||
GEMINI_TELEMETRY_OTLP_ENDPOINT: 'http://env:4317',
|
||||
GEMINI_TELEMETRY_OTLP_PROTOCOL: 'http',
|
||||
GEMINI_TELEMETRY_LOG_PROMPTS: 'true',
|
||||
GEMINI_TELEMETRY_OUTFILE: 'env.log',
|
||||
GEMINI_TELEMETRY_USE_COLLECTOR: 'true',
|
||||
QWEN_TELEMETRY_ENABLED: '1',
|
||||
QWEN_TELEMETRY_TARGET: 'gcp',
|
||||
QWEN_TELEMETRY_OTLP_ENDPOINT: 'http://env:4317',
|
||||
QWEN_TELEMETRY_OTLP_PROTOCOL: 'http',
|
||||
QWEN_TELEMETRY_LOG_PROMPTS: 'true',
|
||||
QWEN_TELEMETRY_OUTFILE: 'env.log',
|
||||
QWEN_TELEMETRY_USE_COLLECTOR: 'true',
|
||||
} as Record<string, string>;
|
||||
const argv = {
|
||||
telemetry: false,
|
||||
|
|
@ -133,7 +133,7 @@ describe('telemetry/config helpers', () => {
|
|||
});
|
||||
|
||||
it('throws on unknown protocol values', async () => {
|
||||
const env = { GEMINI_TELEMETRY_OTLP_PROTOCOL: 'unknown' } as Record<
|
||||
const env = { QWEN_TELEMETRY_OTLP_PROTOCOL: 'unknown' } as Record<
|
||||
string,
|
||||
string
|
||||
>;
|
||||
|
|
@ -143,7 +143,7 @@ describe('telemetry/config helpers', () => {
|
|||
});
|
||||
|
||||
it('throws on unknown target values', async () => {
|
||||
const env = { GEMINI_TELEMETRY_TARGET: 'unknown' } as Record<
|
||||
const env = { QWEN_TELEMETRY_TARGET: 'unknown' } as Record<
|
||||
string,
|
||||
string
|
||||
>;
|
||||
|
|
|
|||
|
|
@ -57,12 +57,12 @@ export async function resolveTelemetrySettings(options: {
|
|||
|
||||
const enabled =
|
||||
argv.telemetry ??
|
||||
parseBooleanEnvFlag(env['GEMINI_TELEMETRY_ENABLED']) ??
|
||||
parseBooleanEnvFlag(env['QWEN_TELEMETRY_ENABLED']) ??
|
||||
settings.enabled;
|
||||
|
||||
const rawTarget =
|
||||
(argv.telemetryTarget as string | TelemetryTarget | undefined) ??
|
||||
env['GEMINI_TELEMETRY_TARGET'] ??
|
||||
env['QWEN_TELEMETRY_TARGET'] ??
|
||||
(settings.target as string | TelemetryTarget | undefined);
|
||||
const target = parseTelemetryTargetValue(rawTarget);
|
||||
if (rawTarget !== undefined && target === undefined) {
|
||||
|
|
@ -75,13 +75,13 @@ export async function resolveTelemetrySettings(options: {
|
|||
|
||||
const otlpEndpoint =
|
||||
argv.telemetryOtlpEndpoint ??
|
||||
env['GEMINI_TELEMETRY_OTLP_ENDPOINT'] ??
|
||||
env['QWEN_TELEMETRY_OTLP_ENDPOINT'] ??
|
||||
env['OTEL_EXPORTER_OTLP_ENDPOINT'] ??
|
||||
settings.otlpEndpoint;
|
||||
|
||||
const rawProtocol =
|
||||
(argv.telemetryOtlpProtocol as string | undefined) ??
|
||||
env['GEMINI_TELEMETRY_OTLP_PROTOCOL'] ??
|
||||
env['QWEN_TELEMETRY_OTLP_PROTOCOL'] ??
|
||||
settings.otlpProtocol;
|
||||
const otlpProtocol = (['grpc', 'http'] as const).find(
|
||||
(p) => p === rawProtocol,
|
||||
|
|
@ -96,16 +96,14 @@ export async function resolveTelemetrySettings(options: {
|
|||
|
||||
const logPrompts =
|
||||
argv.telemetryLogPrompts ??
|
||||
parseBooleanEnvFlag(env['GEMINI_TELEMETRY_LOG_PROMPTS']) ??
|
||||
parseBooleanEnvFlag(env['QWEN_TELEMETRY_LOG_PROMPTS']) ??
|
||||
settings.logPrompts;
|
||||
|
||||
const outfile =
|
||||
argv.telemetryOutfile ??
|
||||
env['GEMINI_TELEMETRY_OUTFILE'] ??
|
||||
settings.outfile;
|
||||
argv.telemetryOutfile ?? env['QWEN_TELEMETRY_OUTFILE'] ?? settings.outfile;
|
||||
|
||||
const useCollector =
|
||||
parseBooleanEnvFlag(env['GEMINI_TELEMETRY_USE_COLLECTOR']) ??
|
||||
parseBooleanEnvFlag(env['QWEN_TELEMETRY_USE_COLLECTOR']) ??
|
||||
settings.useCollector;
|
||||
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -173,7 +173,7 @@ function buildImage(imageName, dockerfile) {
|
|||
).version;
|
||||
|
||||
const imageTag =
|
||||
process.env.GEMINI_SANDBOX_IMAGE_TAG || imageName.split(':')[1];
|
||||
process.env.QWEN_SANDBOX_IMAGE_TAG || imageName.split(':')[1];
|
||||
const finalImageName = `${imageName.split(':')[0]}:${imageTag}`;
|
||||
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -32,27 +32,27 @@ const argv = yargs(hideBin(process.argv)).option('q', {
|
|||
default: false,
|
||||
}).argv;
|
||||
|
||||
let geminiSandbox = process.env.GEMINI_SANDBOX;
|
||||
let qwenSandbox = process.env.QWEN_SANDBOX;
|
||||
|
||||
if (!geminiSandbox) {
|
||||
if (!qwenSandbox) {
|
||||
const userSettingsFile = join(os.homedir(), '.qwen', 'settings.json');
|
||||
if (existsSync(userSettingsFile)) {
|
||||
const settings = JSON.parse(
|
||||
stripJsonComments(readFileSync(userSettingsFile, 'utf-8')),
|
||||
);
|
||||
if (settings.sandbox) {
|
||||
geminiSandbox = settings.sandbox;
|
||||
qwenSandbox = settings.sandbox;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!geminiSandbox) {
|
||||
if (!qwenSandbox) {
|
||||
let currentDir = process.cwd();
|
||||
while (true) {
|
||||
const geminiEnv = join(currentDir, '.qwen', '.env');
|
||||
const qwenEnv = join(currentDir, '.qwen', '.env');
|
||||
const regularEnv = join(currentDir, '.env');
|
||||
if (existsSync(geminiEnv)) {
|
||||
dotenv.config({ path: geminiEnv, quiet: true });
|
||||
if (existsSync(qwenEnv)) {
|
||||
dotenv.config({ path: qwenEnv, quiet: true });
|
||||
break;
|
||||
} else if (existsSync(regularEnv)) {
|
||||
dotenv.config({ path: regularEnv, quiet: true });
|
||||
|
|
@ -64,10 +64,10 @@ if (!geminiSandbox) {
|
|||
}
|
||||
currentDir = parentDir;
|
||||
}
|
||||
geminiSandbox = process.env.GEMINI_SANDBOX;
|
||||
qwenSandbox = process.env.QWEN_SANDBOX;
|
||||
}
|
||||
|
||||
geminiSandbox = (geminiSandbox || '').toLowerCase();
|
||||
qwenSandbox = (qwenSandbox || '').toLowerCase();
|
||||
|
||||
const commandExists = (cmd) => {
|
||||
// Use 'where.exe' (not 'where') on Windows because PowerShell aliases
|
||||
|
|
@ -90,23 +90,23 @@ const commandExists = (cmd) => {
|
|||
};
|
||||
|
||||
let command = '';
|
||||
if (['1', 'true'].includes(geminiSandbox)) {
|
||||
if (['1', 'true'].includes(qwenSandbox)) {
|
||||
if (commandExists('docker')) {
|
||||
command = 'docker';
|
||||
} else if (commandExists('podman')) {
|
||||
command = 'podman';
|
||||
} else {
|
||||
console.error(
|
||||
'ERROR: install docker or podman or specify command in GEMINI_SANDBOX',
|
||||
'ERROR: install docker or podman or specify command in QWEN_SANDBOX',
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
} else if (geminiSandbox && !['0', 'false'].includes(geminiSandbox)) {
|
||||
if (commandExists(geminiSandbox)) {
|
||||
command = geminiSandbox;
|
||||
} else if (qwenSandbox && !['0', 'false'].includes(qwenSandbox)) {
|
||||
if (commandExists(qwenSandbox)) {
|
||||
command = qwenSandbox;
|
||||
} else {
|
||||
console.error(
|
||||
`ERROR: missing sandbox command '${geminiSandbox}' (from GEMINI_SANDBOX)`,
|
||||
`ERROR: missing sandbox command '${qwenSandbox}' (from QWEN_SANDBOX)`,
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ const projectHash = crypto
|
|||
// User-level .gemini directory in home
|
||||
const USER_GEMINI_DIR = path.join(os.homedir(), '.qwen');
|
||||
// Project-level .gemini directory in the workspace
|
||||
const WORKSPACE_GEMINI_DIR = path.join(projectRoot, '.qwen');
|
||||
const WORKSPACE_QWEN_DIR = path.join(projectRoot, '.qwen');
|
||||
|
||||
// Telemetry artifacts are stored in a hashed directory under the user's ~/.qwen/tmp
|
||||
export const OTEL_DIR = path.join(USER_GEMINI_DIR, 'tmp', projectHash, 'otel');
|
||||
|
|
@ -34,7 +34,7 @@ export const BIN_DIR = path.join(OTEL_DIR, 'bin');
|
|||
|
||||
// Workspace settings remain in the project's .gemini directory
|
||||
export const WORKSPACE_SETTINGS_FILE = path.join(
|
||||
WORKSPACE_GEMINI_DIR,
|
||||
WORKSPACE_QWEN_DIR,
|
||||
'settings.json',
|
||||
);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue