deepline 0.1.10 → 0.1.12
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/README.md +4 -4
- package/dist/cli/index.js +509 -353
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/index.mjs +513 -358
- package/dist/cli/index.mjs.map +1 -1
- package/dist/index.d.mts +250 -305
- package/dist/index.d.ts +250 -305
- package/dist/index.js +174 -286
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +174 -285
- package/dist/index.mjs.map +1 -1
- package/dist/repo/apps/play-runner-workers/src/coordinator-entry.ts +23 -13
- package/dist/repo/apps/play-runner-workers/src/entry.ts +581 -1220
- package/dist/repo/sdk/src/cli/commands/play.ts +381 -247
- package/dist/repo/sdk/src/cli/commands/tools.ts +1 -1
- package/dist/repo/sdk/src/cli/dataset-stats.ts +86 -12
- package/dist/repo/sdk/src/client.ts +54 -51
- package/dist/repo/sdk/src/index.ts +7 -16
- package/dist/repo/sdk/src/play.ts +122 -135
- package/dist/repo/sdk/src/plays/bundle-play-file.ts +6 -3
- package/dist/repo/sdk/src/tool-output.ts +0 -111
- package/dist/repo/sdk/src/types.ts +2 -0
- package/dist/repo/sdk/src/version.ts +1 -1
- package/dist/repo/sdk/src/worker-play-entry.ts +3 -0
- package/dist/repo/shared_libs/play-runtime/context.ts +510 -267
- package/dist/repo/shared_libs/play-runtime/csv-rename.ts +180 -0
- package/dist/repo/shared_libs/play-runtime/ctx-types.ts +13 -1
- package/dist/repo/shared_libs/play-runtime/tool-result.ts +139 -114
- package/dist/repo/shared_libs/plays/bundling/index.ts +68 -5
- package/dist/repo/shared_libs/plays/compiler-manifest.ts +1 -1
- package/dist/repo/shared_libs/plays/dataset.ts +1 -1
- package/dist/repo/shared_libs/plays/runtime-validation.ts +8 -28
- package/package.json +1 -1
- package/dist/repo/apps/play-runner-workers/src/runtime/tool-result.ts +0 -184
|
@@ -628,7 +628,7 @@ async function executeTool(args: string[]): Promise<number> {
|
|
|
628
628
|
}
|
|
629
629
|
throw error;
|
|
630
630
|
}
|
|
631
|
-
const rawResponse = await client.
|
|
631
|
+
const rawResponse = await client.executeTool(parsed.toolId, parsed.params);
|
|
632
632
|
|
|
633
633
|
const listConversion = tryConvertToList(rawResponse, {
|
|
634
634
|
listExtractorPaths: metadata.listExtractorPaths ?? [],
|
|
@@ -35,6 +35,66 @@ export type CanonicalRowsInfo = {
|
|
|
35
35
|
source: string | null;
|
|
36
36
|
};
|
|
37
37
|
|
|
38
|
+
const CSV_PROJECTED_FIELDS_KEY = '__deeplineCsvProjectedFields';
|
|
39
|
+
|
|
40
|
+
function csvProjectedFields(row: Record<string, unknown>): Set<string> {
|
|
41
|
+
const serialized = row[CSV_PROJECTED_FIELDS_KEY];
|
|
42
|
+
if (!Array.isArray(serialized)) {
|
|
43
|
+
return new Set();
|
|
44
|
+
}
|
|
45
|
+
return new Set(
|
|
46
|
+
serialized.filter((field): field is string => typeof field === 'string'),
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function stripCsvProjectionFields(
|
|
51
|
+
row: Record<string, unknown>,
|
|
52
|
+
): Record<string, unknown> {
|
|
53
|
+
const projectedFields = csvProjectedFields(row);
|
|
54
|
+
if (projectedFields.size === 0 && !(CSV_PROJECTED_FIELDS_KEY in row)) {
|
|
55
|
+
return row;
|
|
56
|
+
}
|
|
57
|
+
const stripped = { ...row };
|
|
58
|
+
for (const field of projectedFields) {
|
|
59
|
+
delete stripped[field];
|
|
60
|
+
}
|
|
61
|
+
delete stripped[CSV_PROJECTED_FIELDS_KEY];
|
|
62
|
+
return stripped;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function stripCsvProjectionColumns(
|
|
66
|
+
columns: string[],
|
|
67
|
+
rows: Array<Record<string, unknown>>,
|
|
68
|
+
): string[] {
|
|
69
|
+
const projectedFields = new Set<string>();
|
|
70
|
+
let hasProjectionMetadata = false;
|
|
71
|
+
for (const row of rows) {
|
|
72
|
+
for (const field of csvProjectedFields(row)) {
|
|
73
|
+
projectedFields.add(field);
|
|
74
|
+
}
|
|
75
|
+
hasProjectionMetadata ||= CSV_PROJECTED_FIELDS_KEY in row;
|
|
76
|
+
}
|
|
77
|
+
if (!hasProjectionMetadata && projectedFields.size === 0) {
|
|
78
|
+
return columns;
|
|
79
|
+
}
|
|
80
|
+
return columns.filter(
|
|
81
|
+
(column) =>
|
|
82
|
+
column !== CSV_PROJECTED_FIELDS_KEY && !projectedFields.has(column),
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function sanitizeCsvProjectionInfo(input: {
|
|
87
|
+
rows: Array<Record<string, unknown>>;
|
|
88
|
+
columns: string[];
|
|
89
|
+
}): {
|
|
90
|
+
rows: Array<Record<string, unknown>>;
|
|
91
|
+
columns: string[];
|
|
92
|
+
} {
|
|
93
|
+
const columns = stripCsvProjectionColumns(input.columns, input.rows);
|
|
94
|
+
const rows = input.rows.map(stripCsvProjectionFields);
|
|
95
|
+
return { rows, columns };
|
|
96
|
+
}
|
|
97
|
+
|
|
38
98
|
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
39
99
|
return Boolean(value && typeof value === 'object' && !Array.isArray(value));
|
|
40
100
|
}
|
|
@@ -118,16 +178,21 @@ export function extractCanonicalRowsInfo(statusOrResult: unknown): CanonicalRows
|
|
|
118
178
|
|
|
119
179
|
for (const candidate of candidates) {
|
|
120
180
|
if (isSerializedDataset(candidate.value)) {
|
|
121
|
-
const
|
|
122
|
-
const totalRows = readNumber(candidate.value.count) ??
|
|
181
|
+
const rawRows = rowArray(candidate.value.preview) ?? [];
|
|
182
|
+
const totalRows = readNumber(candidate.value.count) ?? rawRows.length;
|
|
183
|
+
const rawColumns =
|
|
184
|
+
Array.isArray(candidate.value.columns) &&
|
|
185
|
+
candidate.value.columns.every((column) => typeof column === 'string')
|
|
186
|
+
? (candidate.value.columns as string[])
|
|
187
|
+
: inferColumns(rawRows);
|
|
188
|
+
const { rows, columns } = sanitizeCsvProjectionInfo({
|
|
189
|
+
rows: rawRows,
|
|
190
|
+
columns: rawColumns,
|
|
191
|
+
});
|
|
123
192
|
return {
|
|
124
193
|
rows,
|
|
125
194
|
totalRows,
|
|
126
|
-
columns
|
|
127
|
-
Array.isArray(candidate.value.columns) &&
|
|
128
|
-
candidate.value.columns.every((column) => typeof column === 'string')
|
|
129
|
-
? (candidate.value.columns as string[])
|
|
130
|
-
: inferColumns(rows),
|
|
195
|
+
columns,
|
|
131
196
|
complete: rows.length === totalRows,
|
|
132
197
|
source: candidate.source,
|
|
133
198
|
};
|
|
@@ -138,10 +203,14 @@ export function extractCanonicalRowsInfo(statusOrResult: unknown): CanonicalRows
|
|
|
138
203
|
continue;
|
|
139
204
|
}
|
|
140
205
|
const totalRows = readNumber(candidate.total) ?? rows.length;
|
|
141
|
-
|
|
206
|
+
const sanitized = sanitizeCsvProjectionInfo({
|
|
142
207
|
rows,
|
|
143
|
-
totalRows,
|
|
144
208
|
columns: inferColumns(rows),
|
|
209
|
+
});
|
|
210
|
+
return {
|
|
211
|
+
rows: sanitized.rows,
|
|
212
|
+
totalRows,
|
|
213
|
+
columns: sanitized.columns,
|
|
145
214
|
complete: rows.length === totalRows,
|
|
146
215
|
source: candidate.source,
|
|
147
216
|
};
|
|
@@ -261,15 +330,16 @@ export function buildDatasetStats(
|
|
|
261
330
|
totalRows = rows.length,
|
|
262
331
|
columns = inferColumns(rows),
|
|
263
332
|
): DatasetStats {
|
|
333
|
+
const sanitized = sanitizeCsvProjectionInfo({ rows, columns });
|
|
264
334
|
const columnStats: DatasetStats['columnStats'] = {};
|
|
265
|
-
for (const column of columns) {
|
|
335
|
+
for (const column of sanitized.columns) {
|
|
266
336
|
let nonEmpty = 0;
|
|
267
337
|
let empty = 0;
|
|
268
338
|
let sampleValue: unknown;
|
|
269
339
|
let sampleValueType: string | null = null;
|
|
270
340
|
const valueCounts = new Map<string, number>();
|
|
271
341
|
|
|
272
|
-
for (const row of rows) {
|
|
342
|
+
for (const row of sanitized.rows) {
|
|
273
343
|
const raw = row[column];
|
|
274
344
|
const value = compactCell(raw);
|
|
275
345
|
if (value) {
|
|
@@ -331,10 +401,14 @@ export function writeCanonicalRowsCsv(
|
|
|
331
401
|
`Run output only includes ${rowsInfo.rows.length} preview row(s) of ${rowsInfo.totalRows}; cannot export a complete CSV from this status payload yet.`,
|
|
332
402
|
);
|
|
333
403
|
}
|
|
404
|
+
const sanitized = sanitizeCsvProjectionInfo({
|
|
405
|
+
rows: rowsInfo.rows,
|
|
406
|
+
columns: rowsInfo.columns,
|
|
407
|
+
});
|
|
334
408
|
const resolved = resolve(outPath);
|
|
335
409
|
writeFileSync(
|
|
336
410
|
resolved,
|
|
337
|
-
csvStringFromRows(
|
|
411
|
+
csvStringFromRows(sanitized.rows, sanitized.columns),
|
|
338
412
|
'utf-8',
|
|
339
413
|
);
|
|
340
414
|
return resolved;
|
|
@@ -64,6 +64,21 @@ import type { PlayCompilerManifest } from '../../shared_libs/plays/compiler-mani
|
|
|
64
64
|
|
|
65
65
|
const TERMINAL_PLAY_STATUSES = new Set(['completed', 'failed', 'cancelled']);
|
|
66
66
|
|
|
67
|
+
export type ToolExecution<TData = unknown, TMeta = Record<string, unknown>> = {
|
|
68
|
+
status: string;
|
|
69
|
+
job_id?: string;
|
|
70
|
+
result: {
|
|
71
|
+
data: TData;
|
|
72
|
+
meta?: TMeta;
|
|
73
|
+
};
|
|
74
|
+
billing?: Record<string, unknown>;
|
|
75
|
+
[key: string]: unknown;
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
79
|
+
return Boolean(value && typeof value === 'object' && !Array.isArray(value));
|
|
80
|
+
}
|
|
81
|
+
|
|
67
82
|
function normalizePlayStatus(raw: Record<string, unknown>): PlayStatus {
|
|
68
83
|
const status =
|
|
69
84
|
typeof raw.status === 'string'
|
|
@@ -159,8 +174,29 @@ export class DeeplineClient {
|
|
|
159
174
|
return fields.length > 0 ? { fields } : schema;
|
|
160
175
|
}
|
|
161
176
|
|
|
162
|
-
private
|
|
163
|
-
|
|
177
|
+
private schemaMetadata(
|
|
178
|
+
schema: Record<string, unknown> | null | undefined,
|
|
179
|
+
key: string,
|
|
180
|
+
): Record<string, unknown> | null {
|
|
181
|
+
if (!isRecord(schema)) return null;
|
|
182
|
+
const value = schema[key];
|
|
183
|
+
return isRecord(value) ? value : null;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
private playRunCommand(
|
|
187
|
+
play: Pick<PlayListItem, 'name' | 'reference'>,
|
|
188
|
+
options?: { csvInput?: Record<string, unknown> | null },
|
|
189
|
+
): string {
|
|
190
|
+
const target = play.reference || play.name;
|
|
191
|
+
if (options?.csvInput) {
|
|
192
|
+
const inputField =
|
|
193
|
+
typeof options.csvInput.inputField === 'string' &&
|
|
194
|
+
options.csvInput.inputField.trim()
|
|
195
|
+
? options.csvInput.inputField.trim()
|
|
196
|
+
: 'csv';
|
|
197
|
+
return `deepline plays run ${target} --${inputField} leads.csv --watch`;
|
|
198
|
+
}
|
|
199
|
+
return `deepline plays run ${target} --input '{...}' --watch`;
|
|
164
200
|
}
|
|
165
201
|
|
|
166
202
|
private summarizePlayListItem(
|
|
@@ -168,7 +204,12 @@ export class DeeplineClient {
|
|
|
168
204
|
options?: { compact?: boolean },
|
|
169
205
|
): PlayDescription {
|
|
170
206
|
const aliases = play.aliases?.length ? play.aliases : [play.name];
|
|
171
|
-
const
|
|
207
|
+
const csvInput = this.schemaMetadata(play.inputSchema, 'csvInput');
|
|
208
|
+
const rowOutputSchema = this.schemaMetadata(
|
|
209
|
+
play.outputSchema,
|
|
210
|
+
'rowOutputSchema',
|
|
211
|
+
);
|
|
212
|
+
const runCommand = this.playRunCommand(play, { csvInput });
|
|
172
213
|
return {
|
|
173
214
|
name: play.name,
|
|
174
215
|
...(play.reference ? { reference: play.reference } : {}),
|
|
@@ -184,6 +225,8 @@ export class DeeplineClient {
|
|
|
184
225
|
outputSchema: options?.compact
|
|
185
226
|
? this.compactSchema(play.outputSchema)
|
|
186
227
|
: (play.outputSchema ?? null),
|
|
228
|
+
...(csvInput ? { csvInput } : {}),
|
|
229
|
+
...(rowOutputSchema ? { rowOutputSchema } : {}),
|
|
187
230
|
runCommand,
|
|
188
231
|
examples: [runCommand],
|
|
189
232
|
currentPublishedVersion: play.currentPublishedVersion ?? null,
|
|
@@ -259,58 +302,18 @@ export class DeeplineClient {
|
|
|
259
302
|
}
|
|
260
303
|
|
|
261
304
|
/**
|
|
262
|
-
* Execute a tool and return the
|
|
305
|
+
* Execute a tool and return the standard execution envelope.
|
|
263
306
|
*
|
|
264
|
-
*
|
|
265
|
-
*
|
|
266
|
-
*
|
|
267
|
-
*
|
|
268
|
-
* @param toolId - Tool identifier (e.g. `"test_company_search"`)
|
|
269
|
-
* @param input - Tool-specific input parameters
|
|
270
|
-
* @returns The tool's output (shape varies by tool)
|
|
271
|
-
* @throws {@link DeeplineError} if the tool execution fails
|
|
272
|
-
*
|
|
273
|
-
* @example
|
|
274
|
-
* ```typescript
|
|
275
|
-
* const company = await client.executeTool('test_company_search', {
|
|
276
|
-
* domain: 'stripe.com',
|
|
277
|
-
* });
|
|
278
|
-
* console.log(company); // { name: "Stripe", industry: "Financial Services", ... }
|
|
279
|
-
* ```
|
|
280
|
-
*/
|
|
281
|
-
async executeTool(
|
|
282
|
-
toolId: string,
|
|
283
|
-
input: Record<string, unknown>,
|
|
284
|
-
): Promise<unknown> {
|
|
285
|
-
const res = await this.http.post<{ result: unknown }>(
|
|
286
|
-
`/api/v2/integrations/${encodeURIComponent(toolId)}/execute`,
|
|
287
|
-
{ payload: input },
|
|
288
|
-
);
|
|
289
|
-
return res.result ?? res;
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
/**
|
|
293
|
-
* Execute a tool and return the full response envelope.
|
|
294
|
-
*
|
|
295
|
-
* Unlike {@link executeTool}, this returns the complete API response including
|
|
296
|
-
* `job_id`, `status`, `credits`, and the raw `result` object.
|
|
297
|
-
*
|
|
298
|
-
* @param toolId - Tool identifier
|
|
299
|
-
* @param input - Tool-specific input parameters
|
|
300
|
-
* @returns Full response with job metadata and result
|
|
301
|
-
*
|
|
302
|
-
* @example
|
|
303
|
-
* ```typescript
|
|
304
|
-
* const raw = await client.executeToolRaw('test_company_search', { domain: 'stripe.com' });
|
|
305
|
-
* console.log(`Job: ${raw.job_id}, Credits: ${raw.credits}`);
|
|
306
|
-
* console.log(`Result:`, raw.result);
|
|
307
|
-
* ```
|
|
307
|
+
* The `result.data` field contains the provider payload. `result.meta`
|
|
308
|
+
* contains provider/upstream metadata such as HTTP status or paging details.
|
|
309
|
+
* Top-level fields such as `status`, `job_id`, and `billing` describe the
|
|
310
|
+
* Deepline execution.
|
|
308
311
|
*/
|
|
309
|
-
async
|
|
312
|
+
async executeTool<TData = unknown, TMeta = Record<string, unknown>>(
|
|
310
313
|
toolId: string,
|
|
311
314
|
input: Record<string, unknown>,
|
|
312
|
-
): Promise<
|
|
313
|
-
return this.http.post<
|
|
315
|
+
): Promise<ToolExecution<TData, TMeta>> {
|
|
316
|
+
return this.http.post<ToolExecution<TData, TMeta>>(
|
|
314
317
|
`/api/v2/integrations/${encodeURIComponent(toolId)}/execute`,
|
|
315
318
|
{ payload: input },
|
|
316
319
|
);
|
|
@@ -10,11 +10,8 @@
|
|
|
10
10
|
* const ctx = await Deepline.connect();
|
|
11
11
|
*
|
|
12
12
|
* // Execute a tool
|
|
13
|
-
* const result = await ctx.tools.execute({
|
|
14
|
-
*
|
|
15
|
-
* input: { domain: 'stripe.com' },
|
|
16
|
-
* });
|
|
17
|
-
* const company = result.value;
|
|
13
|
+
* const result = await ctx.tools.execute('test_company_search', { domain: 'stripe.com' });
|
|
14
|
+
* const company = result.result.data;
|
|
18
15
|
*
|
|
19
16
|
* // Run a named play
|
|
20
17
|
* const job = await ctx.play('email-waterfall').run({ domain: 'stripe.com' });
|
|
@@ -28,10 +25,7 @@
|
|
|
28
25
|
*
|
|
29
26
|
* export default definePlay('my-play', async (ctx, input: { domain: string }) => {
|
|
30
27
|
* ctx.log(`Looking up ${input.domain}`);
|
|
31
|
-
* const company = await ctx.tools.execute({
|
|
32
|
-
* id: 'company_search',
|
|
33
|
-
* tool: 'test_company_search',
|
|
34
|
-
* input: { domain: input.domain },
|
|
28
|
+
* const company = await ctx.tools.execute('company_search', 'test_company_search', { domain: input.domain }, {
|
|
35
29
|
* description: 'Look up company details by domain.',
|
|
36
30
|
* });
|
|
37
31
|
* return company;
|
|
@@ -58,7 +52,7 @@
|
|
|
58
52
|
|
|
59
53
|
// ——— Client ———
|
|
60
54
|
export { DeeplineClient } from './client.js';
|
|
61
|
-
export type { PlayStatus } from './client.js';
|
|
55
|
+
export type { PlayStatus, ToolExecution } from './client.js';
|
|
62
56
|
export { SDK_API_CONTRACT, SDK_VERSION } from './version.js';
|
|
63
57
|
|
|
64
58
|
// ——— Errors ———
|
|
@@ -86,15 +80,12 @@ export {
|
|
|
86
80
|
|
|
87
81
|
// ——— Tool output processing ———
|
|
88
82
|
export {
|
|
89
|
-
createToolCallResult,
|
|
90
83
|
tryConvertToList,
|
|
91
84
|
writeCsvOutputFile,
|
|
92
85
|
writeJsonOutputFile,
|
|
93
86
|
extractSummaryFields,
|
|
94
87
|
} from './tool-output.js';
|
|
95
88
|
|
|
96
|
-
export type { ToolCallResult } from './tool-output.js';
|
|
97
|
-
|
|
98
89
|
// ——— Types (re-exported for consumers) ———
|
|
99
90
|
export type {
|
|
100
91
|
DeeplineClientOptions,
|
|
@@ -119,13 +110,13 @@ export type {
|
|
|
119
110
|
DeeplineNamedPlay,
|
|
120
111
|
DeeplinePlayRuntimeContext,
|
|
121
112
|
DefinedPlay,
|
|
113
|
+
ColumnMap,
|
|
114
|
+
CsvInput,
|
|
122
115
|
PlayBindings,
|
|
116
|
+
FileInput,
|
|
123
117
|
PlayInputContract,
|
|
124
118
|
PlayJob,
|
|
125
119
|
ConditionalStepResolver,
|
|
126
|
-
MapDefinitionOptions,
|
|
127
|
-
MapRowKey,
|
|
128
|
-
MapRunOptions,
|
|
129
120
|
MapStepBuilder,
|
|
130
121
|
MapStepResolver,
|
|
131
122
|
PlayDataset,
|