@modelprofile.com/flexharness-models 10.10.0 → 10.12.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.
@@ -1,5 +1,5 @@
1
1
  import type * as plugins from './plugins.js';
2
- import type { TSmartAiProviderOptions } from './interfaces.js';
2
+ import type { TSmartAiLanguageModel, TSmartAiProviderOptions } from './interfaces.js';
3
3
  export type TSmartAiMessageCacheProvider = 'anthropic' | 'openrouter' | 'bedrock' | 'openaiCompatible' | 'copilot' | 'alibaba';
4
4
  export type TSmartAiCacheRetention = 'ephemeral' | '1h' | 'in_memory' | '24h';
5
5
  export interface ISmartAiCacheOptions {
@@ -9,6 +9,8 @@ export interface ISmartAiCacheOptions {
9
9
  key?: string;
10
10
  /** Short retention is the default; longer retention is opt-in. */
11
11
  retention?: TSmartAiCacheRetention;
12
+ /** Configured maximum idle scheduling budget, not a promise of cache retention or a cache hit. */
13
+ warmDurationMs?: number;
12
14
  }
13
15
  export type TSmartAiCacheSetting = boolean | 'auto' | ISmartAiCacheOptions;
14
16
  export declare function mergeSmartAiProviderOptions(defaults?: TSmartAiProviderOptions, overrides?: TSmartAiProviderOptions): TSmartAiProviderOptions | undefined;
@@ -29,3 +31,36 @@ export declare function applySmartAiCacheProviderOptions(input: {
29
31
  cache?: TSmartAiCacheSetting;
30
32
  sessionId?: string;
31
33
  }): TSmartAiProviderOptions | undefined;
34
+ /** Observation at the model dispatch boundary; no field certifies a cache write or hit. */
35
+ export interface ISmartAiCacheDispatch {
36
+ dispatchedAt: number;
37
+ /** Configured/inferred maximum idle budget, when known. */
38
+ warmDurationMs?: number;
39
+ /** Epoch milliseconds measured from dispatch, never from the start of a wait. */
40
+ idleDeadline?: number;
41
+ source?: 'configured' | 'anthropic';
42
+ }
43
+ /** Cache controls emitted by an owning adapter, not proposed prompt/provider options. */
44
+ export interface ISmartAiEffectiveCachePolicy {
45
+ provider: 'anthropic';
46
+ controls: readonly unknown[];
47
+ }
48
+ export interface ISmartAiCachePolicyObservation {
49
+ dispatchedAt: number;
50
+ /** Absent when the final adapter/transport policy cannot be confirmed. */
51
+ policy?: ISmartAiEffectiveCachePolicy;
52
+ }
53
+ export type TSmartAiCachePolicyObserver = (observation: ISmartAiCachePolicyObservation) => void;
54
+ type TSmartAiCachePolicyObserverFactory = (observer: TSmartAiCachePolicyObserver) => plugins.LanguageModelV4;
55
+ /** The owning provider supplies a request-local observer after its relevant transforms. */
56
+ export declare function registerSmartAiCachePolicyObserver(model: plugins.LanguageModelV4, factory: TSmartAiCachePolicyObserverFactory): plugins.LanguageModelV4;
57
+ /** Undefined means the caller must observe conservatively at its own invocation boundary. */
58
+ export declare function bindSmartAiCachePolicyObserver(model: TSmartAiLanguageModel, observer: TSmartAiCachePolicyObserver): plugins.LanguageModelV4 | undefined;
59
+ export declare function observeSmartAiCacheDispatch(input: {
60
+ cache?: TSmartAiCacheSetting;
61
+ dispatchedAt: number;
62
+ effectivePolicy?: ISmartAiEffectiveCachePolicy;
63
+ }): ISmartAiCacheDispatch;
64
+ /** Bound one wait; reserve up to one second (10% for short budgets) for the next boundary. */
65
+ export declare function getSmartAiCacheWaitMs(requestedMs: number, dispatch?: ISmartAiCacheDispatch, now?: number): number;
66
+ export {};
@@ -92,9 +92,17 @@ function shouldUseMessageLevelOptions(provider) {
92
92
  return provider === 'anthropic' || provider === 'bedrock';
93
93
  }
94
94
  function applyProviderOptionsDefaults(item, defaults) {
95
+ // Cache controls are atomic caller policies, not objects whose missing TTL can be
96
+ // filled from defaults. Anthropic also accepts cache_control; injecting cacheControl
97
+ // beside it would shadow that caller policy under the SDK's camelCase ?? snake_case rule.
98
+ const hasCallerControl = Object.entries(defaults).some(([namespace, controls]) => {
99
+ const caller = item.providerOptions?.[namespace];
100
+ return isObject(caller) && isObject(controls) && (Object.keys(controls).some((key) => Object.prototype.hasOwnProperty.call(caller, key))
101
+ || (namespace === 'anthropic' && Object.prototype.hasOwnProperty.call(caller, 'cache_control')));
102
+ });
95
103
  return {
96
104
  ...item,
97
- providerOptions: mergeSmartAiProviderOptions(defaults, item.providerOptions),
105
+ providerOptions: hasCallerControl ? item.providerOptions : mergeSmartAiProviderOptions(defaults, item.providerOptions),
98
106
  };
99
107
  }
100
108
  function isToolApprovalPart(part) {
@@ -176,4 +184,78 @@ export function getSmartAiCacheProviderOptions(input) {
176
184
  export function applySmartAiCacheProviderOptions(input) {
177
185
  return mergeSmartAiProviderOptions(getSmartAiCacheProviderOptions(input), input.providerOptions);
178
186
  }
179
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRhaS5jYWNoZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzX21vZGVscy9zbWFydGFpLmNhY2hlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQXdCQSxTQUFTLFFBQVEsQ0FBQyxLQUFjO0lBQzlCLE9BQU8sT0FBTyxLQUFLLEtBQUssUUFBUSxJQUFJLEtBQUssS0FBSyxJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQzlFLENBQUM7QUFFRCxTQUFTLGlCQUFpQixDQUFDLFFBQTRCLEVBQUUsU0FBOEI7SUFDckYsTUFBTSxNQUFNLEdBQXVCLEVBQUUsR0FBRyxRQUFRLEVBQUUsQ0FBQztJQUVuRCxJQUFJLENBQUMsU0FBUztRQUFFLE9BQU8sTUFBTSxDQUFDO0lBRTlCLEtBQUssTUFBTSxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsSUFBSSxNQUFNLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUM7UUFDckQsTUFBTSxRQUFRLEdBQUcsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQzdCLElBQUksUUFBUSxDQUFDLFFBQVEsQ0FBQyxJQUFJLFFBQVEsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO1lBQzFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsR0FBRyxpQkFBaUIsQ0FBQyxRQUE4QixFQUFFLEtBQTJCLENBQUMsQ0FBQztZQUM3RixTQUFTO1FBQ1gsQ0FBQztRQUNELE1BQU0sQ0FBQyxHQUFHLENBQUMsR0FBRyxLQUEwQixDQUFDO0lBQzNDLENBQUM7SUFFRCxPQUFPLE1BQU0sQ0FBQztBQUNoQixDQUFDO0FBRUQsTUFBTSxVQUFVLDJCQUEyQixDQUN6QyxRQUFrQyxFQUNsQyxTQUFtQztJQUVuQyxJQUFJLENBQUMsUUFBUTtRQUFFLE9BQU8sU0FBUyxDQUFDO0lBQ2hDLElBQUksQ0FBQyxTQUFTO1FBQUUsT0FBTyxRQUFRLENBQUM7SUFDaEMsT0FBTyxpQkFBaUIs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
187
+ // Bind to the exact model identity. SDK wrappers intentionally do not inherit this
188
+ // capability: an opaque wrapper can change the adapter, policy, or dispatch entirely.
189
+ const cachePolicyObserverFactories = new WeakMap();
190
+ /** The owning provider supplies a request-local observer after its relevant transforms. */
191
+ export function registerSmartAiCachePolicyObserver(model, factory) {
192
+ cachePolicyObserverFactories.set(model, factory);
193
+ return model;
194
+ }
195
+ /** Undefined means the caller must observe conservatively at its own invocation boundary. */
196
+ export function bindSmartAiCachePolicyObserver(model, observer) {
197
+ return cachePolicyObserverFactories.get(model)?.(observer);
198
+ }
199
+ export function observeSmartAiCacheDispatch(input) {
200
+ if (!Number.isSafeInteger(input.dispatchedAt) || input.dispatchedAt < 0) {
201
+ throw new Error('Cache dispatch time must be a non-negative safe integer.');
202
+ }
203
+ const observation = { dispatchedAt: input.dispatchedAt };
204
+ const withDuration = (warmDurationMs, source) => {
205
+ const idleDeadline = input.dispatchedAt + warmDurationMs;
206
+ if (!Number.isSafeInteger(idleDeadline))
207
+ throw new Error('Cache idle deadline exceeds the safe integer range.');
208
+ return { ...observation, warmDurationMs, idleDeadline, source };
209
+ };
210
+ const cache = cacheOptionsFromSetting(input.cache);
211
+ if (!cache)
212
+ return observation;
213
+ if (cache.warmDurationMs !== undefined) {
214
+ if (!Number.isSafeInteger(cache.warmDurationMs) || cache.warmDurationMs <= 0) {
215
+ throw new Error('cache.warmDurationMs must be a positive safe integer.');
216
+ }
217
+ return withDuration(cache.warmDurationMs, 'configured');
218
+ }
219
+ // Never infer from provider/model names or proposed controls. Only an observed
220
+ // native adapter policy establishes the documented scheduling budget.
221
+ const policy = input.effectivePolicy;
222
+ if (policy?.provider !== 'anthropic' || policy.controls.length === 0)
223
+ return observation;
224
+ const durations = [];
225
+ for (const control of policy.controls) {
226
+ if (!isObject(control) || control.type !== 'ephemeral')
227
+ return observation;
228
+ if (control.ttl === undefined || control.ttl === '5m')
229
+ durations.push(300_000);
230
+ else if (control.ttl === '1h')
231
+ durations.push(3_600_000);
232
+ else
233
+ return observation;
234
+ }
235
+ return withDuration(Math.min(...durations), 'anthropic');
236
+ }
237
+ /** Bound one wait; reserve up to one second (10% for short budgets) for the next boundary. */
238
+ export function getSmartAiCacheWaitMs(requestedMs, dispatch, now = Date.now()) {
239
+ if (!Number.isFinite(requestedMs) || requestedMs < 0)
240
+ throw new Error('Wait duration must be non-negative and finite.');
241
+ if (!Number.isSafeInteger(now) || now < 0)
242
+ throw new Error('Wait time must be a non-negative safe integer.');
243
+ if (dispatch) {
244
+ if (!Number.isSafeInteger(dispatch.dispatchedAt) || dispatch.dispatchedAt < 0) {
245
+ throw new Error('Cache dispatch time must be a non-negative safe integer.');
246
+ }
247
+ if (dispatch.idleDeadline !== undefined || dispatch.warmDurationMs !== undefined) {
248
+ if (!Number.isSafeInteger(dispatch.idleDeadline) || !Number.isSafeInteger(dispatch.warmDurationMs)
249
+ || dispatch.warmDurationMs <= 0
250
+ || dispatch.idleDeadline !== dispatch.dispatchedAt + dispatch.warmDurationMs) {
251
+ throw new Error('Invalid cache dispatch budget.');
252
+ }
253
+ }
254
+ }
255
+ const maximum = Math.min(240_000, Math.floor(requestedMs));
256
+ if (dispatch?.idleDeadline === undefined || dispatch.warmDurationMs === undefined)
257
+ return maximum;
258
+ const headroom = Math.min(1000, Math.ceil(dispatch.warmDurationMs / 10));
259
+ return Math.max(0, Math.min(maximum, Math.floor(dispatch.idleDeadline - now - headroom)));
260
+ }
261
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic21hcnRhaS5jYWNoZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzX21vZGVscy9zbWFydGFpLmNhY2hlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQTBCQSxTQUFTLFFBQVEsQ0FBQyxLQUFjO0lBQzlCLE9BQU8sT0FBTyxLQUFLLEtBQUssUUFBUSxJQUFJLEtBQUssS0FBSyxJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQzlFLENBQUM7QUFFRCxTQUFTLGlCQUFpQixDQUFDLFFBQTRCLEVBQUUsU0FBOEI7SUFDckYsTUFBTSxNQUFNLEdBQXVCLEVBQUUsR0FBRyxRQUFRLEVBQUUsQ0FBQztJQUVuRCxJQUFJLENBQUMsU0FBUztRQUFFLE9BQU8sTUFBTSxDQUFDO0lBRTlCLEtBQUssTUFBTSxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsSUFBSSxNQUFNLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUM7UUFDckQsTUFBTSxRQUFRLEdBQUcsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQzdCLElBQUksUUFBUSxDQUFDLFFBQVEsQ0FBQyxJQUFJLFFBQVEsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO1lBQzFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsR0FBRyxpQkFBaUIsQ0FBQyxRQUE4QixFQUFFLEtBQTJCLENBQUMsQ0FBQztZQUM3RixTQUFTO1FBQ1gsQ0FBQztRQUNELE1BQU0sQ0FBQyxHQUFHLENBQUMsR0FBRyxLQUEwQixDQUFDO0lBQzNDLENBQUM7SUFFRCxPQUFPLE1BQU0sQ0FBQztBQUNoQixDQUFDO0FBRUQsTUFBTSxVQUFVLDJCQUEyQixDQUN6QyxRQUFrQyxFQUNsQyxTQUFtQztJQUVuQyxJQUFJLENBQUMsUUFBUTtRQUFFLE9BQU8sU0FBUyxDQUFDO0lBQ2hDLElBQUksQ0FBQyxTQUFTO1FBQUUsT0FBTyxRQUFRLENBQUM7SUFDaEMsT0FBTyxpQkFBaUIs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
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "author": "Task Venture Capital GmbH",
3
3
  "license": "MIT",
4
4
  "name": "@modelprofile.com/flexharness-models",
5
- "version": "10.10.0",
5
+ "version": "10.12.0",
6
6
  "type": "module",
7
7
  "description": "Provider-independent model contracts, prompt caching and explicit model registration.",
8
8
  "main": "./dist_ts_models/index.js",
@@ -1,5 +1,5 @@
1
1
  import type * as plugins from './plugins.js';
2
- import type { TSmartAiProviderOptions } from './interfaces.js';
2
+ import type { TSmartAiLanguageModel, TSmartAiProviderOptions } from './interfaces.js';
3
3
 
4
4
  export type TSmartAiMessageCacheProvider =
5
5
  | 'anthropic'
@@ -18,6 +18,8 @@ export interface ISmartAiCacheOptions {
18
18
  key?: string;
19
19
  /** Short retention is the default; longer retention is opt-in. */
20
20
  retention?: TSmartAiCacheRetention;
21
+ /** Configured maximum idle scheduling budget, not a promise of cache retention or a cache hit. */
22
+ warmDurationMs?: number;
21
23
  }
22
24
 
23
25
  export type TSmartAiCacheSetting = boolean | 'auto' | ISmartAiCacheOptions;
@@ -128,9 +130,19 @@ function applyProviderOptionsDefaults<T extends { providerOptions?: TSmartAiProv
128
130
  item: T,
129
131
  defaults: TSmartAiProviderOptions,
130
132
  ): T {
133
+ // Cache controls are atomic caller policies, not objects whose missing TTL can be
134
+ // filled from defaults. Anthropic also accepts cache_control; injecting cacheControl
135
+ // beside it would shadow that caller policy under the SDK's camelCase ?? snake_case rule.
136
+ const hasCallerControl = Object.entries(defaults).some(([namespace, controls]) => {
137
+ const caller = item.providerOptions?.[namespace];
138
+ return isObject(caller) && isObject(controls) && (
139
+ Object.keys(controls).some((key) => Object.prototype.hasOwnProperty.call(caller, key))
140
+ || (namespace === 'anthropic' && Object.prototype.hasOwnProperty.call(caller, 'cache_control'))
141
+ );
142
+ });
131
143
  return {
132
144
  ...item,
133
- providerOptions: mergeSmartAiProviderOptions(defaults, item.providerOptions),
145
+ providerOptions: hasCallerControl ? item.providerOptions : mergeSmartAiProviderOptions(defaults, item.providerOptions),
134
146
  };
135
147
  }
136
148
 
@@ -248,3 +260,111 @@ export function applySmartAiCacheProviderOptions(input: {
248
260
  input.providerOptions,
249
261
  );
250
262
  }
263
+
264
+ /** Observation at the model dispatch boundary; no field certifies a cache write or hit. */
265
+ export interface ISmartAiCacheDispatch {
266
+ dispatchedAt: number;
267
+ /** Configured/inferred maximum idle budget, when known. */
268
+ warmDurationMs?: number;
269
+ /** Epoch milliseconds measured from dispatch, never from the start of a wait. */
270
+ idleDeadline?: number;
271
+ source?: 'configured' | 'anthropic';
272
+ }
273
+
274
+ /** Cache controls emitted by an owning adapter, not proposed prompt/provider options. */
275
+ export interface ISmartAiEffectiveCachePolicy {
276
+ provider: 'anthropic';
277
+ controls: readonly unknown[];
278
+ }
279
+
280
+ export interface ISmartAiCachePolicyObservation {
281
+ dispatchedAt: number;
282
+ /** Absent when the final adapter/transport policy cannot be confirmed. */
283
+ policy?: ISmartAiEffectiveCachePolicy;
284
+ }
285
+
286
+ export type TSmartAiCachePolicyObserver = (observation: ISmartAiCachePolicyObservation) => void;
287
+ type TSmartAiCachePolicyObserverFactory = (observer: TSmartAiCachePolicyObserver) => plugins.LanguageModelV4;
288
+
289
+ // Bind to the exact model identity. SDK wrappers intentionally do not inherit this
290
+ // capability: an opaque wrapper can change the adapter, policy, or dispatch entirely.
291
+ const cachePolicyObserverFactories = new WeakMap<TSmartAiLanguageModel, TSmartAiCachePolicyObserverFactory>();
292
+
293
+ /** The owning provider supplies a request-local observer after its relevant transforms. */
294
+ export function registerSmartAiCachePolicyObserver(
295
+ model: plugins.LanguageModelV4,
296
+ factory: TSmartAiCachePolicyObserverFactory,
297
+ ): plugins.LanguageModelV4 {
298
+ cachePolicyObserverFactories.set(model, factory);
299
+ return model;
300
+ }
301
+
302
+ /** Undefined means the caller must observe conservatively at its own invocation boundary. */
303
+ export function bindSmartAiCachePolicyObserver(
304
+ model: TSmartAiLanguageModel,
305
+ observer: TSmartAiCachePolicyObserver,
306
+ ): plugins.LanguageModelV4 | undefined {
307
+ return cachePolicyObserverFactories.get(model)?.(observer);
308
+ }
309
+
310
+ export function observeSmartAiCacheDispatch(input: {
311
+ cache?: TSmartAiCacheSetting;
312
+ dispatchedAt: number;
313
+ effectivePolicy?: ISmartAiEffectiveCachePolicy;
314
+ }): ISmartAiCacheDispatch {
315
+ if (!Number.isSafeInteger(input.dispatchedAt) || input.dispatchedAt < 0) {
316
+ throw new Error('Cache dispatch time must be a non-negative safe integer.');
317
+ }
318
+ const observation: ISmartAiCacheDispatch = { dispatchedAt: input.dispatchedAt };
319
+ const withDuration = (warmDurationMs: number, source: 'configured' | 'anthropic'): ISmartAiCacheDispatch => {
320
+ const idleDeadline = input.dispatchedAt + warmDurationMs;
321
+ if (!Number.isSafeInteger(idleDeadline)) throw new Error('Cache idle deadline exceeds the safe integer range.');
322
+ return { ...observation, warmDurationMs, idleDeadline, source };
323
+ };
324
+ const cache = cacheOptionsFromSetting(input.cache);
325
+ if (!cache) return observation;
326
+ if (cache.warmDurationMs !== undefined) {
327
+ if (!Number.isSafeInteger(cache.warmDurationMs) || cache.warmDurationMs <= 0) {
328
+ throw new Error('cache.warmDurationMs must be a positive safe integer.');
329
+ }
330
+ return withDuration(cache.warmDurationMs, 'configured');
331
+ }
332
+ // Never infer from provider/model names or proposed controls. Only an observed
333
+ // native adapter policy establishes the documented scheduling budget.
334
+ const policy = input.effectivePolicy;
335
+ if (policy?.provider !== 'anthropic' || policy.controls.length === 0) return observation;
336
+ const durations: number[] = [];
337
+ for (const control of policy.controls) {
338
+ if (!isObject(control) || control.type !== 'ephemeral') return observation;
339
+ if (control.ttl === undefined || control.ttl === '5m') durations.push(300_000);
340
+ else if (control.ttl === '1h') durations.push(3_600_000);
341
+ else return observation;
342
+ }
343
+ return withDuration(Math.min(...durations), 'anthropic');
344
+ }
345
+
346
+ /** Bound one wait; reserve up to one second (10% for short budgets) for the next boundary. */
347
+ export function getSmartAiCacheWaitMs(
348
+ requestedMs: number,
349
+ dispatch?: ISmartAiCacheDispatch,
350
+ now = Date.now(),
351
+ ): number {
352
+ if (!Number.isFinite(requestedMs) || requestedMs < 0) throw new Error('Wait duration must be non-negative and finite.');
353
+ if (!Number.isSafeInteger(now) || now < 0) throw new Error('Wait time must be a non-negative safe integer.');
354
+ if (dispatch) {
355
+ if (!Number.isSafeInteger(dispatch.dispatchedAt) || dispatch.dispatchedAt < 0) {
356
+ throw new Error('Cache dispatch time must be a non-negative safe integer.');
357
+ }
358
+ if (dispatch.idleDeadline !== undefined || dispatch.warmDurationMs !== undefined) {
359
+ if (!Number.isSafeInteger(dispatch.idleDeadline) || !Number.isSafeInteger(dispatch.warmDurationMs)
360
+ || dispatch.warmDurationMs! <= 0
361
+ || dispatch.idleDeadline !== dispatch.dispatchedAt + dispatch.warmDurationMs!) {
362
+ throw new Error('Invalid cache dispatch budget.');
363
+ }
364
+ }
365
+ }
366
+ const maximum = Math.min(240_000, Math.floor(requestedMs));
367
+ if (dispatch?.idleDeadline === undefined || dispatch.warmDurationMs === undefined) return maximum;
368
+ const headroom = Math.min(1000, Math.ceil(dispatch.warmDurationMs / 10));
369
+ return Math.max(0, Math.min(maximum, Math.floor(dispatch.idleDeadline - now - headroom)));
370
+ }