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.
- package/dist/cli/index.js +79 -59
- package/dist/cli/index.mjs +79 -59
- package/dist/index.d.mts +23 -25
- package/dist/index.d.ts +23 -25
- package/dist/index.js +44 -38
- package/dist/index.mjs +44 -38
- package/dist/repo/apps/play-runner-workers/src/entry.ts +40 -12
- package/dist/repo/apps/play-runner-workers/src/runtime/receipts.ts +138 -0
- package/dist/repo/sdk/src/client.ts +9 -11
- package/dist/repo/sdk/src/index.ts +1 -1
- package/dist/repo/sdk/src/play.ts +5 -3
- package/dist/repo/sdk/src/tool-output.ts +8 -12
- package/dist/repo/sdk/src/types.ts +3 -3
- package/dist/repo/sdk/src/version.ts +2 -2
- package/dist/repo/shared_libs/play-runtime/tool-result.ts +50 -34
- package/package.json +1 -1
|
@@ -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-
|
|
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
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
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 `
|
|
563
|
-
* `
|
|
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.
|
|
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.
|
|
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.
|
|
1100
|
-
const meta = response.
|
|
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
|
|
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.
|
|
117
|
-
roots.push({ path: '
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
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
|
-
|
|
112
|
-
raw?: string
|
|
113
|
-
meta?: string
|
|
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.
|
|
2
|
-
export const SDK_API_CONTRACT = "2026-05-v2-tool-
|
|
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
|
|
50
|
-
if (
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
?
|
|
57
|
-
|
|
58
|
-
|
|
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 '
|
|
82
|
+
if (!normalized) return 'toolResponse.raw';
|
|
83
83
|
if (
|
|
84
|
-
normalized === '
|
|
85
|
-
normalized.startsWith('
|
|
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
|
-
? `
|
|
96
|
-
: '
|
|
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 '
|
|
191
|
+
if (!normalized) return 'toolResponse.raw';
|
|
192
192
|
if (
|
|
193
|
-
normalized === '
|
|
194
|
-
normalized.startsWith('
|
|
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
|
-
? `
|
|
203
|
-
: '
|
|
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
|
-
|
|
532
|
-
|
|
533
|
-
|
|
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
|
-
|
|
553
|
-
|
|
565
|
+
value: toolResponse,
|
|
566
|
+
enumerable: false,
|
|
554
567
|
},
|
|
555
|
-
|
|
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.
|
|
586
|
-
...(value.
|
|
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
|
}
|