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,5 +1,5 @@
1
- import { P as PlayArtifactKind$1, a as PlayCompilerManifest } from '../compiler-manifest-BjopNIqx.mjs';
2
- export { b as PLAY_ARTIFACT_KINDS } from '../compiler-manifest-BjopNIqx.mjs';
1
+ import { T as ToolExecutionErrorSchemaVersion, P as PlayArtifactKind$1, a as PlayCompilerManifest } from '../tool-execution-error-9mH4i-mJ.mjs';
2
+ export { b as PLAY_ARTIFACT_KINDS } from '../tool-execution-error-9mH4i-mJ.mjs';
3
3
 
4
4
  type PlayPackageImport = {
5
5
  name: string;
@@ -17,6 +17,8 @@ type PlayArtifactCompatibility = {
17
17
  minRunnerVersion: number;
18
18
  runtimeFeatures: PlayRuntimeFeature[];
19
19
  runtimeBackend?: string | null;
20
+ /** Missing preserves the legacy schema used before this field existed. */
21
+ toolErrorSchemaVersion?: ToolExecutionErrorSchemaVersion;
20
22
  };
21
23
  /** The only executable Play artifact contract. */
22
24
  type PlayArtifactKind = 'cjs_node20';
@@ -1,5 +1,5 @@
1
- import { P as PlayArtifactKind$1, a as PlayCompilerManifest } from '../compiler-manifest-BjopNIqx.js';
2
- export { b as PLAY_ARTIFACT_KINDS } from '../compiler-manifest-BjopNIqx.js';
1
+ import { T as ToolExecutionErrorSchemaVersion, P as PlayArtifactKind$1, a as PlayCompilerManifest } from '../tool-execution-error-9mH4i-mJ.js';
2
+ export { b as PLAY_ARTIFACT_KINDS } from '../tool-execution-error-9mH4i-mJ.js';
3
3
 
4
4
  type PlayPackageImport = {
5
5
  name: string;
@@ -17,6 +17,8 @@ type PlayArtifactCompatibility = {
17
17
  minRunnerVersion: number;
18
18
  runtimeFeatures: PlayRuntimeFeature[];
19
19
  runtimeBackend?: string | null;
20
+ /** Missing preserves the legacy schema used before this field existed. */
21
+ toolErrorSchemaVersion?: ToolExecutionErrorSchemaVersion;
20
22
  };
21
23
  /** The only executable Play artifact contract. */
22
24
  type PlayArtifactKind = 'cjs_node20';
@@ -43,9 +43,15 @@ var PLAY_BACKEND_DESCRIPTORS = {
43
43
  }
44
44
  };
45
45
 
46
+ // ../shared_libs/tool-execution-error.ts
47
+ var TOOL_EXECUTION_ERROR_SCHEMA_VERSION = 1;
48
+
49
+ // ../shared_libs/plays/artifact-contract-version.ts
50
+ var CURRENT_PLAY_ARTIFACT_CONTRACT_VERSION = 2;
51
+
46
52
  // ../shared_libs/plays/contracts.ts
47
53
  var PLAY_PUBLIC_API_VERSION = 1;
48
- var PLAY_ARTIFACT_VERSION = 1;
54
+ var PLAY_ARTIFACT_VERSION = CURRENT_PLAY_ARTIFACT_CONTRACT_VERSION;
49
55
  var PLAY_MIN_RUNNER_VERSION = 1;
50
56
  var PLAY_RUNTIME_FEATURES = [
51
57
  "artifact_storage",
@@ -59,7 +65,8 @@ function buildPlayContractCompatibility(input) {
59
65
  artifactVersion: PLAY_ARTIFACT_VERSION,
60
66
  minRunnerVersion: PLAY_MIN_RUNNER_VERSION,
61
67
  runtimeFeatures: [...PLAY_RUNTIME_FEATURES],
62
- runtimeBackend: input?.runtimeBackend ?? null
68
+ runtimeBackend: input?.runtimeBackend ?? null,
69
+ toolErrorSchemaVersion: input?.toolErrorSchemaVersion ?? TOOL_EXECUTION_ERROR_SCHEMA_VERSION
63
70
  };
64
71
  }
65
72
 
@@ -133,7 +140,7 @@ function validatePlaySourceFilesHaveNoInlineSecrets(sourceFiles) {
133
140
  var MAX_PLAY_BUNDLE_BYTES = 30 * 1024 * 1024;
134
141
 
135
142
  // ../shared_libs/plays/bundling/index.ts
136
- var PLAY_BUNDLE_CACHE_VERSION = 25;
143
+ var PLAY_BUNDLE_CACHE_VERSION = 27;
137
144
  var PLAY_ARTIFACT_CACHE_DIR = join(
138
145
  tmpdir(),
139
146
  `deepline-play-artifacts-v${PLAY_BUNDLE_CACHE_VERSION}`
@@ -283,15 +290,6 @@ function findSourceImportReferences(sourceCode) {
283
290
  function extractDefinedPlayName(sourceCode) {
284
291
  return extractDefinedPlayMetadata(sourceCode, null)?.name ?? null;
285
292
  }
286
- function extractDefinedPlayNameForExport(sourceCode, exportName) {
287
- return extractDefinedPlayMetadata(sourceCode, exportName)?.name ?? null;
288
- }
289
- function extractDefinedPlayDescription(sourceCode) {
290
- return extractDefinedPlayMetadata(sourceCode, null)?.description ?? null;
291
- }
292
- function extractDefinedPlayDescriptionForExport(sourceCode, exportName) {
293
- return extractDefinedPlayMetadata(sourceCode, exportName)?.description ?? null;
294
- }
295
293
  var TypeScriptParser = Parser.extend(
296
294
  tsPlugin({
297
295
  allowSatisfies: true,
@@ -499,9 +497,11 @@ function staticStringFromExpression(node, context, seen = /* @__PURE__ */ new Se
499
497
  );
500
498
  }
501
499
  function propertyNameFromKey(property) {
502
- if (property.computed) return null;
503
500
  const key = isAstNode(property.key) ? property.key : null;
504
501
  if (!key) return null;
502
+ if (property.computed) {
503
+ return key.type === "Literal" && typeof key.value === "string" ? key.value : null;
504
+ }
505
505
  if (key.type === "Identifier" && typeof key.name === "string") {
506
506
  return key.name;
507
507
  }
@@ -523,6 +523,77 @@ function objectExpressionFromNode(node, context, seen = /* @__PURE__ */ new Set(
523
523
  seen
524
524
  );
525
525
  }
526
+ function resolveStaticProperty(node, propertyName, context, ancestors = /* @__PURE__ */ new Set()) {
527
+ if (!node) return { kind: "absent" };
528
+ const object = objectExpressionFromNode(node, context);
529
+ if (!object) return { kind: "unknown" };
530
+ if (ancestors.has(object)) return { kind: "unknown" };
531
+ const nextAncestors = new Set(ancestors).add(object);
532
+ let resolution = { kind: "absent" };
533
+ for (const property of astArray(object.properties)) {
534
+ if (property.type === "SpreadElement") {
535
+ const spreadResolution = resolveStaticProperty(
536
+ isAstNode(property.argument) ? property.argument : null,
537
+ propertyName,
538
+ context,
539
+ nextAncestors
540
+ );
541
+ if (spreadResolution.kind !== "absent") {
542
+ resolution = spreadResolution;
543
+ }
544
+ continue;
545
+ }
546
+ if (property.type !== "Property") continue;
547
+ const resolvedPropertyName = propertyNameFromKey(property);
548
+ if (resolvedPropertyName !== propertyName) {
549
+ if (property.computed && resolvedPropertyName === null) {
550
+ resolution = { kind: "unknown" };
551
+ }
552
+ continue;
553
+ }
554
+ const propertyValue = property.shorthand ? property.key : property.value;
555
+ resolution = isAstNode(propertyValue) ? { kind: "found", value: propertyValue } : { kind: "unknown" };
556
+ }
557
+ return resolution;
558
+ }
559
+ function staticNumberFromExpression(node, context, seen = /* @__PURE__ */ new Set()) {
560
+ const expression = unwrapStaticExpression(node);
561
+ if (!expression) return null;
562
+ if (expression.type === "Literal" && typeof expression.value === "number") {
563
+ return expression.value;
564
+ }
565
+ const identifier = getIdentifierName(expression);
566
+ if (!identifier || seen.has(identifier)) return null;
567
+ seen.add(identifier);
568
+ return staticNumberFromExpression(
569
+ context.declarations.get(identifier),
570
+ context,
571
+ seen
572
+ );
573
+ }
574
+ function toolErrorSchemaVersionFromOptions(node, context) {
575
+ const directCompatibility = resolveStaticProperty(
576
+ node,
577
+ "compatibility",
578
+ context
579
+ );
580
+ if (directCompatibility.kind === "unknown") return null;
581
+ const bindings = resolveStaticProperty(node, "bindings", context);
582
+ if (bindings.kind === "unknown") return null;
583
+ const bindingCompatibility = bindings.kind === "found" ? resolveStaticProperty(bindings.value, "compatibility", context) : { kind: "absent" };
584
+ if (bindingCompatibility.kind === "unknown") return null;
585
+ const compatibility = directCompatibility.kind === "found" ? directCompatibility : bindingCompatibility;
586
+ if (compatibility.kind === "absent") return void 0;
587
+ const schema = resolveStaticProperty(
588
+ compatibility.value,
589
+ "toolErrorSchemaVersion",
590
+ context
591
+ );
592
+ if (schema.kind !== "found") return null;
593
+ const schemaVersion = staticNumberFromExpression(schema.value, context);
594
+ if (schemaVersion === 0 || schemaVersion === 1) return schemaVersion;
595
+ return null;
596
+ }
526
597
  function stringPropertyFromObjectExpression(node, propertyName, context, seenObjects = /* @__PURE__ */ new Set()) {
527
598
  const object = objectExpressionFromNode(node, context);
528
599
  if (!object || seenObjects.has(object)) return null;
@@ -568,12 +639,13 @@ function playMetadataFromDefinePlayCall(node, context) {
568
639
  }
569
640
  const args = astArray(expression.arguments);
570
641
  const firstArg = args[0] ?? null;
642
+ const isObjectForm = args.length === 1 || objectExpressionFromNode(firstArg, context) !== null;
571
643
  const objectName = stringPropertyFromObjectExpression(
572
644
  firstArg,
573
645
  "id",
574
646
  context
575
647
  );
576
- const name = objectName ?? staticStringFromExpression(firstArg, context);
648
+ const name = isObjectForm ? objectName : staticStringFromExpression(firstArg, context);
577
649
  let description = stringPropertyFromObjectExpression(firstArg, "description", context) ?? null;
578
650
  for (let index = args.length - 1; !description && index >= 2; index -= 1) {
579
651
  description = stringPropertyFromObjectExpression(
@@ -582,8 +654,21 @@ function playMetadataFromDefinePlayCall(node, context) {
582
654
  context
583
655
  );
584
656
  }
585
- if (!name && !description) return null;
586
- return { name, description };
657
+ const options = isObjectForm ? firstArg : args[2] ?? null;
658
+ const toolErrorSchemaVersion = toolErrorSchemaVersionFromOptions(
659
+ options,
660
+ context
661
+ );
662
+ const toolErrorSchemaVersionUnknown = toolErrorSchemaVersion === null;
663
+ if (!name && !description && toolErrorSchemaVersion === void 0 && !toolErrorSchemaVersionUnknown) {
664
+ return null;
665
+ }
666
+ return {
667
+ name,
668
+ description,
669
+ toolErrorSchemaVersion: toolErrorSchemaVersion ?? null,
670
+ toolErrorSchemaVersionUnknown
671
+ };
587
672
  }
588
673
  function resolveExportExpression(exportName, context) {
589
674
  if (exportName === "default") {
@@ -960,8 +1045,14 @@ async function analyzeSourceGraph(entryFile, adapter, exportName) {
960
1045
  })).sort((left, right) => left.filePath.localeCompare(right.filePath))
961
1046
  })
962
1047
  );
963
- const playName = extractDefinedPlayNameForExport(sourceCode, exportName) ?? (exportName === "default" ? extractDefinedPlayName(sourceCode) : null);
964
- const playDescription = extractDefinedPlayDescriptionForExport(sourceCode, exportName) ?? (exportName === "default" ? extractDefinedPlayDescription(sourceCode) : null);
1048
+ const metadata = extractDefinedPlayMetadata(sourceCode, exportName) ?? (exportName === "default" ? extractDefinedPlayMetadata(sourceCode, null) : null);
1049
+ if (metadata?.toolErrorSchemaVersionUnknown) {
1050
+ throw new Error(
1051
+ "definePlay compatibility.toolErrorSchemaVersion must be the static literal 0 or 1."
1052
+ );
1053
+ }
1054
+ const playName = metadata?.name ?? null;
1055
+ const playDescription = metadata?.description ?? null;
965
1056
  return {
966
1057
  sourceCode,
967
1058
  sourceFiles: Object.fromEntries(
@@ -978,6 +1069,7 @@ async function analyzeSourceGraph(entryFile, adapter, exportName) {
978
1069
  },
979
1070
  playName,
980
1071
  playDescription,
1072
+ toolErrorSchemaVersion: metadata?.toolErrorSchemaVersion ?? null,
981
1073
  importedPlayDependencies: [...importedPlayDependencies.values()].sort(
982
1074
  (left, right) => left.filePath.localeCompare(right.filePath)
983
1075
  )
@@ -1149,6 +1241,9 @@ entry-export:${exportName}`
1149
1241
  entryFile: absolutePath,
1150
1242
  sourceHash: analysis.sourceHash,
1151
1243
  importPolicy: analysis.importPolicy,
1244
+ compatibility: buildPlayContractCompatibility({
1245
+ toolErrorSchemaVersion: analysis.toolErrorSchemaVersion ?? void 0
1246
+ }),
1152
1247
  cacheHit: true
1153
1248
  },
1154
1249
  sourceCode: analysis.sourceCode,
@@ -1209,7 +1304,9 @@ entry-export:${exportName}`
1209
1304
  bundledCode: executableCode,
1210
1305
  sourceMap: normalizedSourceMap,
1211
1306
  importPolicy: analysis.importPolicy,
1212
- compatibility: buildPlayContractCompatibility(),
1307
+ compatibility: buildPlayContractCompatibility({
1308
+ toolErrorSchemaVersion: analysis.toolErrorSchemaVersion ?? void 0
1309
+ }),
1213
1310
  generatedAt: Date.now(),
1214
1311
  cacheHit: false
1215
1312
  };
@@ -237,4 +237,82 @@ type PlayCompilerManifest = {
237
237
  importedPlayDependencies: PlayCompilerDependencyManifest[];
238
238
  };
239
239
 
240
- export { type PlayArtifactKind as P, type PlayCompilerManifest as a, PLAY_ARTIFACT_KINDS as b };
240
+ declare const TOOL_EXECUTION_ERROR_SCHEMA_VERSION: 1;
241
+ declare const SUPPORTED_TOOL_EXECUTION_ERROR_SCHEMA_VERSIONS: readonly [0, 1];
242
+ type ToolExecutionErrorSchemaVersion = (typeof SUPPORTED_TOOL_EXECUTION_ERROR_SCHEMA_VERSIONS)[number];
243
+ type ToolExecutionErrorOrigin = 'caller' | 'provider' | 'deepline' | 'unknown';
244
+ type ToolExecutionErrorCategory = 'validation' | 'authentication' | 'authorization' | 'rate_limit' | 'network' | 'upstream' | 'billing' | 'conflict' | 'internal' | 'unknown';
245
+ type ToolExecutionNetworkKind = 'timeout' | 'dns' | 'connect' | 'reset' | 'unavailable' | 'unknown';
246
+ type ToolExecutionNetworkScope = 'client_to_deepline' | 'runtime_to_deepline' | 'deepline_to_provider';
247
+ type ToolExecutionFailureV1 = {
248
+ schemaVersion: typeof TOOL_EXECUTION_ERROR_SCHEMA_VERSION;
249
+ toolId: string;
250
+ provider: string | null;
251
+ operation: string | null;
252
+ code: string | null;
253
+ origin: ToolExecutionErrorOrigin;
254
+ category: ToolExecutionErrorCategory;
255
+ retryable: boolean;
256
+ statusCode: number | null;
257
+ requestId: string | null;
258
+ retryAfterMs: number | null;
259
+ networkKind: ToolExecutionNetworkKind | null;
260
+ networkScope: ToolExecutionNetworkScope | null;
261
+ };
262
+ type ToolExecutionErrorOptions = Omit<ToolExecutionFailureV1, 'schemaVersion'> & {
263
+ /**
264
+ * Local diagnostic context inherited from DeeplineError. This is not part of
265
+ * the portable failure payload and is intentionally omitted by serialization.
266
+ */
267
+ details?: Record<string, unknown>;
268
+ };
269
+ type ProviderTransientErrorCategory = 'rate_limit' | 'network' | 'upstream';
270
+ /**
271
+ * Base error class shared by the SDK and play runtime.
272
+ *
273
+ * The global brand preserves `instanceof DeeplineError` when a bundled play
274
+ * and the runtime load separate physical copies of this module.
275
+ */
276
+ declare class DeeplineError extends Error {
277
+ statusCode?: number | undefined;
278
+ code?: string | undefined;
279
+ details?: Record<string, unknown> | undefined;
280
+ constructor(message: string, statusCode?: number | undefined, code?: string | undefined, details?: Record<string, unknown> | undefined);
281
+ static [Symbol.hasInstance](value: unknown): boolean;
282
+ }
283
+ /**
284
+ * A failed `tools.execute` call with stable, allowlisted provenance.
285
+ *
286
+ * `retryable` means Deepline's delivery/idempotency contract says it is safe
287
+ * to repeat the same semantic call. It does not describe durable receipt
288
+ * repairability and does not make arbitrary side-effecting fallbacks safe.
289
+ */
290
+ declare class ToolExecutionError extends DeeplineError {
291
+ readonly toolId: string;
292
+ readonly provider: string | null;
293
+ readonly operation: string | null;
294
+ readonly origin: ToolExecutionErrorOrigin;
295
+ readonly category: ToolExecutionErrorCategory;
296
+ readonly retryable: boolean;
297
+ readonly requestId: string | null;
298
+ readonly retryAfterMs: number | null;
299
+ readonly networkKind: ToolExecutionNetworkKind | null;
300
+ readonly networkScope: ToolExecutionNetworkScope | null;
301
+ constructor(message: string, options: ToolExecutionErrorOptions);
302
+ static [Symbol.hasInstance](value: unknown): boolean;
303
+ }
304
+ /**
305
+ * A provider-owned transient failure that is safe to handle as an empty
306
+ * waterfall leg. Validation, auth, billing, Deepline, and unknown failures
307
+ * never satisfy this type.
308
+ */
309
+ declare class ProviderTransientError extends ToolExecutionError {
310
+ readonly origin: "provider";
311
+ readonly category: ProviderTransientErrorCategory;
312
+ constructor(message: string, options: Omit<ToolExecutionErrorOptions, 'origin' | 'category'> & {
313
+ category: ProviderTransientErrorCategory;
314
+ });
315
+ static [Symbol.hasInstance](value: unknown): boolean;
316
+ }
317
+
318
+ export { DeeplineError as D, type PlayArtifactKind as P, type ToolExecutionErrorSchemaVersion as T, type PlayCompilerManifest as a, PLAY_ARTIFACT_KINDS as b, ToolExecutionError as c, type ToolExecutionErrorOptions as d, ProviderTransientError as e };
@@ -237,4 +237,82 @@ type PlayCompilerManifest = {
237
237
  importedPlayDependencies: PlayCompilerDependencyManifest[];
238
238
  };
239
239
 
240
- export { type PlayArtifactKind as P, type PlayCompilerManifest as a, PLAY_ARTIFACT_KINDS as b };
240
+ declare const TOOL_EXECUTION_ERROR_SCHEMA_VERSION: 1;
241
+ declare const SUPPORTED_TOOL_EXECUTION_ERROR_SCHEMA_VERSIONS: readonly [0, 1];
242
+ type ToolExecutionErrorSchemaVersion = (typeof SUPPORTED_TOOL_EXECUTION_ERROR_SCHEMA_VERSIONS)[number];
243
+ type ToolExecutionErrorOrigin = 'caller' | 'provider' | 'deepline' | 'unknown';
244
+ type ToolExecutionErrorCategory = 'validation' | 'authentication' | 'authorization' | 'rate_limit' | 'network' | 'upstream' | 'billing' | 'conflict' | 'internal' | 'unknown';
245
+ type ToolExecutionNetworkKind = 'timeout' | 'dns' | 'connect' | 'reset' | 'unavailable' | 'unknown';
246
+ type ToolExecutionNetworkScope = 'client_to_deepline' | 'runtime_to_deepline' | 'deepline_to_provider';
247
+ type ToolExecutionFailureV1 = {
248
+ schemaVersion: typeof TOOL_EXECUTION_ERROR_SCHEMA_VERSION;
249
+ toolId: string;
250
+ provider: string | null;
251
+ operation: string | null;
252
+ code: string | null;
253
+ origin: ToolExecutionErrorOrigin;
254
+ category: ToolExecutionErrorCategory;
255
+ retryable: boolean;
256
+ statusCode: number | null;
257
+ requestId: string | null;
258
+ retryAfterMs: number | null;
259
+ networkKind: ToolExecutionNetworkKind | null;
260
+ networkScope: ToolExecutionNetworkScope | null;
261
+ };
262
+ type ToolExecutionErrorOptions = Omit<ToolExecutionFailureV1, 'schemaVersion'> & {
263
+ /**
264
+ * Local diagnostic context inherited from DeeplineError. This is not part of
265
+ * the portable failure payload and is intentionally omitted by serialization.
266
+ */
267
+ details?: Record<string, unknown>;
268
+ };
269
+ type ProviderTransientErrorCategory = 'rate_limit' | 'network' | 'upstream';
270
+ /**
271
+ * Base error class shared by the SDK and play runtime.
272
+ *
273
+ * The global brand preserves `instanceof DeeplineError` when a bundled play
274
+ * and the runtime load separate physical copies of this module.
275
+ */
276
+ declare class DeeplineError extends Error {
277
+ statusCode?: number | undefined;
278
+ code?: string | undefined;
279
+ details?: Record<string, unknown> | undefined;
280
+ constructor(message: string, statusCode?: number | undefined, code?: string | undefined, details?: Record<string, unknown> | undefined);
281
+ static [Symbol.hasInstance](value: unknown): boolean;
282
+ }
283
+ /**
284
+ * A failed `tools.execute` call with stable, allowlisted provenance.
285
+ *
286
+ * `retryable` means Deepline's delivery/idempotency contract says it is safe
287
+ * to repeat the same semantic call. It does not describe durable receipt
288
+ * repairability and does not make arbitrary side-effecting fallbacks safe.
289
+ */
290
+ declare class ToolExecutionError extends DeeplineError {
291
+ readonly toolId: string;
292
+ readonly provider: string | null;
293
+ readonly operation: string | null;
294
+ readonly origin: ToolExecutionErrorOrigin;
295
+ readonly category: ToolExecutionErrorCategory;
296
+ readonly retryable: boolean;
297
+ readonly requestId: string | null;
298
+ readonly retryAfterMs: number | null;
299
+ readonly networkKind: ToolExecutionNetworkKind | null;
300
+ readonly networkScope: ToolExecutionNetworkScope | null;
301
+ constructor(message: string, options: ToolExecutionErrorOptions);
302
+ static [Symbol.hasInstance](value: unknown): boolean;
303
+ }
304
+ /**
305
+ * A provider-owned transient failure that is safe to handle as an empty
306
+ * waterfall leg. Validation, auth, billing, Deepline, and unknown failures
307
+ * never satisfy this type.
308
+ */
309
+ declare class ProviderTransientError extends ToolExecutionError {
310
+ readonly origin: "provider";
311
+ readonly category: ProviderTransientErrorCategory;
312
+ constructor(message: string, options: Omit<ToolExecutionErrorOptions, 'origin' | 'category'> & {
313
+ category: ProviderTransientErrorCategory;
314
+ });
315
+ static [Symbol.hasInstance](value: unknown): boolean;
316
+ }
317
+
318
+ export { DeeplineError as D, type PlayArtifactKind as P, type ToolExecutionErrorSchemaVersion as T, type PlayCompilerManifest as a, PLAY_ARTIFACT_KINDS as b, ToolExecutionError as c, type ToolExecutionErrorOptions as d, ProviderTransientError as e };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deepline",
3
- "version": "0.1.301",
3
+ "version": "0.1.302",
4
4
  "description": "Deepline SDK + CLI — B2B data enrichment powered by durable cloud execution",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -1,166 +0,0 @@
1
- /**
2
- * A completed receipt is an immutable cache fact. Execution coordination is a
3
- * separate, short-lived concern and must never be represented by a "running"
4
- * receipt.
5
- */
6
- export type CompletedReceipt<T> = {
7
- key: string;
8
- output: T;
9
- createdAt: string;
10
- expiresAt?: string | null;
11
- };
12
-
13
- export type CompletedReceiptCache<T> = {
14
- get(key: string): Promise<CompletedReceipt<T> | null>;
15
- /**
16
- * Insert only when the key is absent. On conflict, return the already stored
17
- * immutable fact. Implementations should use INSERT ... ON CONFLICT DO
18
- * NOTHING followed by a point read.
19
- */
20
- putIfAbsent(receipt: CompletedReceipt<T>): Promise<CompletedReceipt<T>>;
21
- };
22
-
23
- export type ReceiptExecutionLock = {
24
- receiptKey: string;
25
- ownerExecutionId: string;
26
- expiresAt: string;
27
- };
28
-
29
- export type ReceiptExecutionLockStore = {
30
- tryAcquire(input: {
31
- receiptKey: string;
32
- ownerExecutionId: string;
33
- expiresAt: string;
34
- }): Promise<ReceiptExecutionLock | null>;
35
- release(input: {
36
- receiptKey: string;
37
- ownerExecutionId: string;
38
- }): Promise<void>;
39
- };
40
-
41
- export type ReceiptMissCoordination =
42
- | { kind: 'provider_idempotency' }
43
- | {
44
- kind: 'execution_lock';
45
- store: ReceiptExecutionLockStore;
46
- ownerExecutionId: string;
47
- lockTtlMs: number;
48
- waitTimeoutMs: number;
49
- pollIntervalMs?: number;
50
- };
51
-
52
- export class ReceiptExecutionLockTimeoutError extends Error {
53
- constructor(receiptKey: string, waitTimeoutMs: number) {
54
- super(
55
- `Timed out waiting ${waitTimeoutMs}ms for receipt execution lock ${receiptKey}.`,
56
- );
57
- this.name = 'ReceiptExecutionLockTimeoutError';
58
- }
59
- }
60
-
61
- const MAX_EXECUTION_LOCK_TTL_MS = 10 * 60_000;
62
-
63
- function assertBoundedLockPolicy(
64
- policy: Extract<ReceiptMissCoordination, { kind: 'execution_lock' }>,
65
- ): void {
66
- if (
67
- !Number.isFinite(policy.lockTtlMs) ||
68
- policy.lockTtlMs <= 0 ||
69
- policy.lockTtlMs > MAX_EXECUTION_LOCK_TTL_MS
70
- ) {
71
- throw new Error(
72
- `Receipt execution lock TTL must be between 1 and ${MAX_EXECUTION_LOCK_TTL_MS}ms.`,
73
- );
74
- }
75
- if (!Number.isFinite(policy.waitTimeoutMs) || policy.waitTimeoutMs <= 0) {
76
- throw new Error('Receipt execution lock wait timeout must be positive.');
77
- }
78
- }
79
-
80
- function sleep(ms: number): Promise<void> {
81
- return new Promise((resolve) => setTimeout(resolve, ms));
82
- }
83
-
84
- async function executeAndPublish<T>(input: {
85
- receiptKey: string;
86
- cache: CompletedReceiptCache<T>;
87
- execute: () => Promise<T>;
88
- now: () => number;
89
- receiptTtlMs?: number | null;
90
- }): Promise<T> {
91
- const output = await input.execute();
92
- const now = input.now();
93
- const receipt = await input.cache.putIfAbsent({
94
- key: input.receiptKey,
95
- output,
96
- createdAt: new Date(now).toISOString(),
97
- ...(input.receiptTtlMs
98
- ? { expiresAt: new Date(now + input.receiptTtlMs).toISOString() }
99
- : {}),
100
- });
101
- return receipt.output;
102
- }
103
-
104
- /**
105
- * Execute one semantic operation against an immutable completed-receipt cache.
106
- *
107
- * Providers with native idempotency do not need a Deepline execution lock:
108
- * concurrent misses may dispatch with the same provider idempotency key, then
109
- * converge on the first immutable cache insert. A separate temporary lock is
110
- * reserved for actions explicitly classified as dangerous non-idempotent side
111
- * effects. Ordinary enrichment misses may do bounded duplicate work and
112
- * converge on the first published receipt.
113
- */
114
- export async function executeWithCompletedReceiptCache<T>(input: {
115
- receiptKey: string;
116
- cache: CompletedReceiptCache<T>;
117
- missCoordination: ReceiptMissCoordination;
118
- execute: () => Promise<T>;
119
- now?: () => number;
120
- receiptTtlMs?: number | null;
121
- }): Promise<T> {
122
- const cached = await input.cache.get(input.receiptKey);
123
- if (cached) return cached.output;
124
-
125
- const now = input.now ?? Date.now;
126
- if (input.missCoordination.kind === 'provider_idempotency') {
127
- return await executeAndPublish({ ...input, now });
128
- }
129
-
130
- const policy = input.missCoordination;
131
- assertBoundedLockPolicy(policy);
132
- const deadline = now() + policy.waitTimeoutMs;
133
- const pollIntervalMs = Math.max(1, policy.pollIntervalMs ?? 100);
134
-
135
- while (true) {
136
- const lock = await policy.store.tryAcquire({
137
- receiptKey: input.receiptKey,
138
- ownerExecutionId: policy.ownerExecutionId,
139
- expiresAt: new Date(now() + policy.lockTtlMs).toISOString(),
140
- });
141
- if (lock) {
142
- try {
143
- // The previous owner may have published between our cache read and
144
- // lock acquisition. Never execute after that terminal fact exists.
145
- const afterAcquire = await input.cache.get(input.receiptKey);
146
- if (afterAcquire) return afterAcquire.output;
147
- return await executeAndPublish({ ...input, now });
148
- } finally {
149
- await policy.store.release({
150
- receiptKey: input.receiptKey,
151
- ownerExecutionId: policy.ownerExecutionId,
152
- });
153
- }
154
- }
155
-
156
- const completed = await input.cache.get(input.receiptKey);
157
- if (completed) return completed.output;
158
- if (now() >= deadline) {
159
- throw new ReceiptExecutionLockTimeoutError(
160
- input.receiptKey,
161
- policy.waitTimeoutMs,
162
- );
163
- }
164
- await sleep(Math.min(pollIntervalMs, Math.max(1, deadline - now())));
165
- }
166
- }