@midscene/shared 0.28.2 → 0.28.3

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.
Files changed (36) hide show
  1. package/dist/es/env/{model-config.mjs → decide-model-config.mjs} +52 -50
  2. package/dist/es/env/global-config-manager.mjs +91 -0
  3. package/dist/es/env/index.mjs +3 -2
  4. package/dist/es/env/model-config-manager.mjs +95 -0
  5. package/dist/es/env/parse.mjs +8 -23
  6. package/dist/es/env/types.mjs +16 -1
  7. package/dist/es/env/utils.mjs +7 -52
  8. package/dist/lib/env/{model-config.js → decide-model-config.js} +57 -52
  9. package/dist/lib/env/global-config-manager.js +125 -0
  10. package/dist/lib/env/index.js +17 -8
  11. package/dist/lib/env/model-config-manager.js +129 -0
  12. package/dist/lib/env/parse.js +9 -27
  13. package/dist/lib/env/types.js +23 -2
  14. package/dist/lib/env/utils.js +12 -69
  15. package/dist/types/env/decide-model-config.d.ts +14 -0
  16. package/dist/types/env/global-config-manager.d.ts +32 -0
  17. package/dist/types/env/helper.d.ts +1 -1
  18. package/dist/types/env/index.d.ts +2 -1
  19. package/dist/types/env/model-config-manager.d.ts +23 -0
  20. package/dist/types/env/parse.d.ts +2 -13
  21. package/dist/types/env/types.d.ts +52 -2
  22. package/dist/types/env/utils.d.ts +4 -8
  23. package/package.json +1 -1
  24. package/src/env/{model-config.ts → decide-model-config.ts} +91 -139
  25. package/src/env/global-config-manager.ts +174 -0
  26. package/src/env/helper.ts +1 -1
  27. package/src/env/index.ts +2 -1
  28. package/src/env/model-config-manager.ts +135 -0
  29. package/src/env/parse.ts +5 -24
  30. package/src/env/types.ts +61 -3
  31. package/src/env/utils.ts +7 -98
  32. package/dist/es/env/global-config.mjs +0 -192
  33. package/dist/lib/env/global-config.js +0 -229
  34. package/dist/types/env/global-config.d.ts +0 -52
  35. package/dist/types/env/model-config.d.ts +0 -70
  36. package/src/env/global-config.ts +0 -329
