deepline 0.1.35 → 0.1.36

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.
@@ -0,0 +1,138 @@
1
+ export type RuntimeReceiptStatus =
2
+ | 'pending'
3
+ | 'running'
4
+ | 'completed'
5
+ | 'failed'
6
+ | 'skipped';
7
+
8
+ export type WorkerRuntimeReceipt = {
9
+ key: string;
10
+ status: RuntimeReceiptStatus;
11
+ output?: unknown;
12
+ error?: string;
13
+ runId?: string | null;
14
+ };
15
+
16
+ export type WorkerRuntimeReceiptResponse = {
17
+ receipt?: WorkerRuntimeReceipt | null;
18
+ };
19
+
20
+ export type WorkerRuntimeReceiptAction =
21
+ | {
22
+ action: 'get_runtime_step_receipt';
23
+ playName: string;
24
+ runId: string;
25
+ key: string;
26
+ }
27
+ | {
28
+ action: 'claim_runtime_step_receipt';
29
+ playName: string;
30
+ runId: string;
31
+ key: string;
32
+ }
33
+ | {
34
+ action: 'complete_runtime_step_receipt';
35
+ playName: string;
36
+ runId: string;
37
+ key: string;
38
+ output: unknown;
39
+ }
40
+ | {
41
+ action: 'fail_runtime_step_receipt';
42
+ playName: string;
43
+ runId: string;
44
+ key: string;
45
+ error: string;
46
+ };
47
+
48
+ type RuntimeReceiptContext = {
49
+ baseUrl: string;
50
+ executorToken: string;
51
+ playName: string;
52
+ runId: string;
53
+ key: string;
54
+ postRuntimeApi: (
55
+ baseUrl: string,
56
+ executorToken: string,
57
+ body: WorkerRuntimeReceiptAction,
58
+ ) => Promise<WorkerRuntimeReceiptResponse>;
59
+ };
60
+
61
+ function scopedReceiptKey(input: {
62
+ playName: string;
63
+ runId: string;
64
+ key: string;
65
+ }): string {
66
+ return `run:${input.runId}:play:${input.playName}:${input.key}`;
67
+ }
68
+
69
+ function receiptOutput<T>(receipt: WorkerRuntimeReceipt): T {
70
+ return receipt.output as T;
71
+ }
72
+
73
+ function errorMessage(error: unknown): string {
74
+ return error instanceof Error ? error.message : String(error);
75
+ }
76
+
77
+ export async function runWorkerRuntimeReceiptBoundary<T>(
78
+ input: RuntimeReceiptContext & {
79
+ execute: () => Promise<T> | T;
80
+ },
81
+ ): Promise<T> {
82
+ const key = scopedReceiptKey(input);
83
+ const existing = await input.postRuntimeApi(input.baseUrl, input.executorToken, {
84
+ action: 'get_runtime_step_receipt',
85
+ playName: input.playName,
86
+ runId: input.runId,
87
+ key,
88
+ });
89
+ if (
90
+ existing.receipt?.status === 'completed' ||
91
+ existing.receipt?.status === 'skipped'
92
+ ) {
93
+ return receiptOutput<T>(existing.receipt);
94
+ }
95
+
96
+ const claimed = await input.postRuntimeApi(input.baseUrl, input.executorToken, {
97
+ action: 'claim_runtime_step_receipt',
98
+ playName: input.playName,
99
+ runId: input.runId,
100
+ key,
101
+ });
102
+ if (!claimed.receipt) {
103
+ if (
104
+ existing.receipt?.status === 'running' &&
105
+ existing.receipt.runId !== input.runId
106
+ ) {
107
+ throw new Error(
108
+ `Runtime receipt ${key} is already running for run ${existing.receipt.runId ?? 'unknown'}.`,
109
+ );
110
+ }
111
+ if (existing.receipt?.status === 'failed') {
112
+ throw new Error(
113
+ `Runtime receipt ${key} is failed and could not be claimed: ${existing.receipt.error ?? 'unknown error'}`,
114
+ );
115
+ }
116
+ }
117
+
118
+ try {
119
+ const output = await input.execute();
120
+ await input.postRuntimeApi(input.baseUrl, input.executorToken, {
121
+ action: 'complete_runtime_step_receipt',
122
+ playName: input.playName,
123
+ runId: input.runId,
124
+ key,
125
+ output,
126
+ });
127
+ return output;
128
+ } catch (error) {
129
+ await input.postRuntimeApi(input.baseUrl, input.executorToken, {
130
+ action: 'fail_runtime_step_receipt',
131
+ playName: input.playName,
132
+ runId: input.runId,
133
+ key,
134
+ error: errorMessage(error),
135
+ });
136
+ throw error;
137
+ }
138
+ }
@@ -68,7 +68,7 @@ import type { PlayCompilerManifest } from '../../shared_libs/plays/compiler-mani
68
68
  const TERMINAL_PLAY_STATUSES = new Set(['completed', 'failed', 'cancelled']);
