deepline 0.1.33 → 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.
@@ -103,17 +103,51 @@ export interface ToolDefinition {
103
103
  inputSchema?: Record<string, unknown>;
104
104
  /** JSON Schema describing the tool's output shape. */
105
105
  outputSchema?: Record<string, unknown>;
106
- /**
107
- * Dotted paths for extracting list data from the tool's response.
108
- *
109
- * Used by {@link tryConvertToList} to automatically find the array of results
110
- * in a nested response. Example: `["people", "result.data"]`.
111
- */
112
- listExtractorPaths?: string[];
113
- /** Field mappings for extracting identity fields (email, phone, etc.) from results. */
114
- resultIdentityGetters?: Record<string, string[]>;
115
- /** Whether the output is a direct object or wrapped in a `result` envelope. */
116
- rowContextShape?: 'direct' | 'result_envelope';
106
+ /** Copyable play-runtime guidance for V2 tool execution results. */
107
+ usageGuidance?: {
108
+ execute?: string;
109
+ toolExecutionResult?: {
110
+ type?: 'ToolExecutionResult';
111
+ toolResponse?: {
112
+ raw?: string;
113
+ meta?: string;
114
+ };
115
+ meta?: string;
116
+ extractedLists?: Array<{
117
+ name: string;
118
+ expression: string;
119
+ details?: {
120
+ strategy?: string;
121
+ rawToolOutputPaths?: string[];
122
+ candidatePaths?: string[];
123
+ };
124
+ }> | Record<string, {
125
+ expression: string;
126
+ details?: {
127
+ strategy?: string;
128
+ rawToolOutputPaths?: string[];
129
+ candidatePaths?: string[];
130
+ };
131
+ }>;
132
+ extractedValues?: Array<{
133
+ name: string;
134
+ expression: string;
135
+ details?: {
136
+ strategy?: string;
137
+ rawToolOutputPaths?: string[];
138
+ candidatePaths?: string[];
139
+ };
140
+ }> | Record<string, {
141
+ expression: string;
142
+ details?: {
143
+ strategy?: string;
144
+ rawToolOutputPaths?: string[];
145
+ candidatePaths?: string[];
146
+ };
147
+ }>;
148
+ [key: string]: unknown;
149
+ };
150
+ };
117
151
  /** Search relevance score returned by ranked tool search. */
118
152
  search_score?: number;
119
153
  /** Search match snippets returned by ranked tool search. */
@@ -1,2 +1,2 @@
1
- export const SDK_VERSION = "0.1.33";
2
- export const SDK_API_CONTRACT = "2026-05-host-env-generic-play-input-flags";
1
+ export const SDK_VERSION = "0.1.36";
2
+ export const SDK_API_CONTRACT = "2026-05-v2-tool-response";
@@ -0,0 +1,49 @@
1
+ export const CLOUDFLARE_DURABLE_OBJECT_CODE_UPDATED_ERROR =
2
+ 'Durable Object reset because its code was updated.';
3
+
4
+ export const PLATFORM_DEPLOY_INTERRUPTED_MESSAGE =
5
+ 'Run interrupted by a platform deploy and was not retried automatically. Re-run the same command; the input is unchanged.';
6
+
7
+ export type PlayRunFailureDetails = {
8
+ code: string;
9
+ phase: string;
10
+ message: string;
11
+ retryable: boolean | null;
12
+ cause?: string;
13
+ };
14
+
15
+ function toErrorText(error: unknown): string {
16
+ if (error instanceof Error) {
17
+ return error.message;
18
+ }
19
+ return String(error);
20
+ }
21
+
22
+ export function isCloudflareDurableObjectCodeUpdatedError(
23
+ error: unknown,
24
+ ): boolean {
25
+ return toErrorText(error).includes(
26
+ CLOUDFLARE_DURABLE_OBJECT_CODE_UPDATED_ERROR,
27
+ );
28
+ }
29
+
30
+ export function normalizePlayRunFailure(
31
+ error: unknown,
32
+ ): PlayRunFailureDetails {
33
+ const cause = toErrorText(error);
34
+ if (isCloudflareDurableObjectCodeUpdatedError(cause)) {
35
+ return {
36
+ code: 'PLATFORM_DEPLOY_INTERRUPTED',
37
+ phase: 'runtime',
38
+ message: PLATFORM_DEPLOY_INTERRUPTED_MESSAGE,
39
+ retryable: true,
40
+ cause: CLOUDFLARE_DURABLE_OBJECT_CODE_UPDATED_ERROR,
41
+ };
42
+ }
43
+ return {
44
+ code: 'RUN_FAILED',
45
+ phase: 'runtime',
46
+ message: cause,
47
+ retryable: null,
48
+ };
49
+ }
@@ -38,6 +38,64 @@ function isRecord(value: unknown): value is Record<string, unknown> {
38
38
  return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
39
39
  }
40
40
 
41
+ export type V2ToolExecuteOutput = {
42
+ raw: unknown;
43
+ meta?: Record<string, unknown>;
44
+ };
45
+
46
+ export function parseV2ToolExecuteOutput(
47
+ data: Record<string, unknown>,
48
+ ): V2ToolExecuteOutput | null {
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
+ }
61
+
62
+ export function adaptV2ExecuteResponseToToolResult(
63
+ data: Record<string, unknown>,
64
+ ): { output?: V2ToolExecuteOutput; result: unknown } {
65
+ const output = parseV2ToolExecuteOutput(data);
66
+ if (!output) {
67
+ return { result: data.result ?? data };
68
+ }
69
+ return {
70
+ output,
71
+ result: {
72
+ data: output.raw,
73
+ ...(output.meta ? { meta: output.meta } : {}),
74
+ },
75
+ };
76
+ }
77
+
78
+ export function toV2RawToolOutputPath(path: string): string {
79
+ const normalized = String(path || '')
80
+ .trim()
81
+ .replace(/^\./, '');
82
+ if (!normalized) return 'toolResponse.raw';
83
+ if (
84
+ normalized === 'toolResponse.raw' ||
85
+ normalized.startsWith('toolResponse.raw.')
86
+ ) {
87
+ return normalized;
88
+ }
89
+ const rawPath = normalized
90
+ .replace(/^result\.data\.?/, '')
91
+ .replace(/^result\.?/, '')
92
+ .replace(/^data\.?/, '')
93
+ .replace(/^\./, '');
94
+ return rawPath
95
+ ? `toolResponse.raw.${rawPath}`
96
+ : 'toolResponse.raw';
97
+ }
98
+
41
99
  function isMeaningfulValue(value: unknown): boolean {
42
100
  if (value == null) return false;
43
101
  if (typeof value === 'string') return value.trim().length > 0;
@@ -123,7 +181,37 @@ function normalizeResultPath(path: string): string {
123
181
  .trim()
124
182
  .replace(/^\./, '');
125
183
  if (!trimmed) return '';
126
- return trimmed.startsWith('result.') ? trimmed : `result.${trimmed}`;
184
+ return toV2RawToolOutputPath(trimmed);
185
+ }
186
+
187
+ function toV2RawToolOutputPathPreservingProviderData(path: string): string {
188
+ const normalized = String(path || '')
189
+ .trim()
190
+ .replace(/^\./, '');
191
+ if (!normalized) return 'toolResponse.raw';
192
+ if (
193
+ normalized === 'toolResponse.raw' ||
194
+ normalized.startsWith('toolResponse.raw.')
195
+ ) {
196
+ return normalized;
197
+ }
198
+ const rawPath = normalized
199
+ .replace(/^result\.?/, '')
200
+ .replace(/^\./, '');
201
+ return rawPath
202
+ ? `toolResponse.raw.${rawPath}`
203
+ : 'toolResponse.raw';
204
+ }
205
+
206
+ function candidateResultPaths(path: string): string[] {
207
+ const candidates = [
208
+ normalizeResultPath(path),
209
+ toV2RawToolOutputPathPreservingProviderData(path),
210
+ ];
211
+ return candidates.filter(
212
+ (candidate, index, all) =>
213
+ candidate.length > 0 && all.indexOf(candidate) === index,
214
+ );
127
215
  }
128
216
 
129
217
  function normalizeRelativePath(path: string): string {
@@ -184,10 +272,10 @@ function findFirstTargetByPath(
184
272
  paths: readonly string[] | undefined,
185
273
  ): ToolResultTargetMetadata | null {
186
274
  for (const path of paths ?? []) {
187
- const normalizedPath = normalizeResultPath(path);
188
- if (!normalizedPath) continue;
189
- const match = getFirstMeaningfulValueAtPath(result, normalizedPath);
190
- if (match) return match;
275
+ for (const candidate of candidateResultPaths(path)) {
276
+ const match = getFirstMeaningfulValueAtPath(result, candidate);
277
+ if (match) return match;
278
+ }
191
279
  }
192
280
  return null;
193
281
  }
@@ -244,8 +332,7 @@ function resolveListRows(
244
332
  const path = normalizeResultPath(rawPath);
245
333
  if (!path) continue;
246
334
  const candidates = [
247
- path,
248
- path.replace(/^result\./, 'result.data.'),
335
+ ...candidateResultPaths(rawPath),
249
336
  ].filter(
250
337
  (candidate, index, all) =>
251
338
  candidate && all.indexOf(candidate) === index,
@@ -303,29 +390,31 @@ function deriveListKeys(input: {
303
390
  .trim()
304
391
  .replace(/^\./, '');
305
392
  if (!path) continue;
306
- const resultPath = normalizeResultPath(path);
307
- const directPrefix = `${listPrefix}.`;
308
- if (resultPath.startsWith(directPrefix)) {
309
- keys[target] = resultPath
310
- .slice(directPrefix.length)
311
- .replace(/^\[\d+\]\.?/, '');
312
- break;
313
- }
314
- const indexedPrefix = `${listPrefix}[0].`;
315
- if (resultPath.startsWith(indexedPrefix)) {
316
- keys[target] = resultPath.slice(indexedPrefix.length);
317
- break;
318
- }
319
- const wildcardPrefix = `${listPrefix}[*].`;
320
- if (resultPath.startsWith(wildcardPrefix)) {
321
- keys[target] = resultPath.slice(wildcardPrefix.length);
322
- break;
323
- }
324
- const dottedIndexPrefix = `${listPrefix}.0.`;
325
- if (resultPath.startsWith(dottedIndexPrefix)) {
326
- keys[target] = resultPath.slice(dottedIndexPrefix.length);
327
- break;
393
+ for (const resultPath of candidateResultPaths(path)) {
394
+ const directPrefix = `${listPrefix}.`;
395
+ if (resultPath.startsWith(directPrefix)) {
396
+ keys[target] = resultPath
397
+ .slice(directPrefix.length)
398
+ .replace(/^\[\d+\]\.?/, '');
399
+ break;
400
+ }
401
+ const indexedPrefix = `${listPrefix}[0].`;
402
+ if (resultPath.startsWith(indexedPrefix)) {
403
+ keys[target] = resultPath.slice(indexedPrefix.length);
404
+ break;
405
+ }
406
+ const wildcardPrefix = `${listPrefix}[*].`;
407
+ if (resultPath.startsWith(wildcardPrefix)) {
408
+ keys[target] = resultPath.slice(wildcardPrefix.length);
409
+ break;
410
+ }
411
+ const dottedIndexPrefix = `${listPrefix}.0.`;
412
+ if (resultPath.startsWith(dottedIndexPrefix)) {
413
+ keys[target] = resultPath.slice(dottedIndexPrefix.length);
414
+ break;
415
+ }
328
416
  }
417
+ if (keys[target]) break;
329
418
  }
330
419
  }
331
420
  if (Object.keys(keys).length === 0 && input.rows[0]) {
@@ -433,12 +522,19 @@ function buildListAccessors(
433
522
 
434
523
  export function createToolExecuteResult<TResult = unknown>(input: {
435
524
  status: string;
525
+ jobId?: string;
436
526
  result: TResult;
437
527
  metadata: ToolResultMetadataInput;
438
528
  execution: ToolResultExecutionMetadata;
529
+ meta?: Record<string, unknown>;
439
530
  }): ToolExecuteResult<TResult> {
440
531
  const result = toResultEnvelope(input.result);
441
- const resultRoot = { result };
532
+ const resultRoot = {
533
+ toolResponse: {
534
+ raw: result.data,
535
+ ...(result.meta ? { meta: result.meta } : {}),
536
+ },
537
+ };
442
538
  const targets = buildTargets(
443
539
  resultRoot,
444
540
  input.metadata.resultIdentityGetters,
@@ -450,12 +546,26 @@ export function createToolExecuteResult<TResult = unknown>(input: {
450
546
  targets,
451
547
  lists,
452
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);
453
555
  const wrapper = {
454
556
  status: input.status,
455
- result,
456
- extracted: buildExtractedAccessors(targets),
457
- lists: buildListAccessors(resultRoot, lists),
557
+ ...(input.jobId ? { job_id: input.jobId } : {}),
558
+ ...(input.meta ? { meta: input.meta } : {}),
559
+ toolResponse,
560
+ extractedValues,
561
+ extractedLists,
458
562
  } as ToolExecuteResult<TResult>;
563
+ Object.defineProperties(wrapper, {
564
+ toolOutput: {
565
+ value: toolResponse,
566
+ enumerable: false,
567
+ },
568
+ });
459
569
  Object.defineProperty(wrapper, '_metadata', {
460
570
  value: metadata,
461
571
  enumerable: false,
@@ -471,7 +581,8 @@ export function isToolExecuteResult(
471
581
  typeof value.status === 'string' &&
472
582
  '_metadata' in value &&
473
583
  isRecord(value._metadata) &&
474
- 'result' in value
584
+ 'toolResponse' in value &&
585
+ 'toolOutput' in value
475
586
  );
476
587
  }
477
588
 
@@ -481,7 +592,14 @@ export function cloneToolExecuteResultWithExecution<TResult>(
481
592
  ): ToolExecuteResult<TResult> {
482
593
  return createToolExecuteResult<TResult>({
483
594
  status: value.status,
484
- result: value.result as TResult,
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,
599
+ result: {
600
+ data: value.toolResponse.raw,
601
+ ...(value.toolResponse.meta ? { meta: value.toolResponse.meta } : {}),
602
+ } as TResult,
485
603
  metadata: {
486
604
  toolId: value._metadata.toolId,
487
605
  resultIdentityGetters: Object.fromEntries(
@@ -500,5 +618,6 @@ export function cloneToolExecuteResultWithExecution<TResult>(
500
618
  ),
501
619
  },
502
620
  execution,
621
+ meta: isRecord(value.meta) ? value.meta : undefined,
503
622
  });
504
623
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deepline",
3
- "version": "0.1.33",
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": {