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
@@ -93,6 +93,10 @@ import {
93
93
  normalizePlayRuntimeSelection,
94
94
  type PlayRuntimeSelection,
95
95
  } from '../../shared_libs/play-runtime/runtime-environment.js';
96
+ import {
97
+ TOOL_EXECUTION_ERROR_SCHEMA_HEADER,
98
+ TOOL_EXECUTION_ERROR_SCHEMA_VERSION,
99
+ } from '../../shared_libs/tool-execution-error.js';
96
100
  import { decodePlayRunPublicStatus } from '../../shared_libs/play-runtime/run-lifecycle-policy.js';
97
101
 
98
102
  const TERMINAL_PLAY_STATUSES = new Set(['completed', 'failed', 'cancelled']);
@@ -1765,6 +1769,9 @@ export class DeeplineClient {
1765
1769
  ): Promise<ToolExecution<TData, TMeta>> {
1766
1770
  const headers = {
1767
1771
  [EXECUTE_RESPONSE_CONTRACT_HEADER]: V2_EXECUTE_RESPONSE_CONTRACT,
1772
+ [TOOL_EXECUTION_ERROR_SCHEMA_HEADER]: String(
1773
+ TOOL_EXECUTION_ERROR_SCHEMA_VERSION,
1774
+ ),
1768
1775
  ...(options?.includeToolMetadata
1769
1776
  ? { [INCLUDE_TOOL_METADATA_HEADER]: 'true' }
1770
1777
  : {}),
@@ -1782,6 +1789,7 @@ export class DeeplineClient {
1782
1789
  timeout: options?.timeout ?? resolveToolExecuteTimeoutMs(toolId, input),
1783
1790
  maxRetries: options?.maxRetries ?? 0,
1784
1791
  exactUrlOnly: true,
1792
+ toolId,
1785
1793
  },
1786
1794
  );
1787
1795
  }
@@ -1,3 +1,20 @@
1
+ import {
2
+ DeeplineError,
3
+ ProviderTransientError,
4
+ ToolExecutionError,
5
+ brandAsProviderTransientError,
6
+ brandAsToolExecutionError,
7
+ isProviderTransientFailure,
8
+ type ToolExecutionErrorOptions,
9
+ } from '../../shared_libs/tool-execution-error.js';
10
+
11
+ export {
12
+ DeeplineError,
13
+ ProviderTransientError,
14
+ ToolExecutionError,
15
+ type ToolExecutionErrorOptions,
16
+ } from '../../shared_libs/tool-execution-error.js';
17
+
1
18
  /**
2
19
  * Base error class for all Deepline SDK errors.
3
20
  *
@@ -20,21 +37,6 @@
20
37
  * }
21
38
  * ```
22
39
  */
