feat(core): Enhance environment logic and introduce MIDSCENE_REPORT_TAG_NAME for customizable report name prefixes (#168)

This commit is contained in:
Zhou xiao 2024-11-26 16:23:04 +08:00 committed by GitHub
parent e7a58b3b24
commit ebc88adc07
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 89 additions and 74 deletions

View File

@ -8,6 +8,7 @@ export default defineConfig({
format: 'cjs',
input: {
index: 'src/index.ts',
env: 'src/env.ts',
utils: 'src/utils.ts',
'ai-model': 'src/ai-model/index.ts',
},

View File

@ -11,12 +11,14 @@
"files": ["dist", "report", "README.md"],
"exports": {
".": "./dist/lib/index.js",
"./env": "./dist/lib/env.js",
"./utils": "./dist/lib/utils.js",
"./ai-model": "./dist/lib/ai-model.js"
},
"typesVersions": {
"*": {
".": ["./dist/lib/types/index.d.ts"],
"env": ["./dist/lib/types/env.d.ts"],
"utils": ["./dist/lib/types/utils.d.ts"],
"ai-model": ["./dist/lib/types/ai-model.d.ts"]
}

View File

@ -1,5 +1,5 @@
import assert from 'node:assert';
import { MIDSCENE_MODEL_NAME, getAIConfig } from '@/ai-model/openai';
import { MIDSCENE_MODEL_NAME, getAIConfig } from '@/env';
import type {
ExecutionDump,
ExecutionTask,

View File

@ -1,3 +1,4 @@
import { MIDSCENE_MODEL_TEXT_ONLY, getAIConfig } from '@/env';
import type {
ChatCompletionContentPart,
ChatCompletionSystemMessageParam,
@ -12,12 +13,7 @@ import {
preferCozeModel,
transformOpenAiArgsToCoze,
} from './coze';
import {
MIDSCENE_MODEL_TEXT_ONLY,
callToGetJSONObject,
getAIConfig,
preferOpenAIModel,
} from './openai';
import { callToGetJSONObject, preferOpenAIModel } from './openai';
export type AIArgs = [
ChatCompletionSystemMessageParam,

View File

@ -3,71 +3,23 @@ import { AIResponseFormat } from '@/types';
import { ifInBrowser } from '@midscene/shared/utils';
import OpenAI, { type ClientOptions, AzureOpenAI } from 'openai';
import type { ChatCompletionMessageParam } from 'openai/resources';
import {
MIDSCENE_DANGEROUSLY_PRINT_ALL_CONFIG,
MIDSCENE_DEBUG_AI_PROFILE,
MIDSCENE_LANGSMITH_DEBUG,
MIDSCENE_MODEL_NAME,
MIDSCENE_OPENAI_INIT_CONFIG_JSON,
OPENAI_API_KEY,
OPENAI_BASE_URL,
OPENAI_USE_AZURE,
allAIConfig,
getAIConfig,
} from '../../env';
import { AIActionType } from '../common';
import { findElementSchema } from '../prompt/element_inspector';
import { planSchema } from '../prompt/planning';
import { assertSchema } from '../prompt/util';
// config keys
export const MIDSCENE_OPENAI_INIT_CONFIG_JSON =
'MIDSCENE_OPENAI_INIT_CONFIG_JSON';
export const MIDSCENE_MODEL_NAME = 'MIDSCENE_MODEL_NAME';
export const MIDSCENE_LANGSMITH_DEBUG = 'MIDSCENE_LANGSMITH_DEBUG';
export const MIDSCENE_DEBUG_AI_PROFILE = 'MIDSCENE_DEBUG_AI_PROFILE';
export const MIDSCENE_DANGEROUSLY_PRINT_ALL_CONFIG =
'MIDSCENE_DANGEROUSLY_PRINT_ALL_CONFIG';
export const MIDSCENE_DEBUG_MODE = 'MIDSCENE_DEBUG_MODE';
export const OPENAI_API_KEY = 'OPENAI_API_KEY';
export const OPENAI_BASE_URL = 'OPENAI_BASE_URL';
export const MIDSCENE_MODEL_TEXT_ONLY = 'MIDSCENE_MODEL_TEXT_ONLY';
export const OPENAI_USE_AZURE = 'OPENAI_USE_AZURE';
export const MIDSCENE_CACHE = 'MIDSCENE_CACHE';
export const MATCH_BY_POSITION = 'MATCH_BY_POSITION';
const allConfigFromEnv = () => {
return {
[MIDSCENE_OPENAI_INIT_CONFIG_JSON]:
process.env[MIDSCENE_OPENAI_INIT_CONFIG_JSON] || undefined,
[MIDSCENE_MODEL_NAME]: process.env[MIDSCENE_MODEL_NAME] || undefined,
[MIDSCENE_DEBUG_MODE]: process.env[MIDSCENE_DEBUG_MODE] || undefined,
[MIDSCENE_LANGSMITH_DEBUG]:
process.env[MIDSCENE_LANGSMITH_DEBUG] || undefined,
[MIDSCENE_DEBUG_AI_PROFILE]:
process.env[MIDSCENE_DEBUG_AI_PROFILE] || undefined,
[MIDSCENE_DANGEROUSLY_PRINT_ALL_CONFIG]:
process.env[MIDSCENE_DANGEROUSLY_PRINT_ALL_CONFIG] || undefined,
[OPENAI_API_KEY]: process.env[OPENAI_API_KEY] || undefined,
[OPENAI_BASE_URL]: process.env[OPENAI_BASE_URL] || undefined,
[MIDSCENE_MODEL_TEXT_ONLY]:
process.env[MIDSCENE_MODEL_TEXT_ONLY] || undefined,
[OPENAI_USE_AZURE]: process.env[OPENAI_USE_AZURE] || undefined,
[MIDSCENE_CACHE]: process.env[MIDSCENE_CACHE] || undefined,
[MATCH_BY_POSITION]: process.env[MATCH_BY_POSITION] || undefined,
};
};
let userConfig: ReturnType<typeof allConfigFromEnv> = {} as any;
export const getAIConfig = (
configKey: keyof typeof userConfig,
): string | undefined => {
if (typeof userConfig[configKey] !== 'undefined') {
return userConfig[configKey];
}
return allConfigFromEnv()[configKey];
};
export const allAIConfig = () => {
return { ...allConfigFromEnv(), ...userConfig };
};
export const overrideAIConfig = (
newConfig: ReturnType<typeof allConfigFromEnv>,
extendMode?: boolean,
) => {
userConfig = extendMode ? { ...userConfig, ...newConfig } : { ...newConfig };
};
export function preferOpenAIModel(preferVendor?: 'coze' | 'openAI') {
if (preferVendor && preferVendor !== 'openAI') return false;
if (getAIConfig(OPENAI_API_KEY)) return true;

View File

@ -1,5 +1,5 @@
import { MATCH_BY_POSITION, getAIConfig } from '@/env';
import type { ResponseFormatJSONSchema } from 'openai/resources';
import { MATCH_BY_POSITION, getAIConfig } from '../openai';
export function systemPromptToFindElement() {
if (getAIConfig(MATCH_BY_POSITION)) {

View File

@ -1,5 +1,5 @@
import { MATCH_BY_POSITION, getAIConfig } from '@/env';
import type { ResponseFormatJSONSchema } from 'openai/resources';
import { MATCH_BY_POSITION, getAIConfig } from '../openai';
const quickAnswerFormat = () => {
const matchByPosition = getAIConfig(MATCH_BY_POSITION);

View File

@ -1,4 +1,5 @@
import assert from 'node:assert';
import { MATCH_BY_POSITION, getAIConfig } from '@/env';
import { imageInfoOfBase64 } from '@/image';
import type {
BaseElement,
@ -9,7 +10,6 @@ import type {
UISection,
} from '@/types';
import type { ResponseFormatJSONSchema } from 'openai/resources';
import { MATCH_BY_POSITION, getAIConfig } from '../openai';
const characteristic =
'You are a versatile professional in software UI design and testing. Your outstanding contributions will impact the user experience of billions of users.';

View File

@ -0,0 +1,62 @@
// config keys
export const MIDSCENE_OPENAI_INIT_CONFIG_JSON =
'MIDSCENE_OPENAI_INIT_CONFIG_JSON';
export const MIDSCENE_MODEL_NAME = 'MIDSCENE_MODEL_NAME';
export const MIDSCENE_LANGSMITH_DEBUG = 'MIDSCENE_LANGSMITH_DEBUG';
export const MIDSCENE_DEBUG_AI_PROFILE = 'MIDSCENE_DEBUG_AI_PROFILE';
export const MIDSCENE_DANGEROUSLY_PRINT_ALL_CONFIG =
'MIDSCENE_DANGEROUSLY_PRINT_ALL_CONFIG';
export const MIDSCENE_DEBUG_MODE = 'MIDSCENE_DEBUG_MODE';
export const OPENAI_API_KEY = 'OPENAI_API_KEY';
export const OPENAI_BASE_URL = 'OPENAI_BASE_URL';
export const MIDSCENE_MODEL_TEXT_ONLY = 'MIDSCENE_MODEL_TEXT_ONLY';
export const OPENAI_USE_AZURE = 'OPENAI_USE_AZURE';
export const MIDSCENE_CACHE = 'MIDSCENE_CACHE';
export const MATCH_BY_POSITION = 'MATCH_BY_POSITION';
export const MIDSCENE_REPORT_TAG_NAME = 'MIDSCENE_REPORT_TAG_NAME';
const allConfigFromEnv = () => {
return {
[MIDSCENE_OPENAI_INIT_CONFIG_JSON]:
process.env[MIDSCENE_OPENAI_INIT_CONFIG_JSON] || undefined,
[MIDSCENE_MODEL_NAME]: process.env[MIDSCENE_MODEL_NAME] || undefined,
[MIDSCENE_DEBUG_MODE]: process.env[MIDSCENE_DEBUG_MODE] || undefined,
[MIDSCENE_LANGSMITH_DEBUG]:
process.env[MIDSCENE_LANGSMITH_DEBUG] || undefined,
[MIDSCENE_DEBUG_AI_PROFILE]:
process.env[MIDSCENE_DEBUG_AI_PROFILE] || undefined,
[MIDSCENE_DANGEROUSLY_PRINT_ALL_CONFIG]:
process.env[MIDSCENE_DANGEROUSLY_PRINT_ALL_CONFIG] || undefined,
[OPENAI_API_KEY]: process.env[OPENAI_API_KEY] || undefined,
[OPENAI_BASE_URL]: process.env[OPENAI_BASE_URL] || undefined,
[MIDSCENE_MODEL_TEXT_ONLY]:
process.env[MIDSCENE_MODEL_TEXT_ONLY] || undefined,
[OPENAI_USE_AZURE]: process.env[OPENAI_USE_AZURE] || undefined,
[MIDSCENE_CACHE]: process.env[MIDSCENE_CACHE] || undefined,
[MATCH_BY_POSITION]: process.env[MATCH_BY_POSITION] || undefined,
[MIDSCENE_REPORT_TAG_NAME]:
process.env[MIDSCENE_REPORT_TAG_NAME] || undefined,
};
};
let userConfig: ReturnType<typeof allConfigFromEnv> = {} as any;
export const getAIConfig = (
configKey: keyof typeof userConfig,
): string | undefined => {
if (typeof userConfig[configKey] !== 'undefined') {
return userConfig[configKey];
}
return allConfigFromEnv()[configKey];
};
export const allAIConfig = () => {
return { ...allConfigFromEnv(), ...userConfig };
};
export const overrideAIConfig = (
newConfig: ReturnType<typeof allConfigFromEnv>,
extendMode?: boolean,
) => {
userConfig = extendMode ? { ...userConfig, ...newConfig } : { ...newConfig };
};

View File

@ -1,5 +1,5 @@
import { Executor } from './action/executor';
import { allAIConfig, getAIConfig, overrideAIConfig } from './ai-model/openai';
import { allAIConfig, getAIConfig, overrideAIConfig } from './env';
import Insight from './insight';
import { getElement, getSection } from './query';
import { getLogDirByType, getVersion, setLogDir } from './utils';

View File

@ -3,7 +3,7 @@ import { randomUUID } from 'node:crypto';
/* eslint-disable @typescript-eslint/ban-types */
import { existsSync } from 'node:fs';
import { join } from 'node:path';
import { MIDSCENE_MODEL_NAME, getAIConfig } from '@/ai-model/openai';
import { MIDSCENE_MODEL_NAME, getAIConfig } from '@/env';
import type {
BaseElement,
DumpMeta,

View File

@ -9,7 +9,7 @@ import {
MIDSCENE_DEBUG_MODE,
MIDSCENE_OPENAI_INIT_CONFIG_JSON,
getAIConfig,
} from './ai-model/openai';
} from './env';
import type { Rect, ReportDumpWithAttributes } from './types';
let logDir = join(process.cwd(), './midscene_run/');

View File

@ -4,6 +4,7 @@ import path from 'node:path';
import type { ElementInfo } from '@/extractor';
import type { StaticPage } from '@/playground';
import type { PlaywrightParserOpt, UIContext } from '@midscene/core';
import { MIDSCENE_REPORT_TAG_NAME, getAIConfig } from '@midscene/core/env';
import { uploadTestInfoToServer } from '@midscene/core/utils';
import { NodeType } from '@midscene/shared/constants';
import { findNearestPackageJson } from '@midscene/shared/fs';
@ -107,8 +108,9 @@ async function alignElements(
}
export function reportFileName(tag = 'web') {
const reportTagName = getAIConfig(MIDSCENE_REPORT_TAG_NAME);
const dateTimeInFileName = dayjs().format('YYYY-MM-DD_HH-mm-ss-SSS');
return `${tag}-${dateTimeInFileName}`;
return `${reportTagName || tag}-${dateTimeInFileName}`;
}
export function printReportMsg(filepath: string) {