@@ -1,329 +0,0 @@
1
- import { getDebug } from '../logger';
2
- import { initDebugConfig } from './init-debug';
3
- import { type IModelConfig, decideModelConfig } from './model-config';
4
- import {
5
- BOOLEAN_ENV_KEYS,
6
- GLOBAL_ENV_KEYS,
7
- NUMBER_ENV_KEYS,
8
- STRING_ENV_KEYS,
9
- } from './types';
10
-
11
- import {
12
- ALL_ENV_KEYS,
13
- MATCH_BY_POSITION,
14
- MODEL_ENV_KEYS,
15
- type TGlobalConfig,
16
- type TIntent,
17
- type TModelConfigFn,
18
- } from './types';
19
-
20
- const allConfigFromEnv = (): Record<string, string | undefined> => {
21
- return ALL_ENV_KEYS.reduce(
22
- // biome-ignore lint/performance/noAccumulatingSpread: <explanation>
23
- (p, name) => ({ ...p, [name]: process.env[name] }),
24
- Object.create(null) as Record<string, string | undefined>,
25
- );
26
- };
27
-
28
- export const GLOBAL_CONFIG_MANAGER_UNINITIALIZED_FLAG =
29
- 'GLOBAL_CONFIG_MANAGER_UNINITIALIZED_FLAG';
30
-
31
- declare global {
32
- const chrome: {
33
- runtime: {
34
- id: string;
35
- };
36
- };
37
- }
38
-
39
- const isInChromeExtension = () =>
40
- typeof chrome !== 'undefined' && chrome.runtime.id;
41
-
42
- const ALL_INTENTS: TIntent[] = ['VQA', 'default', 'grounding', 'planning'];
43
- /**
44
- * Collect global configs from process.env, overrideAIConfig, modelConfig, etc.
45
- * And provider methods to get merged config value
46
- */
47
- export class GlobalConfigManager {
48
- private override:
49
- | {
50
- newConfig?: Partial<TGlobalConfig>;
51
- extendMode?: boolean;
52
- }
53
- | undefined;
54
-
55
- private initialized = false;
56
-
57
- private debugLog: (...args: any[]) => void;
58
-
59
- private modelConfigByIntent: Record<TIntent, IModelConfig | undefined> = {
60
- VQA: undefined,
61
- default: undefined,
62
- grounding: undefined,
63
- planning: undefined,
64
- };
65
-
66
- private allEnvConfig: Record<string, string | undefined> | undefined =
67
- undefined;
68
-
69
- private keysHaveBeenRead: Record<string, boolean> = {};
70
-
71
- private latestModelConfigFn?: TModelConfigFn;
72
-
73
- private modelConfigForChromeExtension: IModelConfig | undefined = undefined;
74
-
75
- constructor() {
76
- initDebugConfig();
77
- const debugLog = getDebug('ai:global-config');
78
- this.debugLog = debugLog;
79
- }
80
-
81
- private initAllEnvConfig() {
82
- const envConfig = allConfigFromEnv();
83
- this.allEnvConfig = (() => {
84
- if (this.override) {
85
- this.debugLog('initAllConfig with override from overrideAIConfig');
86
- const { newConfig, extendMode } = this.override;
87
- if (extendMode) {
88
- this.debugLog('initAllConfig with extend mode from overrideAIConfig');
89
- return { ...envConfig, ...newConfig };
90
- } else {
91
- this.debugLog(
92
- 'initAllConfig without override mode from overrideAIConfig',
93
- );
94
- return { ...newConfig };
95
- }
96
- } else {
97
- this.debugLog('initAllConfig without override from overrideAIConfig');
98
-
99
- return envConfig;
100
- }
101
- })();
102
- }
103
-
104
- private initIntentConfigFromFn() {
105
- const intentConfigFromFn: Record<
106
- TIntent,
107
- ReturnType<TModelConfigFn> | undefined
108
- > = {
109
- VQA: undefined,
110
- default: undefined,
111
- grounding: undefined,
112
- planning: undefined,
113
- };
114
-
115
- if (this.latestModelConfigFn) {
116
- for (const i of ALL_INTENTS) {
117
- const result = this.latestModelConfigFn({ intent: i });
118
- if (!result) {
119
- throw new Error(
120
- `The agent has an option named modelConfig is a function, but it return ${result} when call with intent ${i}, which should be a object.`,
121
- );
122
- }
123
- intentConfigFromFn[i] = result;
124
- }
125
- }
126
- return intentConfigFromFn;
127
- }
128
-
129
- private createUninitializedError(message: string) {
130
- const error = new Error(message);
131
- (error as any)[GLOBAL_CONFIG_MANAGER_UNINITIALIZED_FLAG] = true;
132
- return error;
133
- }
134
-
135
- reset() {
136
- console.warn(
137
- 'globalConfigManager.reset should only be called in Midscene owner unit test',
138
- );
139
- this.initialized = false;
140
- this.override = undefined;
141
- this.allEnvConfig = undefined;
142
- this.keysHaveBeenRead = {};
143
- this.modelConfigByIntent = {
144
- VQA: undefined,
145
- default: undefined,
146
- grounding: undefined,
147
- planning: undefined,
148
- };
149
- }
150
- private initModelConfigForIntent() {
151
- // init all env config
152
- this.initAllEnvConfig();
153
- // get config from agent.modelConfig()
154
- const intentConfigFromFn = this.initIntentConfigFromFn();
155
- // decide model config
156
- for (const i of ALL_INTENTS) {
157
- const result = decideModelConfig({
158
- intent: i,
159
- allConfig: this.allEnvConfig!,
160
- modelConfigFromFn: intentConfigFromFn[i] as unknown as
161
- | Record<string, string | undefined>
162
- | undefined,
163
- });
164
- this.modelConfigByIntent[i] = result;
165
- }
166
- }
167
-
168
- private initModelConfigForChromeExtension() {
169
- this.initAllEnvConfig();
170
- this.modelConfigForChromeExtension = decideModelConfig({
171
- intent: 'default',
172
- allConfig: this.allEnvConfig!,
173
- modelConfigFromFn: undefined,
174
- });
175
- }
176
-
177
- /**
178
- * init and decide all global config value,
179
- * should be called at Agent.constructor
180
- */
181
- init(modelConfigFn?: TModelConfigFn) {
182
- // skip check temporarily because of globalConfigManager will be refactored to support multiple agents
183
- // if (this.initialized) {
184
- // throw new Error('GlobalConfigManager.init should be called only once');
185
- // }
186
-
187
- this.latestModelConfigFn = modelConfigFn;
188
-
189
- this.initModelConfigForIntent();
190
-
191
- this.initialized = true;
192
- }
193
-
194
- getModelConfigByIntent(intent: TIntent) {
195
- if (!this.initialized) {
196
- // chrome extension will call llm with new Agent()
197
- if (isInChromeExtension()) {
198
- console.warn(
199
- 'globalConfigManager is not initialized but was called in chrome Extension, will get model config from env',
200
- );
201
- if (!this.modelConfigForChromeExtension) {
202
- this.initModelConfigForChromeExtension();
203
- }
204
- return this.modelConfigForChromeExtension!;
205
- }
206
- throw this.createUninitializedError(
207
- `globalConfigManager is not initialized when call getModelConfigByIntent with intent ${intent}`,
208
- );
209
- }
210
- return this.modelConfigByIntent[intent]!;
211
- }
212
-
213
- getEnvConfigValue(key: (typeof STRING_ENV_KEYS)[number]) {
214
- const allConfig = this.allEnvConfig || process.env;
215
-
216
- if (!STRING_ENV_KEYS.includes(key)) {
217
- throw new Error(`getEnvConfigValue with key ${key} is not supported.`);
218
- }
219
- if (key === MATCH_BY_POSITION) {
220
- throw new Error(
221
- 'MATCH_BY_POSITION is deprecated, use MIDSCENE_USE_VL_MODEL instead',
222
- );
223
- }
224
- const value = allConfig[key];
225
- this.keysHaveBeenRead[key] = true;
226
- if (typeof value === 'string') {
227
- return value.trim();
228
- }
229
- return value;
230
- }
231
-
232
- /**
233
- * read number only from process.env
234
- */
235
- getEnvConfigInNumber(key: (typeof NUMBER_ENV_KEYS)[number]): number {
236
- const allConfig = this.allEnvConfig || process.env;
237
- if (!NUMBER_ENV_KEYS.includes(key)) {
238
- throw new Error(`getEnvConfigInNumber with key ${key} is not supported`);
239
- }
240
- const value = allConfig[key];
241
- this.keysHaveBeenRead[key] = true;
242
- return Number(value || '');
243
- }
244
-
245
- /**
246
- * read boolean only from process.env
247
- */
248
- getEnvConfigInBoolean(key: (typeof BOOLEAN_ENV_KEYS)[number]): boolean {
249
- const allConfig = this.allEnvConfig || process.env;
250
-
251
- if (!BOOLEAN_ENV_KEYS.includes(key)) {
252
- throw new Error(`getEnvConfigInBoolean with key ${key} is not supported`);
253
- }
254
-
255
- const value = allConfig[key];
256
- this.keysHaveBeenRead[key] = true;
257
-
258
- if (!value) {
259
- return false;
260
- }
261
- if (/^(true|1)$/i.test(value)) {
262
- return true;
263
- }
264
- if (/^(false|0)$/i.test(value)) {
265
- return false;
266
- }
267
- return !!value.trim();
268
- }
269
-
270
- /**
271
- * for overrideAIConfig
272
- * can only override keys in MODEL_ENV_KEYS
273
- */
274
- registerOverride(
275
- newConfig: Partial<
276
- Record<
277
- (typeof GLOBAL_ENV_KEYS)[number] | (typeof MODEL_ENV_KEYS)[number],
278
- string
279
- >
280
- >,
281
- extendMode = false, // true: merge with global config, false: override global config
282
- ) {
283
- // skip check temporarily because of globalConfigManager will be refactored to support multiple agents
284
- // if (this.initialized) {
285
- // throw new Error(
286
- // 'overrideAIConfig must be called before Agent.constructor',
287
- // );
288
- // }
289
- for (const key in newConfig) {
290
- if (![...GLOBAL_ENV_KEYS, ...MODEL_ENV_KEYS].includes(key as never)) {
291
- throw new Error(`Failed to override AI config, invalid key: ${key}`);
292
- }
293
- const value = newConfig[key as keyof typeof newConfig];
294
- if (typeof value !== 'string') {
295
- throw new Error(
296
- `Failed to override AI config, value for key ${key} must be a string, but got with type ${typeof value}`,
297
- );
298
- }
299
- if (this.keysHaveBeenRead[key]) {
300
- console.warn(
301
- `Warning: try to override AI config with key ${key} ,but it has been read.`,
302
- );
303
- }
304
- }
305
- const savedNewConfig = extendMode
306
- ? {
307
- ...this.override?.newConfig,
308
- ...newConfig,
309
- }
310
- : newConfig;
311
-
312
- this.override = {
313
- newConfig: {
314
- ...savedNewConfig,
315
- },
316
- extendMode,
317
- };
318
-
319
- // initModelConfigForIntent will throw error if lack model related vars in process.env
320
- // so call it after initialized
321
- if (this.initialized) {
322
- this.initModelConfigForIntent();
323
- } else {
324
- this.initAllEnvConfig();
325
- // reset modelConfigForChromeExtension to force re-init when overrideAIConfig is called
326
- this.modelConfigForChromeExtension = undefined;
327
- }
328
- }
329
- }