23
- export class DeeplineError extends Error {
24
- constructor(
25
- message: string,
26
- /** HTTP status code from the API response, if applicable. */
27
- public statusCode?: number,
28
- /** Machine-readable error code (e.g. `'AUTH_ERROR'`, `'RATE_LIMIT'`, `'CONFIG_ERROR'`). */
29
- public code?: string,
30
- /** Additional context from the API response body. */
31
- public details?: Record<string, unknown>,
32
- ) {
33
- super(message);
34
- this.name = 'DeeplineError';
35
- }
36
- }
37
-
38
40
  /**
39
41
  * Thrown when the API rejects the request due to an invalid or missing API key.
40
42
  *
@@ -102,6 +104,46 @@ export class RateLimitError extends DeeplineError {
102
104
  }
103
105
  }
104
106
 
107
+ /**
108
+ * Tool-specific 429 preserving both historical RateLimitError catches and the
109
+ * structured ToolExecutionError ontology. JavaScript has one prototype chain,
110
+ * so this class extends RateLimitError and carries ToolExecutionError's stable
111
+ * cross-bundle brand.
112
+ */
113
+ export class ToolRateLimitError extends RateLimitError {
114
+ readonly toolId: string;
115
+ readonly provider: string | null;
116
+ readonly operation: string | null;
117
+ override readonly code: string | undefined;
118
+ readonly origin: ToolExecutionError['origin'];
119
+ readonly category: ToolExecutionError['category'];
120
+ readonly retryable: boolean;
121
+ readonly requestId: string | null;
122
+ readonly networkKind: ToolExecutionError['networkKind'];
123
+ readonly networkScope: ToolExecutionError['networkScope'];
124
+
125
+ constructor(message: string, options: ToolExecutionErrorOptions) {
126
+ super(options.retryAfterMs ?? 5_000, message);
127
+ this.name = 'ToolRateLimitError';
128
+ this.statusCode = options.statusCode ?? 429;
129
+ this.code = options.code ?? undefined;
130
+ this.toolId = options.toolId;
131
+ this.provider = options.provider;
132
+ this.operation = options.operation;
133
+ this.origin = options.origin;
134
+ this.category = options.category;
135
+ this.retryable = options.retryable;
136
+ this.requestId = options.requestId;
137
+ this.networkKind = options.networkKind;
138
+ this.networkScope = options.networkScope;
139
+ this.details = options.details;
140
+ brandAsToolExecutionError(this);
141
+ if (isProviderTransientFailure(this)) {
142
+ brandAsProviderTransientError(this);
143
+ }
144
+ }
145
+ }
146
+
105
147
  /**
106
148
  * Thrown when the SDK cannot resolve a valid configuration.
107
149
  *
@@ -22,7 +22,18 @@ import { existsSync, readFileSync } from 'node:fs';
22
22
  import { homedir } from 'node:os';
23
23
  import { join } from 'node:path';
24
24
  import type { ResolvedConfig } from './types.js';
25
- import { AuthError, DeeplineError, RateLimitError } from './errors.js';
25
+ import {
26
+ AuthError,
27
+ DeeplineError,
28
+ RateLimitError,
29
+ ToolExecutionError,
30
+ ToolRateLimitError,
31
+ } from './errors.js';
32
+ import {
33
+ deserializeToolExecutionFailure,
34
+ serializeToolExecutionFailure,
35
+ TOOL_EXECUTION_ERROR_SCHEMA_VERSION,
36
+ } from '../../shared_libs/tool-execution-error.js';
26
37
  import { SDK_API_CONTRACT, SDK_VERSION } from './version.js';
27
38
  import type { LiveEventEnvelope } from './types.js';
28
39
  import { baseUrlSlug, sdkCliStateDirPath } from './config.js';
@@ -67,6 +78,8 @@ interface RequestOptions {
67
78
  maxRetries?: number;
68
79
  /** Disable localhost/127.0.0.1 failover for non-idempotent requests. */
69
80
  exactUrlOnly?: boolean;
81
+ /** Enables endpoint-specific structured tool failure mapping. */
82
+ toolId?: string;
70
83
  }
71
84
 
