deepline 0.1.56 → 0.1.58

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.
package/dist/index.js CHANGED
@@ -22,10 +22,21 @@ var src_exports = {};
22
22
  __export(src_exports, {
23
23
  AuthError: () => AuthError,
24
24
  ConfigError: () => ConfigError,
25
+ DEEPLINE_TOOL_CATEGORIES: () => DEEPLINE_TOOL_CATEGORIES,
25
26
  Deepline: () => Deepline,
26
27
  DeeplineClient: () => DeeplineClient,
27
28
  DeeplineContext: () => DeeplineContext,
28
29
  DeeplineError: () => DeeplineError,
30
+ PLAY_BOOTSTRAP_COMPANY_FIELDS: () => PLAY_BOOTSTRAP_COMPANY_FIELDS,
31
+ PLAY_BOOTSTRAP_COMPANY_PROVIDER_CATEGORY: () => PLAY_BOOTSTRAP_COMPANY_PROVIDER_CATEGORY,
32
+ PLAY_BOOTSTRAP_CONTACT_FIELDS: () => PLAY_BOOTSTRAP_CONTACT_FIELDS,
33
+ PLAY_BOOTSTRAP_FINDER_KINDS: () => PLAY_BOOTSTRAP_FINDER_KINDS,
34
+ PLAY_BOOTSTRAP_OUTPUT_FIELD_BY_FINDER: () => PLAY_BOOTSTRAP_OUTPUT_FIELD_BY_FINDER,
35
+ PLAY_BOOTSTRAP_PEOPLE_PROVIDER_CATEGORY: () => PLAY_BOOTSTRAP_PEOPLE_PROVIDER_CATEGORY,
36
+ PLAY_BOOTSTRAP_PROVIDER_CATEGORY_BY_FINDER: () => PLAY_BOOTSTRAP_PROVIDER_CATEGORY_BY_FINDER,
37
+ PLAY_BOOTSTRAP_SOURCE_KINDS: () => PLAY_BOOTSTRAP_SOURCE_KINDS,
38
+ PLAY_BOOTSTRAP_STAGE_KINDS: () => PLAY_BOOTSTRAP_STAGE_KINDS,
39
+ PLAY_BOOTSTRAP_TEMPLATES: () => PLAY_BOOTSTRAP_TEMPLATES,
29
40
  PROD_URL: () => PROD_URL,
30
41
  RateLimitError: () => RateLimitError,
31
42
  SDK_API_CONTRACT: () => SDK_API_CONTRACT,
@@ -34,7 +45,12 @@ __export(src_exports, {
34
45
  definePlay: () => definePlay,
35
46
  defineWorkflow: () => defineWorkflow,
36
47
  extractSummaryFields: () => extractSummaryFields,
48
+ formatPlayBootstrapFinderKinds: () => formatPlayBootstrapFinderKinds,
49
+ formatPlayBootstrapFinderKindsForSentence: () => formatPlayBootstrapFinderKindsForSentence,
50
+ formatPlayBootstrapTemplates: () => formatPlayBootstrapTemplates,
37
51
  getDefinedPlayMetadata: () => getDefinedPlayMetadata,
52
+ isPlayBootstrapFinderKind: () => isPlayBootstrapFinderKind,
53
+ isPlayBootstrapTemplate: () => isPlayBootstrapTemplate,
38
54
  resolveConfig: () => resolveConfig,
39
55
  steps: () => steps,
40
56
  tryConvertToList: () => tryConvertToList,
@@ -216,10 +232,10 @@ function resolveConfig(options) {
216
232
 
217
233
  // src/release.ts
218
234
  var SDK_RELEASE = {
219
- version: "0.1.56",
235
+ version: "0.1.58",
220
236
  apiContract: "2026-05-play-tool-describe-starters",
221
237
  supportPolicy: {
222
- latest: "0.1.56",
238
+ latest: "0.1.58",
223
239
  minimumSupported: "0.1.53",
224
240
  deprecatedBelow: "0.1.53"
225
241
  }
@@ -1684,6 +1700,91 @@ var DeeplineClient = class {
1684
1700
  }
1685
1701
  };
1686
1702
 
1703
+ // ../shared_libs/plays/bootstrap-routes.ts
1704
+ var DEEPLINE_TOOL_CATEGORIES = [
1705
+ "company_search",
1706
+ "people_search",
1707
+ "people_enrich",
1708
+ "email_finder",
1709
+ "email_verify",
1710
+ "phone_finder",
1711
+ "phone_verify",
1712
+ "identity_resolution",
1713
+ "reverse_lookup",
1714
+ "enrichment",
1715
+ "batch",
1716
+ "premium",
1717
+ "free"
1718
+ ];
1719
+ var PLAY_BOOTSTRAP_TEMPLATES = [
1720
+ "people-list",
1721
+ "company-list",
1722
+ "people-email",
1723
+ "people-phone",
1724
+ "company-people",
1725
+ "company-people-email",
1726
+ "company-people-phone"
1727
+ ];
1728
+ var PLAY_BOOTSTRAP_SOURCE_KINDS = [
1729
+ "csv",
1730
+ "play",
1731
+ "provider",
1732
+ "providers"
1733
+ ];
1734
+ var PLAY_BOOTSTRAP_STAGE_KINDS = [
1735
+ "play",
1736
+ "provider",
1737
+ "providers"
1738
+ ];
1739
+ var PLAY_BOOTSTRAP_FINDER_KINDS = [
1740
+ "email_finder",
1741
+ "phone_finder"
1742
+ ];
1743
+ var PLAY_BOOTSTRAP_COMPANY_PROVIDER_CATEGORY = "company_search";
1744
+ var PLAY_BOOTSTRAP_PEOPLE_PROVIDER_CATEGORY = "people_search";
1745
+ var PLAY_BOOTSTRAP_PROVIDER_CATEGORY_BY_FINDER = {
1746
+ email_finder: "email_finder",
1747
+ phone_finder: "phone_finder"
1748
+ };
1749
+ var PLAY_BOOTSTRAP_OUTPUT_FIELD_BY_FINDER = {
1750
+ email_finder: "email",
1751
+ phone_finder: "phone"
1752
+ };
1753
+ var PLAY_BOOTSTRAP_CONTACT_FIELDS = [
1754
+ "first_name",
1755
+ "last_name",
1756
+ "domain",
1757
+ "company_name",
1758
+ "linkedin_url",
1759
+ "title",
1760
+ "email",
1761
+ "phone"
1762
+ ];
1763
+ var PLAY_BOOTSTRAP_COMPANY_FIELDS = [
1764
+ "domain",
1765
+ "company_domain",
1766
+ "company_name",
1767
+ "linkedin_url",
1768
+ "website"
1769
+ ];
1770
+ function isPlayBootstrapFinderKind(value) {
1771
+ return PLAY_BOOTSTRAP_FINDER_KINDS.includes(value);
1772
+ }
1773
+ function isPlayBootstrapTemplate(value) {
1774
+ return PLAY_BOOTSTRAP_TEMPLATES.includes(value);
1775
+ }
1776
+ function formatPlayBootstrapFinderKinds() {
1777
+ return PLAY_BOOTSTRAP_FINDER_KINDS.join("|");
1778
+ }
1779
+ function formatPlayBootstrapTemplates() {
1780
+ return PLAY_BOOTSTRAP_TEMPLATES.join("|");
1781
+ }
1782
+ function formatPlayBootstrapFinderKindsForSentence() {
1783
+ const allButLast = PLAY_BOOTSTRAP_FINDER_KINDS.slice(0, -1);
1784
+ const last = PLAY_BOOTSTRAP_FINDER_KINDS.at(-1);
1785
+ return `${allButLast.join(", ")} or ${last}`;
1786
+ }
1787
+
1687
1788
  // ../shared_libs/play-runtime/tool-result.ts
1688
1789
  var TARGET_FALLBACK_KEYS = {
1689
1790
  email: [/^email$/i, /^address$/i, /email/i],
@@ -2742,10 +2843,21 @@ function extractSummaryFields(payload) {
2742
2843
  0 && (module.exports = {
2743
2844
  AuthError,
2744
2845
  ConfigError,
2846
+ DEEPLINE_TOOL_CATEGORIES,
2745
2847
  Deepline,
2746
2848
  DeeplineClient,
2747
2849
  DeeplineContext,
2748
2850
  DeeplineError,
2851
+ PLAY_BOOTSTRAP_COMPANY_FIELDS,
2852
+ PLAY_BOOTSTRAP_COMPANY_PROVIDER_CATEGORY,
2853
+ PLAY_BOOTSTRAP_CONTACT_FIELDS,
2854
+ PLAY_BOOTSTRAP_FINDER_KINDS,
2855
+ PLAY_BOOTSTRAP_OUTPUT_FIELD_BY_FINDER,
2856
+ PLAY_BOOTSTRAP_PEOPLE_PROVIDER_CATEGORY,
2857
+ PLAY_BOOTSTRAP_PROVIDER_CATEGORY_BY_FINDER,
2858
+ PLAY_BOOTSTRAP_SOURCE_KINDS,
2859
+ PLAY_BOOTSTRAP_STAGE_KINDS,
2860
+ PLAY_BOOTSTRAP_TEMPLATES,
2749
2861
  PROD_URL,
2750
2862
  RateLimitError,
2751
2863
  SDK_API_CONTRACT,
@@ -2754,7 +2866,12 @@ function extractSummaryFields(payload) {
2754
2866
  definePlay,
2755
2867
  defineWorkflow,
2756
2868
  extractSummaryFields,
2869
+ formatPlayBootstrapFinderKinds,
2870
+ formatPlayBootstrapFinderKindsForSentence,
2871
+ formatPlayBootstrapTemplates,
2757
2872
  getDefinedPlayMetadata,
2873
+ isPlayBootstrapFinderKind,
2874
+ isPlayBootstrapTemplate,
2758
2875
  resolveConfig,
2759
2876
  steps,
2760
2877
  tryConvertToList,
package/dist/index.mjs CHANGED
@@ -170,10 +170,10 @@ function resolveConfig(options) {
170
170
 
171
171
  // src/release.ts
172
172
  var SDK_RELEASE = {
173
- version: "0.1.56",
173
+ version: "0.1.58",
174
174
  apiContract: "2026-05-play-tool-describe-starters",
175
175
  supportPolicy: {
176
- latest: "0.1.56",
176
+ latest: "0.1.58",
177
177
  minimumSupported: "0.1.53",
178
178
  deprecatedBelow: "0.1.53"
179
179
  }
@@ -1638,6 +1638,91 @@ var DeeplineClient = class {
1638
1638
  }
1639
1639
  };
1640
1640
 
1641
+ // ../shared_libs/plays/bootstrap-routes.ts
1642
+ var DEEPLINE_TOOL_CATEGORIES = [
1643
+ "company_search",
1644
+ "people_search",
1645
+ "people_enrich",
1646
+ "email_finder",
1647
+ "email_verify",
1648
+ "phone_finder",
1649
+ "phone_verify",
1650
+ "identity_resolution",
1651
+ "reverse_lookup",
1652
+ "enrichment",
1653
+ "batch",
1654
+ "premium",
1655
+ "free"
1656
+ ];
1657
+ var PLAY_BOOTSTRAP_TEMPLATES = [
1658
+ "people-list",
1659
+ "company-list",
1660
+ "people-email",
1661
+ "people-phone",
1662
+ "company-people",
1663
+ "company-people-email",
1664
+ "company-people-phone"
1665
+ ];
1666
+ var PLAY_BOOTSTRAP_SOURCE_KINDS = [
1667
+ "csv",
1668
+ "play",
1669
+ "provider",
1670
+ "providers"
1671
+ ];
1672
+ var PLAY_BOOTSTRAP_STAGE_KINDS = [
1673
+ "play",
1674
+ "provider",
1675
+ "providers"
1676
+ ];
1677
+ var PLAY_BOOTSTRAP_FINDER_KINDS = [
1678
+ "email_finder",
1679
+ "phone_finder"
1680
+ ];
1681
+ var PLAY_BOOTSTRAP_COMPANY_PROVIDER_CATEGORY = "company_search";
1682
+ var PLAY_BOOTSTRAP_PEOPLE_PROVIDER_CATEGORY = "people_search";
1683
+ var PLAY_BOOTSTRAP_PROVIDER_CATEGORY_BY_FINDER = {
1684
+ email_finder: "email_finder",
1685
+ phone_finder: "phone_finder"
1686
+ };
1687
+ var PLAY_BOOTSTRAP_OUTPUT_FIELD_BY_FINDER = {
1688
+ email_finder: "email",
1689
+ phone_finder: "phone"
1690
+ };
1691
+ var PLAY_BOOTSTRAP_CONTACT_FIELDS = [
1692
+ "first_name",
1693
+ "last_name",
1694
+ "domain",
1695
+ "company_name",
1696
+ "linkedin_url",
1697
+ "title",
1698
+ "email",
1699
+ "phone"
1700
+ ];
1701
+ var PLAY_BOOTSTRAP_COMPANY_FIELDS = [
1702
+ "domain",
1703
+ "company_domain",
1704
+ "company_name",
1705
+ "linkedin_url",
1706
+ "website"
1707
+ ];
1708
+ function isPlayBootstrapFinderKind(value) {
1709
+ return PLAY_BOOTSTRAP_FINDER_KINDS.includes(value);
1710
+ }
1711
+ function isPlayBootstrapTemplate(value) {
1712
+ return PLAY_BOOTSTRAP_TEMPLATES.includes(value);
1713
+ }
1714
+ function formatPlayBootstrapFinderKinds() {
1715
+ return PLAY_BOOTSTRAP_FINDER_KINDS.join("|");
1716
+ }
1717
+ function formatPlayBootstrapTemplates() {
1718
+ return PLAY_BOOTSTRAP_TEMPLATES.join("|");
1719
+ }
1720
+ function formatPlayBootstrapFinderKindsForSentence() {
1721
+ const allButLast = PLAY_BOOTSTRAP_FINDER_KINDS.slice(0, -1);
1722
+ const last = PLAY_BOOTSTRAP_FINDER_KINDS.at(-1);
1723
+ return `${allButLast.join(", ")} or ${last}`;
1724
+ }
1725
+
1641
1726
  // ../shared_libs/play-runtime/tool-result.ts
1642
1727
  var TARGET_FALLBACK_KEYS = {
1643
1728
  email: [/^email$/i, /^address$/i, /email/i],
@@ -2695,10 +2780,21 @@ function extractSummaryFields(payload) {
2695
2780
  export {
2696
2781
  AuthError,
2697
2782
  ConfigError,
2783
+ DEEPLINE_TOOL_CATEGORIES,
2698
2784
  Deepline,
2699
2785
  DeeplineClient,
2700
2786
  DeeplineContext,
2701
2787
  DeeplineError,
2788
+ PLAY_BOOTSTRAP_COMPANY_FIELDS,
2789
+ PLAY_BOOTSTRAP_COMPANY_PROVIDER_CATEGORY,
2790
+ PLAY_BOOTSTRAP_CONTACT_FIELDS,
2791
+ PLAY_BOOTSTRAP_FINDER_KINDS,
2792
+ PLAY_BOOTSTRAP_OUTPUT_FIELD_BY_FINDER,
2793
+ PLAY_BOOTSTRAP_PEOPLE_PROVIDER_CATEGORY,
2794
+ PLAY_BOOTSTRAP_PROVIDER_CATEGORY_BY_FINDER,
2795
+ PLAY_BOOTSTRAP_SOURCE_KINDS,
2796
+ PLAY_BOOTSTRAP_STAGE_KINDS,
2797
+ PLAY_BOOTSTRAP_TEMPLATES,
2702
2798
  PROD_URL,
2703
2799
  RateLimitError,
2704
2800
  SDK_API_CONTRACT,
@@ -2707,7 +2803,12 @@ export {
2707
2803
  definePlay,
2708
2804
  defineWorkflow,
2709
2805
  extractSummaryFields,
2806
+ formatPlayBootstrapFinderKinds,
2807
+ formatPlayBootstrapFinderKindsForSentence,
2808
+ formatPlayBootstrapTemplates,
2710
2809
  getDefinedPlayMetadata,
2810
+ isPlayBootstrapFinderKind,
2811
+ isPlayBootstrapTemplate,
2711
2812
  resolveConfig,
2712
2813
  steps,
2713
2814
  tryConvertToList,
@@ -130,6 +130,12 @@ import type {
130
130
  LiveNodeProgressMap,
131
131
  LiveNodeProgressSnapshot,
132
132
  } from './runtime/live-progress';
133
+ import {
134
+ ToolHttpError,
135
+ extractErrorBilling,
136
+ isHardBillingToolHttpError,
137
+ normalizeToolHttpErrorMessage,
138
+ } from './runtime/tool-http-errors';
133
139
 
134
140
  // The play's default export. The bundler injects this — see bundle-play-file.ts.
135
141
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
@@ -195,23 +201,6 @@ const EXECUTE_TOOL_METADATA_HEADER = 'x-deepline-include-tool-metadata';
195
201
  const EXECUTE_RESPONSE_CONTRACT_HEADER = 'x-deepline-execute-response-contract';
196
202
  const V2_EXECUTE_RESPONSE_CONTRACT = 'v2-tool-execution-result';
197
203
 
198
- class ToolHttpError extends Error {
199
- readonly billing: Record<string, unknown> | null;
200
-
201
- constructor(message: string, billing: Record<string, unknown> | null) {
202
- super(message);
203
- this.name = 'ToolHttpError';
204
- this.billing = billing;
205
- }
206
- }
207
-
208
- function formatCreditAmount(value: unknown): string {
209
- if (typeof value !== 'number' || !Number.isFinite(value)) {
210
- return String(value ?? '-');
211
- }
212
- return Number(value.toFixed(8)).toString();
213
- }
214
-
215
204
  function getStringField(value: unknown, key: string): string | null {
216
205
  if (!isRecord(value)) return null;
217
206
  const field = value[key];
@@ -227,71 +216,6 @@ function getObjectField(
227
216
  return isRecord(field) ? field : null;
228
217
  }
229
218
 
230
- function isInsufficientCreditsBilling(
231
- billing: Record<string, unknown> | null,
232
- ): billing is Record<string, unknown> {
233
- return billing?.kind === 'insufficient_credits';
234
- }
235
-
236
- function formatInsufficientCreditsMessage(input: {
237
- billing: Record<string, unknown>;
238
- toolId: string;
239
- }): string {
240
- const operation =
241
- getStringField(input.billing, 'operation_id') ??
242
- getStringField(input.billing, 'operation') ??
243
- input.toolId;
244
- const balance = formatCreditAmount(input.billing.balance_credits);
245
- const required = formatCreditAmount(input.billing.required_credits);
246
- const recommended = formatCreditAmount(
247
- input.billing.recommended_add_credits ?? input.billing.needed_credits,
248
- );
249
- const billingUrl = getStringField(input.billing, 'billing_url');
250
- const addSuffix =
251
- billingUrl && recommended !== '-'
252
- ? ` Add >=${recommended} at ${billingUrl}.`
253
- : billingUrl
254
- ? ` Add credits at ${billingUrl}.`
255
- : '';
256
- return `Workspace balance ${balance} < required ${required} for ${operation}.${addSuffix}`;
257
- }
258
-
259
- function normalizeToolHttpErrorMessage(input: {
260
- toolId: string;
261
- status: number;
262
- attempt: number;
263
- maxAttempts: number;
264
- bodyText: string;
265
- }): ToolHttpError {
266
- let parsed: Record<string, unknown> | null = null;
267
- try {
268
- const candidate = JSON.parse(input.bodyText);
269
- parsed = isRecord(candidate) ? candidate : null;
270
- } catch {
271
- parsed = null;
272
- }
273
- const billing = getObjectField(parsed, 'billing');
274
- if (isInsufficientCreditsBilling(billing)) {
275
- return new ToolHttpError(
276
- `tool ${input.toolId} ${input.status} attempt ${input.attempt}/${input.maxAttempts}: ${formatInsufficientCreditsMessage(
277
- {
278
- billing,
279
- toolId: input.toolId,
280
- },
281
- )}`,
282
- billing,
283
- );
284
- }
285
- return new ToolHttpError(
286
- `tool ${input.toolId} ${input.status} attempt ${input.attempt}/${input.maxAttempts}: ${input.bodyText.slice(0, 500)}`,
287
- billing,
288
- );
289
- }
290
-
291
- function extractErrorBilling(error: unknown): Record<string, unknown> | null {
292
- return error instanceof ToolHttpError ? error.billing : null;
293
- }
294
-
295
219
  /** R2 binding injected by the Worker runtime (when present in deploy metadata). */
296
220
  type WorkerEnv = {
297
221
  PLAYS_BUCKET?: R2Bucket;
@@ -1348,7 +1272,7 @@ async function callToolDirect(
1348
1272
  bodyText: text,
1349
1273
  });
1350
1274
  const retryable =
1351
- res.status === 429 ||
1275
+ (res.status === 429 && !isHardBillingToolHttpError(lastError)) ||
1352
1276
  (res.status >= 500 && WORKER_RETRY_SAFE_5XX_TOOLS.has(toolId));
1353
1277
  if (!retryable || attempt >= maxAttempts) {
1354
1278
  throw lastError;
@@ -0,0 +1,198 @@
1
+ export class ToolHttpError extends Error {
2
+ readonly billing: Record<string, unknown> | null;
3
+
4
+ constructor(message: string, billing: Record<string, unknown> | null) {
5
+ super(message);
6
+ this.name = 'ToolHttpError';
7
+ this.billing = billing;
8
+ }
9
+ }
10
+
11
+ function formatCreditAmount(value: unknown): string {
12
+ if (typeof value !== 'number' || !Number.isFinite(value)) {
13
+ return String(value ?? '-');
14
+ }
15
+ return Number(value.toFixed(8)).toString();
16
+ }
17
+
18
+ function isRecord(value: unknown): value is Record<string, unknown> {
19
+ return value !== null && typeof value === 'object' && !Array.isArray(value);
20
+ }
21
+
22
+ function getStringField(value: unknown, key: string): string | null {
23
+ if (!isRecord(value)) return null;
24
+ const field = value[key];
25
+ return typeof field === 'string' && field.trim() ? field : null;
26
+ }
27
+
28
+ function getObjectField(
29
+ value: unknown,
30
+ key: string,
31
+ ): Record<string, unknown> | null {
32
+ if (!isRecord(value)) return null;
33
+ const field = value[key];
34
+ return isRecord(field) ? field : null;
35
+ }
36
+
37
+ function isInsufficientCreditsBilling(
38
+ billing: Record<string, unknown> | null,
39
+ ): billing is Record<string, unknown> {
40
+ return billing?.kind === 'insufficient_credits';
41
+ }
42
+
43
+ function isHardBillingFailurePayload(
44
+ payload: Record<string, unknown> | null,
45
+ ): payload is Record<string, unknown> {
46
+ if (!payload) return false;
47
+ const category = String(
48
+ payload.error_category ?? payload.errorCategory ?? '',
49
+ ).toLowerCase();
50
+ const code = String(payload.code ?? payload.error_code ?? '').toUpperCase();
51
+ const message = String(
52
+ payload.error ?? payload.message ?? payload.failure_description ?? '',
53
+ ).toLowerCase();
54
+ if (category === 'billing') return true;
55
+ if (
56
+ code === 'INSUFFICIENT_CREDITS' ||
57
+ code === 'BILLING_CAP_EXCEEDED' ||
58
+ code === 'MONTHLY_BILLING_LIMIT_EXCEEDED'
59
+ ) {
60
+ return true;
61
+ }
62
+ return (
63
+ (message.includes('billing cap') ||
64
+ message.includes('monthly billing limit') ||
65
+ message.includes('rolling 30-day organization billing cap') ||
66
+ message.includes('insufficient credits')) &&
67
+ !message.includes('rate limit')
68
+ );
69
+ }
70
+
71
+ function normalizeHardBillingPayload(
72
+ payload: Record<string, unknown>,
73
+ ): Record<string, unknown> {
74
+ return {
75
+ kind: 'billing_cap_exceeded',
76
+ code:
77
+ typeof payload.code === 'string' && payload.code.trim()
78
+ ? payload.code
79
+ : 'MONTHLY_BILLING_LIMIT_EXCEEDED',
80
+ error_category: 'billing',
81
+ failure_origin:
82
+ typeof payload.failure_origin === 'string' && payload.failure_origin.trim()
83
+ ? payload.failure_origin
84
+ : 'deepline_billing',
85
+ message:
86
+ typeof payload.error === 'string' && payload.error.trim()
87
+ ? payload.error
88
+ : typeof payload.message === 'string' && payload.message.trim()
89
+ ? payload.message
90
+ : 'Deepline billing cap exceeded.',
91
+ ...payload,
92
+ };
93
+ }
94
+
95
+ function formatHardBillingFailureMessage(input: {
96
+ billing: Record<string, unknown>;
97
+ toolId: string;
98
+ status: number;
99
+ attempt: number;
100
+ maxAttempts: number;
101
+ }): string {
102
+ const code = getStringField(input.billing, 'code');
103
+ const message =
104
+ getStringField(input.billing, 'message') ??
105
+ getStringField(input.billing, 'error') ??
106
+ 'Deepline billing cap exceeded.';
107
+ return [
108
+ `tool ${input.toolId} ${input.status} attempt ${input.attempt}/${input.maxAttempts}:`,
109
+ 'Deepline billing cap exceeded.',
110
+ 'Run halted before marking remaining rows processed.',
111
+ code ? `code=${code}.` : '',
112
+ message,
113
+ ]
114
+ .filter(Boolean)
115
+ .join(' ');
116
+ }
117
+
118
+ function formatInsufficientCreditsMessage(input: {
119
+ billing: Record<string, unknown>;
120
+ toolId: string;
121
+ }): string {
122
+ const operation =
123
+ getStringField(input.billing, 'operation_id') ??
124
+ getStringField(input.billing, 'operation') ??
125
+ input.toolId;
126
+ const balance = formatCreditAmount(input.billing.balance_credits);
127
+ const required = formatCreditAmount(input.billing.required_credits);
128
+ const recommended = formatCreditAmount(
129
+ input.billing.recommended_add_credits ?? input.billing.needed_credits,
130
+ );
131
+ const billingUrl = getStringField(input.billing, 'billing_url');
132
+ const addSuffix =
133
+ billingUrl && recommended !== '-'
134
+ ? ` Add >=${recommended} at ${billingUrl}.`
135
+ : billingUrl
136
+ ? ` Add credits at ${billingUrl}.`
137
+ : '';
138
+ return `Workspace balance ${balance} < required ${required} for ${operation}.${addSuffix}`;
139
+ }
140
+
141
+ export function normalizeToolHttpErrorMessage(input: {
142
+ toolId: string;
143
+ status: number;
144
+ attempt: number;
145
+ maxAttempts: number;
146
+ bodyText: string;
147
+ }): ToolHttpError {
148
+ let parsed: Record<string, unknown> | null = null;
149
+ try {
150
+ const candidate = JSON.parse(input.bodyText);
151
+ parsed = isRecord(candidate) ? candidate : null;
152
+ } catch {
153
+ parsed = null;
154
+ }
155
+ const billing = getObjectField(parsed, 'billing');
156
+ if (isInsufficientCreditsBilling(billing)) {
157
+ return new ToolHttpError(
158
+ `tool ${input.toolId} ${input.status} attempt ${input.attempt}/${input.maxAttempts}: ${formatInsufficientCreditsMessage(
159
+ {
160
+ billing,
161
+ toolId: input.toolId,
162
+ },
163
+ )}`,
164
+ billing,
165
+ );
166
+ }
167
+ const hardBillingPayload = isHardBillingFailurePayload(billing)
168
+ ? normalizeHardBillingPayload(billing)
169
+ : isHardBillingFailurePayload(parsed)
170
+ ? normalizeHardBillingPayload(parsed)
171
+ : null;
172
+ if (hardBillingPayload) {
173
+ return new ToolHttpError(
174
+ formatHardBillingFailureMessage({
175
+ billing: hardBillingPayload,
176
+ toolId: input.toolId,
177
+ status: input.status,
178
+ attempt: input.attempt,
179
+ maxAttempts: input.maxAttempts,
180
+ }),
181
+ hardBillingPayload,
182
+ );
183
+ }
184
+ return new ToolHttpError(
185
+ `tool ${input.toolId} ${input.status} attempt ${input.attempt}/${input.maxAttempts}: ${input.bodyText.slice(0, 500)}`,
186
+ billing,
187
+ );
188
+ }
189
+
190
+ export function extractErrorBilling(
191
+ error: unknown,
192
+ ): Record<string, unknown> | null {
193
+ return error instanceof ToolHttpError ? error.billing : null;
194
+ }
195
+
196
+ export function isHardBillingToolHttpError(error: unknown): boolean {
197
+ return error instanceof ToolHttpError && isHardBillingFailurePayload(error.billing);
198
+ }
@@ -57,6 +57,24 @@
57
57
  export { DeeplineClient } from './client.js';
58
58
  export type { PlayStatus, ToolExecution } from './client.js';
59
59
  export { SDK_API_CONTRACT, SDK_VERSION } from './version.js';
60
+ export {
61
+ DEEPLINE_TOOL_CATEGORIES,
62
+ PLAY_BOOTSTRAP_COMPANY_FIELDS,
63
+ PLAY_BOOTSTRAP_COMPANY_PROVIDER_CATEGORY,
64
+ PLAY_BOOTSTRAP_CONTACT_FIELDS,
65
+ PLAY_BOOTSTRAP_FINDER_KINDS,
66
+ PLAY_BOOTSTRAP_OUTPUT_FIELD_BY_FINDER,
67
+ PLAY_BOOTSTRAP_PEOPLE_PROVIDER_CATEGORY,
68
+ PLAY_BOOTSTRAP_PROVIDER_CATEGORY_BY_FINDER,
69
+ PLAY_BOOTSTRAP_STAGE_KINDS,
70
+ PLAY_BOOTSTRAP_SOURCE_KINDS,
71
+ PLAY_BOOTSTRAP_TEMPLATES,
72
+ formatPlayBootstrapFinderKinds,
73
+ formatPlayBootstrapFinderKindsForSentence,
74
+ formatPlayBootstrapTemplates,
75
+ isPlayBootstrapFinderKind,
76
+ isPlayBootstrapTemplate,
77
+ } from '../../shared_libs/plays/bootstrap-routes.js';
60
78
 
61
79
  // ——— Errors ———
62
80
  export {
@@ -106,6 +124,9 @@ export type {
106
124
  PublishPlayVersionResult,
107
125
  StartPlayRunRequest,
108
126
  PlayListItem,
127
+ DeeplineToolCategory,
128
+ PlayBootstrapFinderKind,
129
+ PlayBootstrapEntityKind,
109
130
  } from './types.js';
110
131
 
111
132
  export type {
@@ -534,28 +534,12 @@ export interface DeeplinePlayRuntimeContext {
534
534
  bodyText: string;
535
535
  json: unknown | null;
536
536
  }>;
537
- /**
538
- * Invoke another registered or file-backed play as a child workflow.
539
- *
540
- * Use this for real composition boundaries, especially when a fitting
541
- * scalar prebuilt play already encodes provider order, fallbacks,
542
- * normalization, and no-result behavior. Do not invoke plays through
543
- * `ctx.tools.execute`; tools and plays are separate namespaces.
544
- *
545
- * `key` is the stable child-call identity for idempotency and traceability.
546
- *
547
- * @param key - Child call id.
548
- * @param playRef - Play name or handle.
549
- * @param input - Child input.
550
- * @param options - Run options.
551
- * @returns Child play output.
552
- */
553
- runPlay(
537
+ runPlay<TOutput = unknown>(
554
538
  key: string,
555
539
  playRef: string | PlayReferenceLike,
556
540
  input: Record<string, unknown>,
557
541
  options: { description?: string; staleAfterSeconds?: number },
558
- ): Promise<Record<string, unknown>>;
542
+ ): Promise<TOutput>;
559
543
 
560
544
  /**
561
545
  * Emit a log line visible in `play tail` and the play's progress logs.
@@ -50,10 +50,10 @@ export type SdkRelease = {
50
50
  };
51
51
 
52
52
  export const SDK_RELEASE = {
53
- version: '0.1.56',
53
+ version: '0.1.58',
54
54
  apiContract: '2026-05-play-tool-describe-starters',
55
55
  supportPolicy: {
56
- latest: '0.1.56',
56
+ latest: '0.1.58',
57
57
  minimumSupported: '0.1.53',
58
58
  deprecatedBelow: '0.1.53',
59
59
  },