deepline 0.1.300 → 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 (37) 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/runtime-receipt-store-adapter.ts +103 -0
  16. package/dist/bundling-sources/shared_libs/play-runtime/runtime-receipt-writer.ts +78 -5
  17. package/dist/bundling-sources/shared_libs/play-runtime/tool-execute-retry-policy.ts +17 -12
  18. package/dist/bundling-sources/shared_libs/play-runtime/tool-http-errors.ts +210 -5
  19. package/dist/bundling-sources/shared_libs/play-runtime/work-receipts.ts +4 -0
  20. package/dist/bundling-sources/shared_libs/plays/artifact-contract-version.ts +6 -0
  21. package/dist/bundling-sources/shared_libs/plays/artifact-types.ts +4 -0
  22. package/dist/bundling-sources/shared_libs/plays/bundling/index.ts +159 -12
  23. package/dist/bundling-sources/shared_libs/plays/contracts.ts +69 -1
  24. package/dist/bundling-sources/shared_libs/tool-execution-error.ts +428 -0
  25. package/dist/cli/index.js +501 -179
  26. package/dist/cli/index.mjs +501 -179
  27. package/dist/index.d.mts +39 -18
  28. package/dist/index.d.ts +39 -18
  29. package/dist/index.js +394 -59
  30. package/dist/index.mjs +391 -59
  31. package/dist/plays/bundle-play-file.d.mts +4 -2
  32. package/dist/plays/bundle-play-file.d.ts +4 -2
  33. package/dist/plays/bundle-play-file.mjs +116 -19
  34. package/dist/{compiler-manifest-BjopNIqx.d.mts → tool-execution-error-9mH4i-mJ.d.mts} +79 -1
  35. package/dist/{compiler-manifest-BjopNIqx.d.ts → tool-execution-error-9mH4i-mJ.d.ts} +79 -1
  36. package/package.json +1 -1
  37. package/dist/bundling-sources/shared_libs/play-runtime/completed-receipt-cache.ts +0 -166
@@ -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
+ }