deepline 0.1.301 → 0.1.302

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 (35) hide show
  1. package/dist/bundling-sources/sdk/src/client.ts +8 -0
  2. package/dist/bundling-sources/sdk/src/errors.ts +57 -15
  3. package/dist/bundling-sources/sdk/src/http.ts +82 -5
  4. package/dist/bundling-sources/sdk/src/index.ts +4 -0
  5. package/dist/bundling-sources/sdk/src/play.ts +29 -1
  6. package/dist/bundling-sources/sdk/src/release.ts +5 -3
  7. package/dist/bundling-sources/shared_libs/play-runtime/context.ts +120 -14
  8. package/dist/bundling-sources/shared_libs/play-runtime/ctx-types.ts +10 -0
  9. package/dist/bundling-sources/shared_libs/play-runtime/durable-receipt-execution.ts +59 -11
  10. package/dist/bundling-sources/shared_libs/play-runtime/execution-ledger-store.ts +3 -3
  11. package/dist/bundling-sources/shared_libs/play-runtime/execution-plan.ts +0 -15
  12. package/dist/bundling-sources/shared_libs/play-runtime/protocol.ts +3 -0
  13. package/dist/bundling-sources/shared_libs/play-runtime/runtime-actions.ts +3 -0
  14. package/dist/bundling-sources/shared_libs/play-runtime/runtime-api.ts +136 -36
  15. package/dist/bundling-sources/shared_libs/play-runtime/tool-execute-retry-policy.ts +17 -12
  16. package/dist/bundling-sources/shared_libs/play-runtime/tool-http-errors.ts +210 -5
  17. package/dist/bundling-sources/shared_libs/play-runtime/work-receipts.ts +4 -0
  18. package/dist/bundling-sources/shared_libs/plays/artifact-contract-version.ts +6 -0
  19. package/dist/bundling-sources/shared_libs/plays/artifact-types.ts +4 -0
  20. package/dist/bundling-sources/shared_libs/plays/bundling/index.ts +159 -12
  21. package/dist/bundling-sources/shared_libs/plays/contracts.ts +69 -1
  22. package/dist/bundling-sources/shared_libs/tool-execution-error.ts +428 -0
  23. package/dist/cli/index.js +501 -179
  24. package/dist/cli/index.mjs +501 -179
  25. package/dist/index.d.mts +39 -18
  26. package/dist/index.d.ts +39 -18
  27. package/dist/index.js +394 -59
  28. package/dist/index.mjs +391 -59
  29. package/dist/plays/bundle-play-file.d.mts +4 -2
  30. package/dist/plays/bundle-play-file.d.ts +4 -2
  31. package/dist/plays/bundle-play-file.mjs +116 -19
  32. package/dist/{compiler-manifest-BjopNIqx.d.mts → tool-execution-error-9mH4i-mJ.d.mts} +79 -1
  33. package/dist/{compiler-manifest-BjopNIqx.d.ts → tool-execution-error-9mH4i-mJ.d.ts} +79 -1
  34. package/package.json +1 -1
  35. package/dist/bundling-sources/shared_libs/play-runtime/completed-receipt-cache.ts +0 -166
@@ -1,3 +1,11 @@
1
+ import {
2
+ LEGACY_TOOL_EXECUTION_ERROR_SCHEMA_VERSION,
3
+ SUPPORTED_TOOL_EXECUTION_ERROR_SCHEMA_VERSIONS,
4
+ TOOL_EXECUTION_ERROR_SCHEMA_VERSION,
5
+ type ToolExecutionErrorSchemaVersion,
6
+ } from '../tool-execution-error';
7
+ import { CURRENT_PLAY_ARTIFACT_CONTRACT_VERSION } from './artifact-contract-version';
8
+
1
9
  export type PlayContractSource = 'ad_hoc' | 'draft' | 'published';
2
10
 
3
11
  export type PlayRuntimeFeature =
@@ -7,7 +15,7 @@ export type PlayRuntimeFeature =
7
15
  | 'packaged_files';
8
16
 
9
17
  export const PLAY_PUBLIC_API_VERSION = 1;
10
- export const PLAY_ARTIFACT_VERSION = 1;
18
+ export const PLAY_ARTIFACT_VERSION = CURRENT_PLAY_ARTIFACT_CONTRACT_VERSION;
11
19
  export const PLAY_MIN_RUNNER_VERSION = 1;
