mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-04-23 19:44:30 -07:00
feat(sdk): initial package bootstrap for SDK (#18861)
This commit is contained in:
@@ -239,6 +239,18 @@ export default tseslint.config(
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
files: ['packages/sdk/src/**/*.{ts,tsx}'],
|
||||||
|
rules: {
|
||||||
|
'no-restricted-imports': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
name: '@google/gemini-cli-sdk',
|
||||||
|
message: 'Please use relative imports within the @google/gemini-cli-sdk package.',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
files: ['packages/*/src/**/*.test.{ts,tsx}'],
|
files: ['packages/*/src/**/*.test.{ts,tsx}'],
|
||||||
plugins: {
|
plugins: {
|
||||||
|
|||||||
Generated
+21
@@ -1389,6 +1389,10 @@
|
|||||||
"resolved": "packages/core",
|
"resolved": "packages/core",
|
||||||
"link": true
|
"link": true
|
||||||
},
|
},
|
||||||
|
"node_modules/@google/gemini-cli-sdk": {
|
||||||
|
"resolved": "packages/sdk",
|
||||||
|
"link": true
|
||||||
|
},
|
||||||
"node_modules/@google/gemini-cli-test-utils": {
|
"node_modules/@google/gemini-cli-test-utils": {
|
||||||
"resolved": "packages/test-utils",
|
"resolved": "packages/test-utils",
|
||||||
"link": true
|
"link": true
|
||||||
@@ -17557,6 +17561,23 @@
|
|||||||
"uuid": "dist-node/bin/uuid"
|
"uuid": "dist-node/bin/uuid"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"packages/sdk": {
|
||||||
|
"name": "@google/gemini-cli-sdk",
|
||||||
|
"version": "0.29.0-nightly.20260203.71f46f116",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"@google/gemini-cli-core": "file:../core",
|
||||||
|
"zod": "^3.23.8",
|
||||||
|
"zod-to-json-schema": "^3.23.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"typescript": "^5.3.3",
|
||||||
|
"vitest": "^3.1.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=20"
|
||||||
|
}
|
||||||
|
},
|
||||||
"packages/test-utils": {
|
"packages/test-utils": {
|
||||||
"name": "@google/gemini-cli-test-utils",
|
"name": "@google/gemini-cli-test-utils",
|
||||||
"version": "0.30.0-nightly.20260210.a2174751d",
|
"version": "0.30.0-nightly.20260210.a2174751d",
|
||||||
|
|||||||
@@ -4,12 +4,12 @@
|
|||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { Config } from '@google/gemini-cli-core';
|
import type { Config, AuthType } from '@google/gemini-cli-core';
|
||||||
import {
|
import {
|
||||||
AuthType,
|
|
||||||
debugLogger,
|
debugLogger,
|
||||||
OutputFormat,
|
OutputFormat,
|
||||||
ExitCodes,
|
ExitCodes,
|
||||||
|
getAuthTypeFromEnv,
|
||||||
} from '@google/gemini-cli-core';
|
} from '@google/gemini-cli-core';
|
||||||
import { USER_SETTINGS_PATH } from './config/settings.js';
|
import { USER_SETTINGS_PATH } from './config/settings.js';
|
||||||
import { validateAuthMethod } from './config/auth.js';
|
import { validateAuthMethod } from './config/auth.js';
|
||||||
@@ -17,19 +17,6 @@ import { type LoadedSettings } from './config/settings.js';
|
|||||||
import { handleError } from './utils/errors.js';
|
import { handleError } from './utils/errors.js';
|
||||||
import { runExitCleanup } from './utils/cleanup.js';
|
import { runExitCleanup } from './utils/cleanup.js';
|
||||||
|
|
||||||
function getAuthTypeFromEnv(): AuthType | undefined {
|
|
||||||
if (process.env['GOOGLE_GENAI_USE_GCA'] === 'true') {
|
|
||||||
return AuthType.LOGIN_WITH_GOOGLE;
|
|
||||||
}
|
|
||||||
if (process.env['GOOGLE_GENAI_USE_VERTEXAI'] === 'true') {
|
|
||||||
return AuthType.USE_VERTEX_AI;
|
|
||||||
}
|
|
||||||
if (process.env['GEMINI_API_KEY']) {
|
|
||||||
return AuthType.USE_GEMINI;
|
|
||||||
}
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function validateNonInteractiveAuth(
|
export async function validateNonInteractiveAuth(
|
||||||
configuredAuthType: AuthType | undefined,
|
configuredAuthType: AuthType | undefined,
|
||||||
useExternalAuth: boolean | undefined,
|
useExternalAuth: boolean | undefined,
|
||||||
|
|||||||
@@ -56,6 +56,27 @@ export enum AuthType {
|
|||||||
COMPUTE_ADC = 'compute-default-credentials',
|
COMPUTE_ADC = 'compute-default-credentials',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detects the best authentication type based on environment variables.
|
||||||
|
*
|
||||||
|
* Checks in order:
|
||||||
|
* 1. GOOGLE_GENAI_USE_GCA=true -> LOGIN_WITH_GOOGLE
|
||||||
|
* 2. GOOGLE_GENAI_USE_VERTEXAI=true -> USE_VERTEX_AI
|
||||||
|
* 3. GEMINI_API_KEY -> USE_GEMINI
|
||||||
|
*/
|
||||||
|
export function getAuthTypeFromEnv(): AuthType | undefined {
|
||||||
|
if (process.env['GOOGLE_GENAI_USE_GCA'] === 'true') {
|
||||||
|
return AuthType.LOGIN_WITH_GOOGLE;
|
||||||
|
}
|
||||||
|
if (process.env['GOOGLE_GENAI_USE_VERTEXAI'] === 'true') {
|
||||||
|
return AuthType.USE_VERTEX_AI;
|
||||||
|
}
|
||||||
|
if (process.env['GEMINI_API_KEY']) {
|
||||||
|
return AuthType.USE_GEMINI;
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
export type ContentGeneratorConfig = {
|
export type ContentGeneratorConfig = {
|
||||||
apiKey?: string;
|
apiKey?: string;
|
||||||
vertexai?: boolean;
|
vertexai?: boolean;
|
||||||
|
|||||||
@@ -140,6 +140,7 @@ export * from './prompts/mcp-prompts.js';
|
|||||||
export * from './agents/types.js';
|
export * from './agents/types.js';
|
||||||
export * from './agents/agentLoader.js';
|
export * from './agents/agentLoader.js';
|
||||||
export * from './agents/local-executor.js';
|
export * from './agents/local-executor.js';
|
||||||
|
export * from './agents/agent-scheduler.js';
|
||||||
|
|
||||||
// Export specific tool logic
|
// Export specific tool logic
|
||||||
export * from './tools/read-file.js';
|
export * from './tools/read-file.js';
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
# @google/gemini-cli-sdk
|
||||||
|
|
||||||
|
The Gemini CLI SDK provides a programmatic interface to interact with Gemini
|
||||||
|
models and tools.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install @google/gemini-cli-sdk
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { GeminiCliAgent } from '@google/gemini-cli-sdk';
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
const agent = new GeminiCliAgent({
|
||||||
|
instructions: 'You are a helpful assistant.',
|
||||||
|
});
|
||||||
|
|
||||||
|
const controller = new AbortController();
|
||||||
|
const signal = controller.signal;
|
||||||
|
|
||||||
|
// Stream responses from the agent
|
||||||
|
const stream = agent.sendStream('Why is the sky blue?', signal);
|
||||||
|
|
||||||
|
for await (const chunk of stream) {
|
||||||
|
if (chunk.type === 'content') {
|
||||||
|
process.stdout.write(chunk.value.text || '');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
main().catch(console.error);
|
||||||
|
```
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright 2026 Google LLC
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { GeminiCliAgent, tool, z } from '../src/index.js';
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
const myTool = tool(
|
||||||
|
{
|
||||||
|
name: 'add',
|
||||||
|
description: 'Add two numbers.',
|
||||||
|
inputSchema: z.object({
|
||||||
|
a: z.number().describe('the first number'),
|
||||||
|
b: z.number().describe('the second number'),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
async ({ a, b }) => {
|
||||||
|
console.log(`Tool 'add' called with a=${a}, b=${b}`);
|
||||||
|
return { result: a + b };
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const agent = new GeminiCliAgent({
|
||||||
|
instructions: 'Make sure to always talk like a pirate.',
|
||||||
|
tools: [myTool],
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("Sending prompt: 'add 5 + 6'");
|
||||||
|
for await (const chunk of agent.sendStream(
|
||||||
|
'add 5 + 6 and tell me a story involving the result',
|
||||||
|
)) {
|
||||||
|
console.log(JSON.stringify(chunk, null, 2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
main().catch(console.error);
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright 2026 Google LLC
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
export * from './src/index.js';
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
{
|
||||||
|
"name": "@google/gemini-cli-sdk",
|
||||||
|
"version": "0.29.0-nightly.20260203.71f46f116",
|
||||||
|
"description": "Gemini CLI SDK",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/google-gemini/gemini-cli.git"
|
||||||
|
},
|
||||||
|
"type": "module",
|
||||||
|
"main": "dist/index.js",
|
||||||
|
"types": "dist/index.d.ts",
|
||||||
|
"scripts": {
|
||||||
|
"build": "node ../../scripts/build_package.js",
|
||||||
|
"lint": "eslint . --ext .ts,.tsx",
|
||||||
|
"format": "prettier --write .",
|
||||||
|
"test": "vitest run",
|
||||||
|
"test:ci": "vitest run",
|
||||||
|
"typecheck": "tsc --noEmit"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"dist"
|
||||||
|
],
|
||||||
|
"dependencies": {
|
||||||
|
"@google/gemini-cli-core": "file:../core",
|
||||||
|
"zod": "^3.23.8",
|
||||||
|
"zod-to-json-schema": "^3.23.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"typescript": "^5.3.3",
|
||||||
|
"vitest": "^3.1.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=20"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,130 @@
|
|||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright 2026 Google LLC
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {
|
||||||
|
Config,
|
||||||
|
type ConfigParameters,
|
||||||
|
PREVIEW_GEMINI_MODEL_AUTO,
|
||||||
|
GeminiEventType,
|
||||||
|
type ToolCallRequestInfo,
|
||||||
|
type ServerGeminiStreamEvent,
|
||||||
|
type GeminiClient,
|
||||||
|
scheduleAgentTools,
|
||||||
|
getAuthTypeFromEnv,
|
||||||
|
AuthType,
|
||||||
|
} from '@google/gemini-cli-core';
|
||||||
|
|
||||||
|
import { type Tool, SdkTool, type z } from './tool.js';
|
||||||
|
|
||||||
|
export interface GeminiCliAgentOptions {
|
||||||
|
instructions: string;
|
||||||
|
tools?: Array<Tool<z.ZodType>>;
|
||||||
|
model?: string;
|
||||||
|
cwd?: string;
|
||||||
|
debug?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class GeminiCliAgent {
|
||||||
|
private readonly config: Config;
|
||||||
|
private readonly tools: Array<Tool<z.ZodType>>;
|
||||||
|
|
||||||
|
constructor(options: GeminiCliAgentOptions) {
|
||||||
|
const cwd = options.cwd || process.cwd();
|
||||||
|
this.tools = options.tools || [];
|
||||||
|
|
||||||
|
const configParams: ConfigParameters = {
|
||||||
|
sessionId: `sdk-${Date.now()}`,
|
||||||
|
targetDir: cwd,
|
||||||
|
cwd,
|
||||||
|
debugMode: options.debug ?? false,
|
||||||
|
model: options.model || PREVIEW_GEMINI_MODEL_AUTO,
|
||||||
|
userMemory: options.instructions,
|
||||||
|
// Minimal config
|
||||||
|
enableHooks: false,
|
||||||
|
mcpEnabled: false,
|
||||||
|
extensionsEnabled: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
this.config = new Config(configParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
async *sendStream(
|
||||||
|
prompt: string,
|
||||||
|
signal?: AbortSignal,
|
||||||
|
): AsyncGenerator<ServerGeminiStreamEvent> {
|
||||||
|
// Lazy initialization of auth and client
|
||||||
|
if (!this.config.getContentGenerator()) {
|
||||||
|
const authType = getAuthTypeFromEnv() || AuthType.COMPUTE_ADC;
|
||||||
|
|
||||||
|
await this.config.refreshAuth(authType);
|
||||||
|
await this.config.initialize();
|
||||||
|
|
||||||
|
// Register tools now that registry exists
|
||||||
|
const registry = this.config.getToolRegistry();
|
||||||
|
const messageBus = this.config.getMessageBus();
|
||||||
|
|
||||||
|
for (const toolDef of this.tools) {
|
||||||
|
const sdkTool = new SdkTool(toolDef, messageBus);
|
||||||
|
registry.registerTool(sdkTool);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const client = this.config.getGeminiClient();
|
||||||
|
|
||||||
|
let request: Parameters<GeminiClient['sendMessageStream']>[0] = [
|
||||||
|
{ text: prompt },
|
||||||
|
];
|
||||||
|
const abortSignal = signal ?? new AbortController().signal;
|
||||||
|
const sessionId = this.config.getSessionId();
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
// sendMessageStream returns AsyncGenerator<ServerGeminiStreamEvent, Turn>
|
||||||
|
const stream = client.sendMessageStream(request, abortSignal, sessionId);
|
||||||
|
|
||||||
|
const toolCallsToSchedule: ToolCallRequestInfo[] = [];
|
||||||
|
|
||||||
|
for await (const event of stream) {
|
||||||
|
yield event;
|
||||||
|
if (event.type === GeminiEventType.ToolCallRequest) {
|
||||||
|
const toolCall = event.value;
|
||||||
|
let args = toolCall.args;
|
||||||
|
if (typeof args === 'string') {
|
||||||
|
args = JSON.parse(args);
|
||||||
|
}
|
||||||
|
toolCallsToSchedule.push({
|
||||||
|
...toolCall,
|
||||||
|
args,
|
||||||
|
isClientInitiated: false,
|
||||||
|
prompt_id: sessionId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (toolCallsToSchedule.length === 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const completedCalls = await scheduleAgentTools(
|
||||||
|
this.config,
|
||||||
|
toolCallsToSchedule,
|
||||||
|
{
|
||||||
|
schedulerId: sessionId,
|
||||||
|
toolRegistry: this.config.getToolRegistry(),
|
||||||
|
signal: abortSignal,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const functionResponses = completedCalls.flatMap(
|
||||||
|
(call) => call.response.responseParts,
|
||||||
|
);
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||||
|
request = functionResponses as unknown as Parameters<
|
||||||
|
GeminiClient['sendMessageStream']
|
||||||
|
>[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright 2026 Google LLC
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
export * from './agent.js';
|
||||||
|
export * from './tool.js';
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright 2026 Google LLC
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { z } from 'zod';
|
||||||
|
import { zodToJsonSchema } from 'zod-to-json-schema';
|
||||||
|
import {
|
||||||
|
BaseDeclarativeTool,
|
||||||
|
BaseToolInvocation,
|
||||||
|
type ToolResult,
|
||||||
|
type ToolInvocation,
|
||||||
|
Kind,
|
||||||
|
type MessageBus,
|
||||||
|
} from '@google/gemini-cli-core';
|
||||||
|
|
||||||
|
export { z };
|
||||||
|
|
||||||
|
export interface ToolDefinition<T extends z.ZodType> {
|
||||||
|
name: string;
|
||||||
|
description: string;
|
||||||
|
inputSchema: T;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Tool<T extends z.ZodType> extends ToolDefinition<T> {
|
||||||
|
action: (params: z.infer<T>) => Promise<unknown>;
|
||||||
|
}
|
||||||
|
|
||||||
|
class SdkToolInvocation<T extends z.ZodType> extends BaseToolInvocation<
|
||||||
|
z.infer<T>,
|
||||||
|
ToolResult
|
||||||
|
> {
|
||||||
|
constructor(
|
||||||
|
params: z.infer<T>,
|
||||||
|
messageBus: MessageBus,
|
||||||
|
private readonly action: (params: z.infer<T>) => Promise<unknown>,
|
||||||
|
toolName: string,
|
||||||
|
) {
|
||||||
|
super(params, messageBus, toolName);
|
||||||
|
}
|
||||||
|
|
||||||
|
getDescription(): string {
|
||||||
|
return `Executing ${this._toolName}...`;
|
||||||
|
}
|
||||||
|
|
||||||
|
async execute(
|
||||||
|
_signal: AbortSignal,
|
||||||
|
_updateOutput?: (output: string) => void,
|
||||||
|
): Promise<ToolResult> {
|
||||||
|
try {
|
||||||
|
const result = await this.action(this.params);
|
||||||
|
const output =
|
||||||
|
typeof result === 'string' ? result : JSON.stringify(result, null, 2);
|
||||||
|
return {
|
||||||
|
llmContent: output,
|
||||||
|
returnDisplay: output,
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
const errorMessage =
|
||||||
|
error instanceof Error ? error.message : String(error);
|
||||||
|
return {
|
||||||
|
llmContent: `Error: ${errorMessage}`,
|
||||||
|
returnDisplay: `Error: ${errorMessage}`,
|
||||||
|
error: {
|
||||||
|
message: errorMessage,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SdkTool<T extends z.ZodType> extends BaseDeclarativeTool<
|
||||||
|
z.infer<T>,
|
||||||
|
ToolResult
|
||||||
|
> {
|
||||||
|
constructor(
|
||||||
|
private readonly definition: Tool<T>,
|
||||||
|
messageBus: MessageBus,
|
||||||
|
) {
|
||||||
|
super(
|
||||||
|
definition.name,
|
||||||
|
definition.name,
|
||||||
|
definition.description,
|
||||||
|
Kind.Other,
|
||||||
|
zodToJsonSchema(definition.inputSchema),
|
||||||
|
messageBus,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected createInvocation(
|
||||||
|
params: z.infer<T>,
|
||||||
|
messageBus: MessageBus,
|
||||||
|
toolName?: string,
|
||||||
|
): ToolInvocation<z.infer<T>, ToolResult> {
|
||||||
|
return new SdkToolInvocation(
|
||||||
|
params,
|
||||||
|
messageBus,
|
||||||
|
this.definition.action,
|
||||||
|
toolName || this.name,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function tool<T extends z.ZodType>(
|
||||||
|
definition: ToolDefinition<T>,
|
||||||
|
action: (params: z.infer<T>) => Promise<unknown>,
|
||||||
|
): Tool<T> {
|
||||||
|
return {
|
||||||
|
...definition,
|
||||||
|
action,
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"extends": "../../tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "dist",
|
||||||
|
"composite": true,
|
||||||
|
"lib": ["DOM", "DOM.Iterable", "ES2023"],
|
||||||
|
"types": ["node", "vitest/globals"]
|
||||||
|
},
|
||||||
|
"include": ["index.ts", "src/**/*.ts", "package.json"],
|
||||||
|
"exclude": ["node_modules", "dist"],
|
||||||
|
"references": [{ "path": "../core" }]
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright 2026 Google LLC
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { defineConfig } from 'vitest/config';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
test: {
|
||||||
|
globals: true,
|
||||||
|
environment: 'node',
|
||||||
|
},
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user