69
69
  const INCLUDE_TOOL_METADATA_HEADER = 'x-deepline-include-tool-metadata';
70
70
  const EXECUTE_RESPONSE_CONTRACT_HEADER = 'x-deepline-execute-response-contract';
71
- const V2_EXECUTE_RESPONSE_CONTRACT = 'v2-tool-execution-result';
71
+ const V2_EXECUTE_RESPONSE_CONTRACT = 'v2-tool-response';
72
72
  const COMPILE_MANIFEST_RETRY_DELAYS_MS = [250, 1_000];
73
73
 
74
74
  function sleep(ms: number): Promise<void> {
@@ -97,15 +97,13 @@ type ExecuteToolRawOptions = {
97
97
  export type ToolExecution<TData = unknown, TMeta = Record<string, unknown>> = {
98
98
  status: string;
99
99
  job_id?: string;
100
- toolExecutionResult: {
101
- toolOutput: {
102
- raw: TData;
103
- meta?: TMeta;
104
- };
105
- extractedLists?: Record<string, unknown>;
106
- extractedValues?: Record<string, unknown>;
107
- meta?: Record<string, unknown>;
100
+ meta?: Record<string, unknown>;
101
+ toolResponse: {
102
+ raw: TData;
103
+ meta?: TMeta;
108
104
  };
105
+ extractedLists?: Record<string, unknown>;
106
+ extractedValues?: Record<string, unknown>;
109
107
  billing?: Record<string, unknown>;
110
108
  [key: string]: unknown;
111
109
  };
@@ -559,8 +557,8 @@ export class DeeplineClient {
559
557
  /**
560
558
  * Execute a tool and return the standard execution envelope.
561
559
  *
562
- * The `toolExecutionResult.toolOutput.raw` field contains the raw tool output.
563
- * `toolExecutionResult.toolOutput.meta` contains tool/provider metadata.
560
+ * The `toolResponse.raw` field contains the raw tool response.
561
+ * `toolResponse.meta` contains tool/provider metadata.
564
562
  * Top-level fields such as `status`, `job_id`, and `billing` describe the
565
563
  * Deepline execution envelope.
566
564
  */
@@ -11,7 +11,7 @@
11
11
  *
12
12
  * // Execute a tool
13
13
  * const result = await deepline.tools.execute('test_company_search', { domain: 'stripe.com' });
14
- * const company = result.toolOutput.raw;
14
+ * const company = result.toolResponse.raw;
15
15
  *
16
16
  * // Run a named play
17
17
  * const job = await deepline.play('email-waterfall').run({ domain: 'stripe.com' });
@@ -926,7 +926,7 @@ export class DeeplineContext {
926
926
  * const tools = await deepline.tools.list();
927
927
  * const meta = await deepline.tools.get('apollo_people_search');
928
928
  * const companyLookup = await deepline.tools.execute('test_company_search', { domain: 'stripe.com' });
929
- * const company = companyLookup.toolOutput.raw;
929
+ * const company = companyLookup.toolResponse.raw;
930
930
  * ```
931
931
  */
932
932
  get tools() {
@@ -1096,8 +1096,8 @@ function toolExecutionEnvelopeToResult(
1096
1096
  fallbackToolId: string,
1097
1097
  response: ToolExecution,
1098
1098
  ): ToolExecuteResult {
1099
- const raw = response.toolExecutionResult?.toolOutput?.raw ?? null;
1100
- const meta = response.toolExecutionResult?.toolOutput?.meta;
1099
+ const raw = response.toolResponse?.raw ?? null;
1100
+ const meta = response.toolResponse?.meta;
1101
1101
  const metadata = isRecord(response._metadata)
1102
1102
  ? response._metadata.tool
1103
1103
  : null;
@@ -1105,6 +1105,7 @@ function toolExecutionEnvelopeToResult(
1105
1105
 
1106
1106
  return createToolExecuteResult({
1107
1107
  status: typeof response.status === 'string' ? response.status : 'completed',
1108
+ jobId: typeof response.job_id === 'string' ? response.job_id : undefined,
1108
1109
  result: {
1109
1110
  data: raw,
1110
1111
  ...(isRecord(meta) ? { meta } : {}),
@@ -1125,6 +1126,7 @@ function toolExecutionEnvelopeToResult(
1125
1126
  cached: false,
1126
1127
  source: 'live',
1127
1128
  },
1129
+ meta: isRecord(response.meta) ? response.meta : undefined,
1128
1130
  });
1129
1131
  }
1130
1132
 
@@ -109,21 +109,17 @@ function normalizeRows(value: unknown): Array<Record<string, unknown>> | null {
109
109
 
110
110
  /**
111
111
  * Generate candidate root objects to search for lists.
112
- * Tries: raw payload → V2 toolExecutionResult.toolOutput.raw → legacy payload.output.body → legacy payload.result → legacy payload.result.data.
112
+ * Tries: raw payload → V2 toolResponse.raw → legacy payload.output.body → legacy payload.result → legacy payload.result.data.
113
113
  */
114
114
  function candidateRoots(payload: unknown): Array<{ path: string | null; value: unknown }> {
115
115
  const roots: Array<{ path: string | null; value: unknown }> = [{ path: null, value: payload }];
116
- if (isPlainObject(payload) && isPlainObject(payload.toolExecutionResult)) {
117
- roots.push({ path: 'toolExecutionResult', value: payload.toolExecutionResult });
118
- const toolOutput = payload.toolExecutionResult.toolOutput;
119
- if (isPlainObject(toolOutput)) {
120
- roots.push({ path: 'toolExecutionResult.toolOutput', value: toolOutput });
121
- if (Object.prototype.hasOwnProperty.call(toolOutput, 'raw')) {
122
- roots.push({
123
- path: 'toolExecutionResult.toolOutput.raw',
124
- value: toolOutput.raw,
125
- });
126
- }
116
+ if (isPlainObject(payload) && isPlainObject(payload.toolResponse)) {
117
+ roots.push({ path: 'toolResponse', value: payload.toolResponse });
118
+ if (Object.prototype.hasOwnProperty.call(payload.toolResponse, 'raw')) {
119
+ roots.push({
120
+ path: 'toolResponse.raw',
121
+ value: payload.toolResponse.raw,
122
+ });
127
123
  }
128
124
  }
129
125
  if (isPlainObject(payload) && isPlainObject(payload.output)) {
@@ -108,9 +108,9 @@ export interface ToolDefinition {
108
108
  execute?: string;
109
109
  toolExecutionResult?: {
110
110
  type?: 'ToolExecutionResult';
111
- toolOutput?: {
112
- raw?: string | { path?: string; schema?: Record<string, unknown> };
113
- meta?: string | { path?: string; schema?: Record<string, unknown> };
111
+ toolResponse?: {
112
+ raw?: string;
113
+ meta?: string;
114
114
  };
115
115
  meta?: string;
116
116
  extractedLists?: Array<{
@@ -1,2 +1,2 @@
1
- export const SDK_VERSION = "0.1.35";
2
- export const SDK_API_CONTRACT = "2026-05-v2-tool-result-contract";
1
+ export const SDK_VERSION = "0.1.36";
2
+ export const SDK_API_CONTRACT = "2026-05-v2-tool-response";
@@ -46,17 +46,17 @@ export type V2ToolExecuteOutput = {
46
46
  export function parseV2ToolExecuteOutput(
47
47
  data: Record<string, unknown>,
48
48
  ): V2ToolExecuteOutput | null {
49
- const toolExecutionResult = data.toolExecutionResult;
50
- if (!isRecord(toolExecutionResult)) return null;
51
- const toolOutput = toolExecutionResult.toolOutput;
52
- if (!isRecord(toolOutput)) return null;
53
- const meta = isRecord(toolOutput.meta) ? toolOutput.meta : undefined;
54
- return {
55
- raw: Object.prototype.hasOwnProperty.call(toolOutput, 'raw')
56
- ? toolOutput.raw
57
- : null,
58
- ...(meta ? { meta } : {}),
59
- };
49
+ const toolResponse = data.toolResponse;
50
+ if (isRecord(toolResponse)) {
51
+ const meta = isRecord(toolResponse.meta) ? toolResponse.meta : undefined;
52
+ return {
53
+ raw: Object.prototype.hasOwnProperty.call(toolResponse, 'raw')
54
+ ? toolResponse.raw
55
+ : null,
56
+ ...(meta ? { meta } : {}),
57
+ };
58
+ }
59
+ return null;
60
60
  }
61
61
 
62
62
  export function adaptV2ExecuteResponseToToolResult(
@@ -79,10 +79,10 @@ export function toV2RawToolOutputPath(path: string): string {
79
79
  const normalized = String(path || '')
80
80
  .trim()
81
81
  .replace(/^\./, '');
82
- if (!normalized) return 'toolExecutionResult.toolOutput.raw';
82
+ if (!normalized) return 'toolResponse.raw';
83
83
  if (
84
- normalized === 'toolExecutionResult.toolOutput.raw' ||
85
- normalized.startsWith('toolExecutionResult.toolOutput.raw.')
84
+ normalized === 'toolResponse.raw' ||
85
+ normalized.startsWith('toolResponse.raw.')
86
86
  ) {
87
87
  return normalized;
88
88
  }
@@ -92,8 +92,8 @@ export function toV2RawToolOutputPath(path: string): string {
92
92
  .replace(/^data\.?/, '')
93
93
  .replace(/^\./, '');
94
94
  return rawPath
95
- ? `toolExecutionResult.toolOutput.raw.${rawPath}`
96
- : 'toolExecutionResult.toolOutput.raw';
95
+ ? `toolResponse.raw.${rawPath}`
96
+ : 'toolResponse.raw';
97
97
  }
98
98
 
99
99
  function isMeaningfulValue(value: unknown): boolean {
@@ -188,10 +188,10 @@ function toV2RawToolOutputPathPreservingProviderData(path: string): string {
188
188
  const normalized = String(path || '')
189
189
  .trim()
190
190
  .replace(/^\./, '');
191
- if (!normalized) return 'toolExecutionResult.toolOutput.raw';
191
+ if (!normalized) return 'toolResponse.raw';
192
192
  if (
193
- normalized === 'toolExecutionResult.toolOutput.raw' ||
194
- normalized.startsWith('toolExecutionResult.toolOutput.raw.')
193
+ normalized === 'toolResponse.raw' ||
194
+ normalized.startsWith('toolResponse.raw.')
195
195
  ) {
196
196
  return normalized;
197
197
  }
@@ -199,8 +199,8 @@ function toV2RawToolOutputPathPreservingProviderData(path: string): string {
199
199
  .replace(/^result\.?/, '')
200
200
  .replace(/^\./, '');
201
201
  return rawPath
202
- ? `toolExecutionResult.toolOutput.raw.${rawPath}`
203
- : 'toolExecutionResult.toolOutput.raw';
202
+ ? `toolResponse.raw.${rawPath}`
203
+ : 'toolResponse.raw';
204
204
  }
205
205
 
206
206
  function candidateResultPaths(path: string): string[] {
@@ -522,17 +522,17 @@ function buildListAccessors(
522
522
 
523
523
  export function createToolExecuteResult<TResult = unknown>(input: {
524
524
  status: string;
525
+ jobId?: string;
525
526
  result: TResult;
526
527
  metadata: ToolResultMetadataInput;
527
528
  execution: ToolResultExecutionMetadata;
529
+ meta?: Record<string, unknown>;
528
530
  }): ToolExecuteResult<TResult> {
529
531
  const result = toResultEnvelope(input.result);
530
532
  const resultRoot = {
531
- toolExecutionResult: {
532
- toolOutput: {
533
- raw: result.data,
534
- ...(result.meta ? { meta: result.meta } : {}),
535
- },
533
+ toolResponse: {
534
+ raw: result.data,
535
+ ...(result.meta ? { meta: result.meta } : {}),
536
536
  },
537
537
  };
538
538
  const targets = buildTargets(
@@ -546,16 +546,26 @@ export function createToolExecuteResult<TResult = unknown>(input: {
546
546
  targets,
547
547
  lists,
548
548
  };
549
+ const toolResponse = {
550
+ raw: result.data,
551
+ ...(result.meta ? { meta: result.meta } : {}),
552
+ };
553
+ const extractedValues = buildExtractedAccessors(targets);
554
+ const extractedLists = buildListAccessors(resultRoot, lists);
549
555
  const wrapper = {
550
556
  status: input.status,
557
+ ...(input.jobId ? { job_id: input.jobId } : {}),
558
+ ...(input.meta ? { meta: input.meta } : {}),
559
+ toolResponse,
560
+ extractedValues,
561
+ extractedLists,
562
+ } as ToolExecuteResult<TResult>;
563
+ Object.defineProperties(wrapper, {
551
564
  toolOutput: {
552
- raw: result.data,
553
- ...(result.meta ? { meta: result.meta } : {}),
565
+ value: toolResponse,
566
+ enumerable: false,
554
567
  },
555
- meta: input.execution,
556
- extractedValues: buildExtractedAccessors(targets),
557
- extractedLists: buildListAccessors(resultRoot, lists),
558
- } as ToolExecuteResult<TResult>;
568
+ });
559
569
  Object.defineProperty(wrapper, '_metadata', {
560
570
  value: metadata,
561
571
  enumerable: false,
@@ -571,6 +581,7 @@ export function isToolExecuteResult(
571
581
  typeof value.status === 'string' &&
572
582
  '_metadata' in value &&
573
583
  isRecord(value._metadata) &&
584
+ 'toolResponse' in value &&
574
585
  'toolOutput' in value
575
586
  );
576
587
  }
@@ -581,9 +592,13 @@ export function cloneToolExecuteResultWithExecution<TResult>(
581
592
  ): ToolExecuteResult<TResult> {
582
593
  return createToolExecuteResult<TResult>({
583
594
  status: value.status,
595
+ jobId:
596
+ typeof (value as unknown as { job_id?: unknown }).job_id === 'string'
597
+ ? (value as unknown as { job_id: string }).job_id
598
+ : undefined,
584
599
  result: {
585
- data: value.toolOutput.raw,
586
- ...(value.toolOutput.meta ? { meta: value.toolOutput.meta } : {}),
600
+ data: value.toolResponse.raw,
601
+ ...(value.toolResponse.meta ? { meta: value.toolResponse.meta } : {}),
587
602
  } as TResult,
588
603
  metadata: {
589
604
  toolId: value._metadata.toolId,
@@ -603,5 +618,6 @@ export function cloneToolExecuteResultWithExecution<TResult>(
603
618
  ),
604
619
  },
605
620
  execution,
621
+ meta: isRecord(value.meta) ? value.meta : undefined,
606
622
  });
607
623
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deepline",
3
- "version": "0.1.35",
3
+ "version": "0.1.36",
4
4
  "description": "Deepline SDK + CLI — B2B data enrichment powered by durable cloud execution",
5
5
  "license": "MIT",
6
6
  "repository": {