72
85
  interface StreamOptions {
@@ -153,6 +166,10 @@ function providerLabelFromToolId(toolId: string): string {
153
166
  return provider || normalized || 'provider';
154
167
  }
155
168
 
169
+ function isRecord(value: unknown): value is Record<string, unknown> {
170
+ return value !== null && typeof value === 'object' && !Array.isArray(value);
171
+ }
172
+
156
173
  /**
157
174
  * Low-level HTTP client used internally by {@link DeeplineClient}.
158
175
  *
@@ -374,6 +391,41 @@ export class HttpClient {
374
391
 
375
392
  clearTimeout(timeoutId);
376
393
 
394
+ const body = await response.text();
395
+ const parsed = parseResponseBody(body);
396
+
397
+ const structuredToolError =
398
+ options?.toolId && !response.ok
399
+ ? deserializeToolExecutionFailure(
400
+ apiErrorMessage(parsed, response.status),
401
+ isRecord(parsed)
402
+ ? (parsed as Record<string, unknown>).tool_error
403
+ : null,
404
+ TOOL_EXECUTION_ERROR_SCHEMA_VERSION,
405
+ )
406
+ : null;
407
+ if (structuredToolError) {
408
+ if (response.status === 429) {
409
+ const retryAfter = parseRetryAfter(response);
410
+ const failure =
411
+ serializeToolExecutionFailure(structuredToolError);
412
+ lastError =
413
+ failure === null
414
+ ? structuredToolError
415
+ : new ToolRateLimitError(structuredToolError.message, {
416
+ ...failure,
417
+ retryAfterMs:
418
+ failure.retryAfterMs ?? Math.max(0, retryAfter),
419
+ });
420
+ if (attempt < maxRetries) {
421
+ retryAfterDelayMs = retryAfter;
422
+ break;
423
+ }
424
+ throw lastError;
425
+ }
426
+ throw structuredToolError;
427
+ }
428
+
377
429
  if (response.status === 429) {
378
430
  const retryAfter = parseRetryAfter(response);
379
431
  lastError = new RateLimitError(retryAfter);
@@ -384,9 +436,6 @@ export class HttpClient {
384
436
  throw lastError;
385
437
  }
386
438
 
387
- const body = await response.text();
388
- const parsed = parseResponseBody(body);
389
-
390
439
  if (
391
440
  (response.status === 401 &&
392
441
  !isProviderOriginatedHttpError(parsed)) ||
@@ -394,7 +443,6 @@ export class HttpClient {
394
443
  ) {
395
444
  throw new AuthError();
396
445
  }
397
-
398
446
  if (!response.ok) {
399
447
  const retryableApiError =
400
448
  options?.retryApiErrors === true &&
@@ -486,6 +534,34 @@ export class HttpClient {
486
534
  lastError,
487
535
  describeRequestTarget(path),
488
536
  );
537
+ if (options?.toolId) {
538
+ const code = mappedNetworkError.code;
539
+ throw new ToolExecutionError(
540
+ withCoworkNetworkHint(mappedNetworkError.message),
541
+ {
542
+ toolId: options.toolId,
543
+ provider: providerLabelFromToolId(options.toolId),
544
+ operation: options.toolId,
545
+ code,
546
+ origin: 'deepline',
547
+ category: 'network',
548
+ // A direct client timeout has ambiguous delivery. Fail closed unless
549
+ // the server returns the authoritative action delivery contract.
550
+ retryable: false,
551
+ statusCode: null,
552
+ requestId: null,
553
+ retryAfterMs: null,
554
+ networkKind:
555
+ code === 'NETWORK_TIMEOUT'
556
+ ? 'timeout'
557
+ : code === 'NETWORK_ABORTED'
558
+ ? 'unknown'
559
+ : 'unavailable',
560
+ networkScope: 'client_to_deepline',
561
+ details: mappedNetworkError.details,
562
+ },
563
+ );
564
+ }
489
565
  throw new DeeplineError(
490
566
  withCoworkNetworkHint(mappedNetworkError.message),
491
567
  undefined,
@@ -610,6 +686,7 @@ export class HttpClient {
610
686
  | 'timeout'
611
687
  | 'maxRetries'
612
688
  | 'exactUrlOnly'
689
+ | 'toolId'
613
690
  >,
614
691
  ): Promise<T> {
615
692
  return this.request<T>(path, {
@@ -123,10 +123,14 @@ export {
123
123
  // ——— Errors ———
124
124
  export {
125
125
  DeeplineError,
126
+ ProviderTransientError,
127
+ ToolExecutionError,
126
128
  AuthError,
127
129
  RateLimitError,
130
+ ToolRateLimitError,
128
131
  ConfigError,
129
132
  } from './errors.js';
133
+ export type { ToolExecutionErrorOptions } from './errors.js';
130
134
 
131
135
  // ——— Config ———
132
136
  export { resolveConfig, PROD_URL } from './config.js';
@@ -113,6 +113,7 @@ import type {
113
113
  ToolMetadata,
114
114
  } from './types.js';
115
115
  import type { ToolExecution } from './client.js';
116
+ import type { ToolExecutionErrorSchemaVersion } from '../../shared_libs/tool-execution-error.js';
116
117
 
117
118
  export type PlayCallExecution = 'inline' | 'child-workflow';
118
119
 
@@ -180,6 +181,16 @@ export type PlayBindings = {
180
181
  * older clients can continue to register revisions during the migration.
181
182
  */
182
183
  description?: string;
184
+ /**
185
+ * Public behavior that must remain pinned for this play artifact.
186
+ *
187
+ * New plays default to typed tool errors (`1`). Set `toolErrorSchemaVersion`
188
+ * to `0` only while migrating code that depends on legacy error names,
189
+ * messages, or classes.
190
+ */
191
+ compatibility?: {
192
+ toolErrorSchemaVersion: ToolExecutionErrorSchemaVersion;
193
+ };
183
194
  /** Allow compilers to bundle this named handler directly without a child run. */
184
195
  inline?: boolean;
185
196
  /** Optional per-run billing controls enforced by the runtime. */
@@ -903,7 +914,7 @@ export interface DeeplinePlayRuntimeContext {
903
914
  key: string,
904
915
  playRef: string | PlayReferenceLike,
905
916
  input: Record<string, unknown>,
906
- options: PlayCallOptions,
917
+ options?: PlayCallOptions,
907
918
  ): Promise<TOutput>;
908
919
 
909
920
  /**
@@ -1182,6 +1193,8 @@ export type DefinePlayConfig<TInput, TOutput extends PlayReturnObject> = {
1182
1193
  bindings?: PlayBindings;
1183
1194
  /** Billing options. */
1184
1195
  billing?: PlayBindings['billing'];
1196
+ /** Runtime compatibility override. Omit for the current typed contract. */
1197
+ compatibility?: PlayBindings['compatibility'];
1185
1198
  };
1186
1199
 
1187
1200
  class DeeplineConditionalStepResolver<
