deepline 0.1.4 → 0.1.8

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.d.mts CHANGED
@@ -1325,7 +1325,7 @@ declare class DeeplineClient {
1325
1325
  }>;
1326
1326
  }
1327
1327
 
1328
- declare const SDK_VERSION = "0.1.4";
1328
+ declare const SDK_VERSION = "0.1.8";
1329
1329
  declare const SDK_API_CONTRACT = "2026-04-plays-v1";
1330
1330
 
1331
1331
  /**
package/dist/index.d.ts CHANGED
@@ -1325,7 +1325,7 @@ declare class DeeplineClient {
1325
1325
  }>;
1326
1326
  }
1327
1327
 
1328
- declare const SDK_VERSION = "0.1.4";
1328
+ declare const SDK_VERSION = "0.1.8";
1329
1329
  declare const SDK_API_CONTRACT = "2026-04-plays-v1";
1330
1330
 
1331
1331
  /**
package/dist/index.js CHANGED
@@ -196,7 +196,7 @@ function resolveConfig(options) {
196
196
  }
197
197
 
198
198
  // src/version.ts
199
- var SDK_VERSION = "0.1.4";
199
+ var SDK_VERSION = "0.1.8";
200
200
  var SDK_API_CONTRACT = "2026-04-plays-v1";
201
201
 
202
202
  // ../shared_libs/play-runtime/coordinator-headers.ts
package/dist/index.mjs CHANGED
@@ -149,7 +149,7 @@ function resolveConfig(options) {
149
149
  }
150
150
 
151
151
  // src/version.ts
152
- var SDK_VERSION = "0.1.4";
152
+ var SDK_VERSION = "0.1.8";
153
153
  var SDK_API_CONTRACT = "2026-04-plays-v1";
154
154
 
155
155
  // ../shared_libs/play-runtime/coordinator-headers.ts
@@ -1,6 +1,7 @@
1
1
  import { createHash } from 'node:crypto';
2
2
  import {
3
3
  existsSync,
4
+ mkdirSync,
4
5
  readFileSync,
5
6
  readdirSync,
6
7
  realpathSync,
@@ -140,6 +141,81 @@ function defaultMaterializedPlayPath(reference: string): string {
140
141
  return resolve(`${safeName || 'play'}.play.ts`);
141
142
  }
142
143
 
144
+ function sanitizeGeneratedPlayName(value: string): string {
145
+ return (
146
+ value
147
+ .trim()
148
+ .toLowerCase()
149
+ .replace(/^prebuilt\//, '')
150
+ .replace(/[^a-z0-9-]/g, '-')
151
+ .replace(/-+/g, '-')
152
+ .replace(/^-|-$/g, '') || 'play'
153
+ );
154
+ }
155
+
156
+ function buildGeneratedCsvWrapperSource(input: {
157
+ wrapperName: string;
158
+ playRef: string;
159
+ }): string {
160
+ return `import { definePlay } from 'deepline';
161
+
162
+ export default definePlay(
163
+ ${JSON.stringify(input.wrapperName)},
164
+ async (ctx, input: Record<string, unknown> & { file: string }) => {
165
+ const rows = await ctx.csv<Record<string, unknown>>(input.file);
166
+ const constants = Object.fromEntries(
167
+ Object.entries(input).filter(([key]) => key !== 'file'),
168
+ );
169
+
170
+ const mappedRows = await ctx
171
+ .map('csv_rows', rows, {
172
+ key: (row, index) =>
173
+ String(
174
+ row.id ??
175
+ row.lead_id ??
176
+ row.email ??
177
+ row.linkedin_url ??
178
+ row.domain ??
179
+ index,
180
+ ),
181
+ })
182
+ .step('result', (row, rowCtx) =>
183
+ rowCtx.runPlay(
184
+ 'row_play',
185
+ ${JSON.stringify(input.playRef)},
186
+ {
187
+ ...constants,
188
+ ...row,
189
+ },
190
+ {
191
+ description: 'Run the source play for this CSV row.',
192
+ },
193
+ ),
194
+ )
195
+ .run({ description: 'Run the source play once per CSV row.' });
196
+
197
+ return { rows: mappedRows };
198
+ },
199
+ );
200
+ `;
201
+ }
202
+
203
+ function writeGeneratedCsvWrapperPlay(playRef: string): string {
204
+ const baseName = sanitizeGeneratedPlayName(
205
+ parseReferencedPlayTarget(playRef).unqualifiedPlayName,
206
+ );
207
+ const wrapperName = `${baseName}-csv`;
208
+ const outputDir = resolve('.deepline', 'generated');
209
+ const outputPath = join(outputDir, `${wrapperName}.play.ts`);
210
+ mkdirSync(outputDir, { recursive: true });
211
+ writeFileSync(
212
+ outputPath,
213
+ buildGeneratedCsvWrapperSource({ wrapperName, playRef }),
214
+ 'utf-8',
215
+ );
216
+ return outputPath;
217
+ }
218
+
143
219
  type MaterializedRemotePlaySource = {
144
220
  path: string;
145
221
  status: 'created' | 'updated' | 'unchanged';
@@ -892,9 +968,16 @@ async function startAndWaitForPlayCompletionByStream(input: {
892
968
  const dashboardUrl =
893
969
  getDashboardUrlFromLiveEvent(event) ??
894
970
  buildPlayDashboardUrl(input.client.baseUrl, input.playName);
895
- input.progress.phase(
896
- `loading play on ${dashboardUrl}`,
897
- );
971
+ if (!input.jsonOutput) {
972
+ writeStartedPlayRun({
973
+ runId: workflowId,
974
+ playName: input.playName,
975
+ dashboardUrl,
976
+ jsonOutput: false,
977
+ progress: input.progress,
978
+ });
979
+ }
980
+ input.progress.phase(`loading play on ${dashboardUrl}`);
898
981
  emittedDashboardUrl = true;
899
982
  }
900
983
  assertPlayWaitNotTimedOut({
@@ -1024,8 +1107,8 @@ async function waitForPlayCompletionByPolling(input: {
1024
1107
  const now = Date.now();
1025
1108
  if (now - lastTransientPollWarningAt >= 30_000) {
1026
1109
  const message = error instanceof Error ? error.message : String(error);
1027
- process.stderr.write(
1028
- `[play tail] transient status poll failed; retrying: ${message}\n`,
1110
+ input.progress.writeLine(
1111
+ `[play tail] transient status poll failed; retrying: ${message}`,
1029
1112
  );
1030
1113
  lastTransientPollWarningAt = now;
1031
1114
  }
@@ -1711,6 +1794,7 @@ function writeStartedPlayRun(input: {
1711
1794
  statusUrl?: string;
1712
1795
  dashboardUrl?: string;
1713
1796
  jsonOutput: boolean;
1797
+ progress?: CliProgress;
1714
1798
  }): void {
1715
1799
  const payload = {
1716
1800
  runId: input.runId,
@@ -1739,7 +1823,12 @@ function writeStartedPlayRun(input: {
1739
1823
  lines.push(` play page: ${input.dashboardUrl}`);
1740
1824
  }
1741
1825
 
1742
- console.log(lines.join('\n'));
1826
+ const output = lines.join('\n');
1827
+ if (input.progress) {
1828
+ input.progress.writeLine(output, process.stdout);
1829
+ return;
1830
+ }
1831
+ console.log(output);
1743
1832
  }
1744
1833
 
1745
1834
  function parsePlayRunOptions(args: string[]): PlayRunCommandOptions {
@@ -2112,6 +2201,7 @@ async function handleFileBackedRun(
2112
2201
  statusUrl: started.statusUrl,
2113
2202
  dashboardUrl,
2114
2203
  jsonOutput: options.jsonOutput,
2204
+ progress,
2115
2205
  });
2116
2206
  return 0;
2117
2207
  }
@@ -2184,6 +2274,22 @@ async function handleNamedRun(options: PlayRunCommandOptions): Promise<number> {
2184
2274
  waitTimeoutMs: options.waitTimeoutMs,
2185
2275
  progress,
2186
2276
  });
2277
+ if (finalStatus.status !== 'completed' && options.csvPath) {
2278
+ progress.phase('generating csv wrapper play');
2279
+ const generatedPlayPath = writeGeneratedCsvWrapperPlay(
2280
+ options.target.name,
2281
+ );
2282
+ progress.writeLogLine(
2283
+ `Generated CSV wrapper play: ${generatedPlayPath}`,
2284
+ );
2285
+ progress.phase('running generated csv wrapper play');
2286
+ return handleFileBackedRun({
2287
+ ...options,
2288
+ target: { kind: 'file', path: generatedPlayPath },
2289
+ revisionId: null,
2290
+ revisionSelector: null,
2291
+ });
2292
+ }
2187
2293
  const exportedPath = exportPlayStatusRows(finalStatus, options.outPath);
2188
2294
  if (finalStatus.status === 'completed') {
2189
2295
  progress.complete();
@@ -2211,6 +2317,7 @@ async function handleNamedRun(options: PlayRunCommandOptions): Promise<number> {
2211
2317
  statusUrl: started.statusUrl,
2212
2318
  dashboardUrl,
2213
2319
  jsonOutput: options.jsonOutput,
2320
+ progress,
2214
2321
  });
2215
2322
  return 0;
2216
2323
  }
@@ -131,6 +131,7 @@ Output:
131
131
  ok: false,
132
132
  error: error instanceof Error ? error.message : String(error),
133
133
  });
134
+ progress?.fail();
134
135
  if (process.argv.includes('--json')) {
135
136
  printJsonError(error);
136
137
  } else if (error instanceof Error) {
@@ -56,6 +56,20 @@ export class CliProgress {
56
56
  }
57
57
  }
58
58
 
59
+ writeLine(line: string, stream: NodeJS.WriteStream = process.stderr): void {
60
+ if (!this.enabled || !this.interactive) {
61
+ stream.write(`${line}\n`);
62
+ return;
63
+ }
64
+ const activeMessage = this.lastMessage;
65
+ this.worker?.terminate().catch(() => undefined);
66
+ this.worker = null;
67
+ stream.write(`\r\x1b[2K${line}\n`);
68
+ if (activeMessage) {
69
+ this.startWorker().postMessage({ type: 'phase', message: activeMessage });
70
+ }
71
+ }
72
+
59
73
  private settle(mark: '✓' | '✗'): void {
60
74
  if (!this.enabled || !this.lastMessage) {
61
75
  return;
@@ -2,6 +2,7 @@ import { spawn } from 'node:child_process';
2
2
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
3
3
  import { homedir } from 'node:os';
4
4
  import { dirname, join } from 'node:path';
5
+ import { getActiveCliProgress } from './progress.js';
5
6
  import { baseUrlSlug } from '../config.js';
6
7
 
7
8
  const CHECK_TIMEOUT_MS = 3_000;
@@ -128,10 +129,13 @@ export async function syncSdkSkillsIfNeeded(baseUrl: string): Promise<void> {
128
129
  const update = await fetchSkillsUpdate(baseUrl, localVersion);
129
130
  if (!update?.needsUpdate || !update.remoteVersion) return;
130
131
 
131
- process.stderr.write('SDK skills changed; syncing deepline-sdk skill...\n');
132
+ const progress = getActiveCliProgress();
133
+ progress?.writeLine('SDK skills changed; syncing deepline-sdk skill...') ??
134
+ process.stderr.write('SDK skills changed; syncing deepline-sdk skill...\n');
132
135
  const installed = await runSkillsInstall(baseUrl);
133
136
  if (!installed) return;
134
137
 
135
138
  writeLocalSkillsVersion(baseUrl, update.remoteVersion);
136
- process.stderr.write('SDK skills are up to date.\n');
139
+ progress?.writeLine('SDK skills are up to date.') ??
140
+ process.stderr.write('SDK skills are up to date.\n');
137
141
  }
@@ -1,2 +1,2 @@
1
- export const SDK_VERSION = "0.1.4";
1
+ export const SDK_VERSION = "0.1.8";
2
2
  export const SDK_API_CONTRACT = "2026-04-plays-v1";
@@ -165,6 +165,14 @@ function formatTypeScriptDiagnostic(diagnostic: ts.Diagnostic): string | null {
165
165
  return `${diagnostic.file.fileName}:${line + 1}:${character + 1} ${message}`;
166
166
  }
167
167
 
168
+ function resolveBundledTypeRoots(): string[] {
169
+ try {
170
+ return [dirname(dirname(playArtifactRequire.resolve('@types/node/package.json')))];
171
+ } catch {
172
+ return [];
173
+ }
174
+ }
175
+
168
176
  function typecheckPlaySource(
169
177
  input: SourceGraphAnalysis,
170
178
  adapter: PlayBundlingAdapter,
@@ -196,6 +204,7 @@ function typecheckPlaySource(
196
204
  allowJs: true,
197
205
  resolveJsonModule: true,
198
206
  types: ['node'],
207
+ typeRoots: resolveBundledTypeRoots(),
199
208
  });
200
209
  return ts
201
210
  .getPreEmitDiagnostics(program)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deepline",
3
- "version": "0.1.4",
3
+ "version": "0.1.8",
4
4
  "description": "Deepline SDK + CLI — B2B data enrichment powered by durable cloud execution",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -44,12 +44,14 @@
44
44
  "prepublishOnly": "tsup"
45
45
  },
46
46
  "dependencies": {
47
+ "@types/node": "^20.0.0",
48
+ "acorn": "^8.16.0",
49
+ "acorn-walk": "^8.3.5",
47
50
  "commander": "^14.0.3",
48
51
  "csv-parse": "^5.6.0",
49
52
  "csv-stringify": "^6.5.0",
50
53
  "esbuild": "^0.25.11",
51
- "typescript": "^5.9.3",
52
- "@types/node": "^20.0.0"
54
+ "typescript": "^5.9.3"
53
55
  },
54
56
  "devDependencies": {
55
57
  "tsup": "^8.0.0"