12
20
  export const PLAY_RUNTIME_FEATURES: PlayRuntimeFeature[] = [
13
21
  'artifact_storage',
@@ -22,10 +30,68 @@ export type PlayContractCompatibilitySnapshot = {
22
30
  minRunnerVersion: number;
23
31
  runtimeFeatures: PlayRuntimeFeature[];
24
32
  runtimeBackend?: string | null;
33
+ /** Missing preserves the legacy contract used by artifacts stored before this field existed. */
34
+ toolErrorSchemaVersion?: ToolExecutionErrorSchemaVersion;
25
35
  };
26
36
 
37
+ export type NormalizedPlayContractCompatibilitySnapshot =
38
+ PlayContractCompatibilitySnapshot & {
39
+ toolErrorSchemaVersion: ToolExecutionErrorSchemaVersion;
40
+ };
41
+
42
+ export class UnsupportedPlayToolErrorSchemaVersionError extends Error {
43
+ constructor(value: unknown) {
44
+ super(
45
+ `Unsupported Play tool error schema version ${String(value)}. Supported versions: ${SUPPORTED_TOOL_EXECUTION_ERROR_SCHEMA_VERSIONS.join(', ')}.`,
46
+ );
47
+ this.name = 'UnsupportedPlayToolErrorSchemaVersionError';
48
+ }
49
+ }
50
+
51
+ export class InvalidPlayContractCompatibilityError extends Error {
52
+ constructor() {
53
+ super('Play artifact compatibility must be an object.');
54
+ this.name = 'InvalidPlayContractCompatibilityError';
55
+ }
56
+ }
57
+
58
+ /**
59
+ * Normalize the artifact-pinned compatibility facts without regenerating them.
60
+ * A missing field is the historical production contract, not an opt-in to the
61
+ * current runtime behavior.
62
+ */
63
+ export function normalizePlayContractCompatibility(
64
+ compatibility: PlayContractCompatibilitySnapshot | null | undefined,
65
+ ): NormalizedPlayContractCompatibilitySnapshot {
66
+ if (
67
+ !compatibility ||
68
+ typeof compatibility !== 'object' ||
69
+ Array.isArray(compatibility)
70
+ ) {
71
+ throw new InvalidPlayContractCompatibilityError();
72
+ }
73
+ const toolErrorSchemaVersion =
74
+ compatibility.toolErrorSchemaVersion ??
75
+ LEGACY_TOOL_EXECUTION_ERROR_SCHEMA_VERSION;
76
+ if (
77
+ !SUPPORTED_TOOL_EXECUTION_ERROR_SCHEMA_VERSIONS.includes(
78
+ toolErrorSchemaVersion as ToolExecutionErrorSchemaVersion,
79
+ )
80
+ ) {
81
+ throw new UnsupportedPlayToolErrorSchemaVersionError(
82
+ toolErrorSchemaVersion,
83
+ );
84
+ }
85
+ return {
86
+ ...compatibility,
87
+ toolErrorSchemaVersion:
88
+ toolErrorSchemaVersion as ToolExecutionErrorSchemaVersion,
89
+ };
90
+ }
91
+
27
92
  export function buildPlayContractCompatibility(input?: {
28
93
  runtimeBackend?: string | null;
94
+ toolErrorSchemaVersion?: ToolExecutionErrorSchemaVersion;
29
95
  }): PlayContractCompatibilitySnapshot {
30
96
  return {
31
97
  apiVersion: PLAY_PUBLIC_API_VERSION,
@@ -33,6 +99,8 @@ export function buildPlayContractCompatibility(input?: {
33
99
  minRunnerVersion: PLAY_MIN_RUNNER_VERSION,
34
100
  runtimeFeatures: [...PLAY_RUNTIME_FEATURES],
35
101
  runtimeBackend: input?.runtimeBackend ?? null,
102
+ toolErrorSchemaVersion:
103
+ input?.toolErrorSchemaVersion ?? TOOL_EXECUTION_ERROR_SCHEMA_VERSION,
36
104
  };
37
105
  }
38
106
 
@@ -0,0 +1,428 @@
1
+ const DEEPLINE_ERROR_BRAND = Symbol.for('deepline.error.v1');
2
+ export const TOOL_EXECUTION_ERROR_BRAND = Symbol.for(
3
+ 'deepline.tool-execution-error.v1',
4
+ );
5
+ const PROVIDER_TRANSIENT_ERROR_BRAND = Symbol.for(
6
+ 'deepline.provider-transient-error.v1',
7
+ );
8
+
9
+ export const LEGACY_TOOL_EXECUTION_ERROR_SCHEMA_VERSION = 0 as const;
10
+ export const TOOL_EXECUTION_ERROR_SCHEMA_VERSION = 1 as const;
11
+ export const SUPPORTED_TOOL_EXECUTION_ERROR_SCHEMA_VERSIONS = [
12
+ LEGACY_TOOL_EXECUTION_ERROR_SCHEMA_VERSION,
13
+ TOOL_EXECUTION_ERROR_SCHEMA_VERSION,
14
+ ] as const;
15
+ export type ToolExecutionErrorSchemaVersion =
16
+ (typeof SUPPORTED_TOOL_EXECUTION_ERROR_SCHEMA_VERSIONS)[number];
17
+ export const TOOL_EXECUTION_ERROR_SCHEMA_HEADER =
18
+ 'x-deepline-tool-error-schema';
19
+
20
+ const MAX_IDENTIFIER_LENGTH = 200;
21
+ const MAX_CODE_LENGTH = 160;
22
+
23
+ export type ToolExecutionErrorOrigin =
24
+ | 'caller'
25
+ | 'provider'
26
+ | 'deepline'
27
+ | 'unknown';
28
+
29
+ export type ToolExecutionErrorCategory =
30
+ | 'validation'
31
+ | 'authentication'
32
+ | 'authorization'
33
+ | 'rate_limit'
34
+ | 'network'
35
+ | 'upstream'
36
+ | 'billing'
37
+ | 'conflict'
38
+ | 'internal'
39
+ | 'unknown';
40
+
41
+ export type ToolExecutionNetworkKind =
42
+ | 'timeout'
43
+ | 'dns'
44
+ | 'connect'
45
+ | 'reset'
46
+ | 'unavailable'
47
+ | 'unknown';
48
+
49
+ export type ToolExecutionNetworkScope =
50
+ | 'client_to_deepline'
51
+ | 'runtime_to_deepline'
52
+ | 'deepline_to_provider';
53
+
54
+ export type ToolExecutionFailureV1 = {
55
+ schemaVersion: typeof TOOL_EXECUTION_ERROR_SCHEMA_VERSION;
56
+ toolId: string;
57
+ provider: string | null;
58
+ operation: string | null;
59
+ code: string | null;
60
+ origin: ToolExecutionErrorOrigin;
61
+ category: ToolExecutionErrorCategory;
62
+ retryable: boolean;
63
+ statusCode: number | null;
64
+ requestId: string | null;
65
+ retryAfterMs: number | null;
66
+ networkKind: ToolExecutionNetworkKind | null;
67
+ networkScope: ToolExecutionNetworkScope | null;
68
+ };
69
+
70
+ export type ToolExecutionErrorOptions = Omit<
71
+ ToolExecutionFailureV1,
72
+ 'schemaVersion'
73
+ > & {
74
+ /**
75
+ * Local diagnostic context inherited from DeeplineError. This is not part of
76
+ * the portable failure payload and is intentionally omitted by serialization.
77
+ */
78
+ details?: Record<string, unknown>;
79
+ };
80
+
81
+ export type ProviderTransientErrorCategory =
82
+ | 'rate_limit'
83
+ | 'network'
84
+ | 'upstream';
85
+
86
+ function nativeInstanceOf(constructor: object, value: unknown): boolean {
87
+ return Reflect.apply(Function.prototype[Symbol.hasInstance], constructor, [
88
+ value,
89
+ ]) as boolean;
90
+ }
91
+
92
+ function hasBrand(value: unknown, brand: symbol): boolean {
93
+ return (
94
+ typeof value === 'object' &&
95
+ value !== null &&
96
+ (value as Record<symbol, unknown>)[brand] === true
97
+ );
98
+ }
99
+
100
+ function applyBrand(value: object, brand: symbol): void {
101
+ if (hasBrand(value, brand)) return;
102
+ Object.defineProperty(value, brand, {
103
+ configurable: false,
104
+ enumerable: false,
105
+ writable: false,
106
+ value: true,
107
+ });
108
+ }
109
+
110
+ /**
111
+ * Base error class shared by the SDK and play runtime.
112
+ *
113
+ * The global brand preserves `instanceof DeeplineError` when a bundled play
114
+ * and the runtime load separate physical copies of this module.
115
+ */
116
+ export class DeeplineError extends Error {
117
+ constructor(
118
+ message: string,
119
+ public statusCode?: number,
120
+ public code?: string,
121
+ public details?: Record<string, unknown>,
122
+ ) {
123
+ super(message);
124
+ this.name = 'DeeplineError';
125
+ applyBrand(this, DEEPLINE_ERROR_BRAND);
126
+ }
127
+
128
+ static [Symbol.hasInstance](value: unknown): boolean {
129
+ // Subclasses inherit static methods. Delegate subclass checks to the native
130
+ // prototype algorithm so AuthError never accidentally matches ConfigError.
131
+ if (this !== DeeplineError) return nativeInstanceOf(this, value);
132
+ return hasBrand(value, DEEPLINE_ERROR_BRAND);
133
+ }
134
+ }
135
+
136
+ /**
137
+ * A failed `tools.execute` call with stable, allowlisted provenance.
138
+ *
139
+ * `retryable` means Deepline's delivery/idempotency contract says it is safe
140
+ * to repeat the same semantic call. It does not describe durable receipt
141
+ * repairability and does not make arbitrary side-effecting fallbacks safe.
142
+ */
143
+ export class ToolExecutionError extends DeeplineError {
144
+ readonly toolId: string;
145
+ readonly provider: string | null;
146
+ readonly operation: string | null;
147
+ readonly origin: ToolExecutionErrorOrigin;
148
+ readonly category: ToolExecutionErrorCategory;
149
+ readonly retryable: boolean;
150
+ readonly requestId: string | null;
151
+ readonly retryAfterMs: number | null;
152
+ readonly networkKind: ToolExecutionNetworkKind | null;
153
+ readonly networkScope: ToolExecutionNetworkScope | null;
154
+
155
+ constructor(message: string, options: ToolExecutionErrorOptions) {
156
+ super(
157
+ message,
158
+ options.statusCode ?? undefined,
159
+ options.code ?? undefined,
160
+ options.details,
161
+ );
162
+ this.name = 'ToolExecutionError';
163
+ this.toolId = options.toolId;
164
+ this.provider = options.provider;
165
+ this.operation = options.operation;
166
+ this.origin = options.origin;
167
+ this.category = options.category;
168
+ this.retryable = options.retryable;
169
+ this.requestId = options.requestId;
170
+ this.retryAfterMs = options.retryAfterMs;
171
+ this.networkKind = options.networkKind;
172
+ this.networkScope = options.networkScope;
173
+ applyBrand(this, TOOL_EXECUTION_ERROR_BRAND);
174
+ if (isProviderTransientFailure(options)) {
175
+ applyBrand(this, PROVIDER_TRANSIENT_ERROR_BRAND);
176
+ }
177
+ }
178
+
179
+ static [Symbol.hasInstance](value: unknown): boolean {
180
+ if (this !== ToolExecutionError) return nativeInstanceOf(this, value);
181
+ return hasBrand(value, TOOL_EXECUTION_ERROR_BRAND);
182
+ }
183
+ }
184
+
185
+ /**
186
+ * Brands a compatibility subclass (notably SDK ToolRateLimitError) as a tool
187
+ * failure without changing its existing prototype chain.
188
+ */
189
+ export function brandAsToolExecutionError(value: object): void {
190
+ applyBrand(value, TOOL_EXECUTION_ERROR_BRAND);
191
+ }
192
+
193
+ export function isProviderTransientFailure(input: {
194
+ origin: ToolExecutionErrorOrigin;
195
+ category: ToolExecutionErrorCategory;
196
+ retryable: boolean;
197
+ }): input is {
198
+ origin: 'provider';
199
+ category: ProviderTransientErrorCategory;
200
+ retryable: boolean;
201
+ } {
202
+ return (
203
+ input.origin === 'provider' &&
204
+ (input.category === 'rate_limit' ||
205
+ input.category === 'network' ||
206
+ input.category === 'upstream')
207
+ );
208
+ }
209
+
210
+ /**
211
+ * A provider-owned transient failure that is safe to handle as an empty
212
+ * waterfall leg. Validation, auth, billing, Deepline, and unknown failures
213
+ * never satisfy this type.
214
+ */
215
+ export class ProviderTransientError extends ToolExecutionError {
216
+ override readonly origin = 'provider' as const;
217
+ declare readonly category: ProviderTransientErrorCategory;
218
+
219
+ constructor(
220
+ message: string,
221
+ options: Omit<ToolExecutionErrorOptions, 'origin' | 'category'> & {
222
+ category: ProviderTransientErrorCategory;
223
+ },
224
+ ) {
225
+ super(message, {
226
+ ...options,
227
+ origin: 'provider',
228
+ category: options.category,
229
+ });
230
+ this.name = 'ProviderTransientError';
231
+ this.category = options.category;
232
+ applyBrand(this, PROVIDER_TRANSIENT_ERROR_BRAND);
233
+ }
234
+
235
+ static [Symbol.hasInstance](value: unknown): boolean {
236
+ if (this !== ProviderTransientError) return nativeInstanceOf(this, value);
237
+ return hasBrand(value, PROVIDER_TRANSIENT_ERROR_BRAND);
238
+ }
239
+ }
240
+
241
+ /** Brand an internal compatibility error after its normalized fields exist. */
242
+ export function brandAsProviderTransientError(value: object): void {
243
+ applyBrand(value, PROVIDER_TRANSIENT_ERROR_BRAND);
244
+ }
245
+
246
+ function boundedString(
247
+ value: unknown,
248
+ maxLength = MAX_IDENTIFIER_LENGTH,
249
+ ): string | null {
250
+ if (typeof value !== 'string') return null;
251
+ const normalized = value.trim();
252
+ return normalized ? normalized.slice(0, maxLength) : null;
253
+ }
254
+
255
+ function finiteNonNegativeInteger(value: unknown): number | null {
256
+ return typeof value === 'number' &&
257
+ Number.isFinite(value) &&
258
+ value >= 0 &&
259
+ Number.isInteger(value)
260
+ ? value
261
+ : null;
262
+ }
263
+
264
+ export function normalizeToolExecutionOrigin(
265
+ value: unknown,
266
+ input?: { provider?: string | null; operation?: string | null },
267
+ ): ToolExecutionErrorOrigin {
268
+ const normalized = boundedString(value)?.toLowerCase();
269
+ if (normalized === 'caller') return 'caller';
270
+ if (normalized === 'provider' || normalized === 'provider_network') {
271
+ return 'provider';
272
+ }
273
+ // Older integration adapters use "upstream" for a provider-owned failure.
274
+ // Only accept that alias when the execution boundary identifies the provider
275
+ // action; an unscoped upstream error fails closed.
276
+ if (
277
+ normalized === 'upstream' &&
278
+ boundedString(input?.provider) &&
279
+ boundedString(input?.operation)
280
+ ) {
281
+ return 'provider';
282
+ }
283
+ if (
284
+ normalized === 'deepline' ||
285
+ normalized === 'deepline_billing' ||
286
+ normalized === 'deepline_rate_limit' ||
287
+ normalized === 'internal' ||
288
+ normalized === 'server'
289
+ ) {
290
+ return 'deepline';
291
+ }
292
+ if (normalized === 'provider_account') return 'provider';
293
+ return 'unknown';
294
+ }
295
+
296
+ export function normalizeToolExecutionCategory(
297
+ value: unknown,
298
+ ): ToolExecutionErrorCategory {
299
+ switch (boundedString(value)?.toLowerCase()) {
300
+ case 'validation':
301
+ case 'authorization':
302
+ case 'rate_limit':
303
+ case 'network':
304
+ case 'upstream':
305
+ case 'billing':
306
+ case 'conflict':
307
+ case 'internal':
308
+ return boundedString(value)!.toLowerCase() as ToolExecutionErrorCategory;
309
+ case 'authentication':
310
+ case 'provider_auth':
311
+ case 'provider_account':
312
+ return 'authentication';
313
+ case 'execution':
314
+ case 'parse':
315
+ case 'stub':
316
+ case 'internal_native_search_performance':
317
+ return 'internal';
318
+ default:
319
+ return 'unknown';
320
+ }
321
+ }
322
+
323
+ function normalizeNetworkKind(value: unknown): ToolExecutionNetworkKind | null {
324
+ switch (boundedString(value)?.toLowerCase()) {
325
+ case 'timeout':
326
+ case 'dns':
327
+ case 'connect':
328
+ case 'reset':
329
+ case 'unavailable':
330
+ case 'unknown':
331
+ return boundedString(value)!.toLowerCase() as ToolExecutionNetworkKind;
332
+ default:
333
+ return null;
334
+ }
335
+ }
336
+
337
+ function normalizeNetworkScope(
338
+ value: unknown,
339
+ ): ToolExecutionNetworkScope | null {
340
+ switch (boundedString(value)?.toLowerCase()) {
341
+ case 'client_to_deepline':
342
+ case 'runtime_to_deepline':
343
+ case 'deepline_to_provider':
344
+ return boundedString(value)!.toLowerCase() as ToolExecutionNetworkScope;
345
+ default:
346
+ return null;
347
+ }
348
+ }
349
+
350
+ function isRecord(value: unknown): value is Record<string, unknown> {
351
+ return value !== null && typeof value === 'object' && !Array.isArray(value);
352
+ }
353
+
354
+ export function normalizeToolExecutionFailure(
355
+ value: unknown,
356
+ ): ToolExecutionFailureV1 | null {
357
+ if (
358
+ !isRecord(value) ||
359
+ value.schemaVersion !== TOOL_EXECUTION_ERROR_SCHEMA_VERSION
360
+ ) {
361
+ return null;
362
+ }
363
+ const toolId = boundedString(value.toolId);
364
+ if (!toolId) return null;
365
+ const provider = boundedString(value.provider);
366
+ const operation = boundedString(value.operation);
367
+ const origin = normalizeToolExecutionOrigin(value.origin, {
368
+ provider,
369
+ operation,
370
+ });
371
+ const category = normalizeToolExecutionCategory(value.category);
372
+ const trustworthy =
373
+ origin !== 'unknown' &&
374
+ category !== 'unknown' &&
375
+ typeof value.retryable === 'boolean';
376
+ return {
377
+ schemaVersion: TOOL_EXECUTION_ERROR_SCHEMA_VERSION,
378
+ toolId,
379
+ provider,
380
+ operation,
381
+ code: boundedString(value.code, MAX_CODE_LENGTH),
382
+ origin,
383
+ category,
384
+ retryable: trustworthy ? value.retryable === true : false,
385
+ statusCode: finiteNonNegativeInteger(value.statusCode),
386
+ requestId: boundedString(value.requestId),
387
+ retryAfterMs: finiteNonNegativeInteger(value.retryAfterMs),
388
+ networkKind: normalizeNetworkKind(value.networkKind),
389
+ networkScope: normalizeNetworkScope(value.networkScope),
390
+ };
391
+ }
392
+
393
+ export function serializeToolExecutionFailure(
394
+ error: unknown,
395
+ ): ToolExecutionFailureV1 | null {
396
+ if (!(error instanceof ToolExecutionError)) return null;
397
+ return normalizeToolExecutionFailure({
398
+ schemaVersion: TOOL_EXECUTION_ERROR_SCHEMA_VERSION,
399
+ toolId: error.toolId,
400
+ provider: error.provider,
401
+ operation: error.operation,
402
+ code: error.code ?? null,
403
+ origin: error.origin,
404
+ category: error.category,
405
+ retryable: error.retryable,
406
+ statusCode: error.statusCode ?? null,
407
+ requestId: error.requestId,
408
+ retryAfterMs: error.retryAfterMs,
409
+ networkKind: error.networkKind,
410
+ networkScope: error.networkScope,
411
+ });
412
+ }
413
+
414
+ export function deserializeToolExecutionFailure(
415
+ message: string,
416
+ value: unknown,
417
+ acceptedSchemaVersion: ToolExecutionErrorSchemaVersion,
418
+ ): ToolExecutionError | null {
419
+ if (acceptedSchemaVersion === LEGACY_TOOL_EXECUTION_ERROR_SCHEMA_VERSION) {
420
+ return null;
421
+ }
422
+ const failure = normalizeToolExecutionFailure(value);
423
+ if (!failure) return null;
424
+ if (isProviderTransientFailure(failure)) {
425
+ return new ProviderTransientError(message, failure);
426
+ }
427
+ return new ToolExecutionError(message, failure);
428
+ }