@@ -1341,6 +1354,8 @@ export type DefinedPlay<TInput, TOutput extends PlayReturnObject> = ((
1341
1354
  DeeplineNamedPlay<TInput, TOutput> & {
1342
1355
  /** Optional trigger bindings (cron, webhook). */
1343
1356
  readonly bindings?: PlayBindings;
1357
+ /** Runtime compatibility explicitly selected by the author. */
1358
+ readonly compatibility?: PlayBindings['compatibility'];
1344
1359
  /** The play's name (same as `.name`). */
1345
1360
  readonly playName: string;
1346
1361
  };
@@ -1351,6 +1366,7 @@ type PlayMetadata = {
1351
1366
  bindings?: PlayBindings;
1352
1367
  inputSchema?: Record<string, unknown>;
1353
1368
  billing?: PlayBindings['billing'];
1369
+ compatibility?: PlayBindings['compatibility'];
1354
1370
  };
1355
1371
 
1356
1372
  const PLAY_METADATA_SYMBOL = Symbol.for('deepline.play.metadata');
@@ -2108,6 +2124,7 @@ export function definePlay<TInput, TOutput extends PlayReturnObject>(
2108
2124
  description: maybeBindings?.description,
2109
2125
  inputSchema: undefined,
2110
2126
  billing: maybeBindings?.billing,
2127
+ compatibility: maybeBindings?.compatibility,
2111
2128
  }
2112
2129
  : {
2113
2130
  name: nameOrConfig.id,
@@ -2116,6 +2133,8 @@ export function definePlay<TInput, TOutput extends PlayReturnObject>(
2116
2133
  description: nameOrConfig.description,
2117
2134
  inputSchema: nameOrConfig.input.schema,
2118
2135
  billing: nameOrConfig.billing,
2136
+ compatibility:
2137
+ nameOrConfig.compatibility ?? nameOrConfig.bindings?.compatibility,
2119
2138
  };
2120
2139
  const name = config.name;
2121
2140
  const fn = config.fn;
@@ -2123,6 +2142,7 @@ export function definePlay<TInput, TOutput extends PlayReturnObject>(
2123
2142
  const description = config.description?.trim();
2124
2143
  const billing = config.billing;
2125
2144
  const inputSchema = config.inputSchema;
2145
+ const compatibility = config.compatibility;
2126
2146
  if (typeof fn !== 'function') {
2127
2147
  throw new Error('definePlay(...) requires an async run function.');
2128
2148
  }
@@ -2156,6 +2176,7 @@ export function definePlay<TInput, TOutput extends PlayReturnObject>(
2156
2176
  ...(bindings ? { bindings } : {}),
2157
2177
  ...(inputSchema ? { inputSchema } : {}),
2158
2178
  ...(billing ? { billing } : {}),
2179
+ ...(compatibility ? { compatibility } : {}),
2159
2180
  };
2160
2181
  const play = fn as DefinedPlay<TInput, TOutput>;
2161
2182
 
@@ -2180,6 +2201,13 @@ export function definePlay<TInput, TOutput extends PlayReturnObject>(
2180
2201
  writable: false,
2181
2202
  });
2182
2203
 
2204
+ Object.defineProperty(play, 'compatibility', {
2205
+ value: compatibility,
2206
+ enumerable: true,
2207
+ configurable: false,
2208
+ writable: false,
2209
+ });
2210
+
2183
2211
  const handle = createNamedPlayHandle<TInput, TOutput>(
2184
2212
  () => new DeeplineClient(),
2185
2213
  name,
@@ -1,3 +1,5 @@
1
+ import { CURRENT_PLAY_ARTIFACT_CONTRACT_VERSION } from '../../shared_libs/plays/artifact-contract-version';
2
+
1
3
  /**
2
4
  * Single source of truth for SDK release metadata.
3
5
  *
@@ -155,7 +157,7 @@ export const SDK_RELEASE = {
155
157
  // 0.1.253 makes play-page browser opening opt-in and retires --no-open.
156
158
  // 0.1.254 removes the internal operations tree from the published SDK CLI.
157
159
  // Operators use the checkout-local deepline-admin binary instead.
158
- version: '0.1.301',
160
+ version: '0.1.302',
159
161
  contracts: {
160
162
  api: {
161
163
  name: 'sdk-http-api',
@@ -171,8 +173,8 @@ export const SDK_RELEASE = {
171
173
  },
172
174
  playArtifact: {
173
175
  name: 'play-artifact-runtime',
174
- currentVersion: 2,
175
- supportedVersions: [1, 2],
176
+ currentVersion: CURRENT_PLAY_ARTIFACT_CONTRACT_VERSION,
177
+ supportedVersions: [1, CURRENT_PLAY_ARTIFACT_CONTRACT_VERSION],
176
178
  },
177
179
  release: {
178
180
  name: 'production-sdk-release',