deepline 0.1.122 → 0.1.124

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.mjs CHANGED
@@ -196,10 +196,11 @@ var SDK_RELEASE = {
196
196
  // skill on the sdk sync surface, and the people-search-to-email prebuilt.
197
197
  // 0.1.108 ships explicit dataset column/tool recompute policy and removes
198
198
  // the SDK enrich generator's one-second stale policy.
199
- version: "0.1.122",
199
+ // 0.1.110 ships authored V2 prebuilts and required top-level play descriptions.
200
+ version: "0.1.124",
200
201
  apiContract: "2026-06-dataset-column-cell-stale-hard-cutover",
201
202
  supportPolicy: {
202
- latest: "0.1.122",
203
+ latest: "0.1.124",
203
204
  minimumSupported: "0.1.53",
204
205
  deprecatedBelow: "0.1.53",
205
206
  commandMinimumSupported: [
@@ -207,6 +208,55 @@ var SDK_RELEASE = {
207
208
  command: "enrich",
208
209
  minimumSupported: "0.1.108",
209
210
  reason: "Older SDK CLI enrich generated stale play source for the current dataset API."
211
+ },
212
+ {
213
+ command: "plays",
214
+ minimumSupported: "0.1.110",
215
+ reason: "Play file commands now require top-level definePlay descriptions so agents and play surfaces can explain local plays."
216
+ },
217
+ {
218
+ command: "plays run",
219
+ minimumSupported: "0.1.110",
220
+ reason: "Play file commands now require top-level definePlay descriptions so agents and play surfaces can explain local plays."
221
+ },
222
+ {
223
+ command: "run",
224
+ displayCommand: "plays run",
225
+ minimumSupported: "0.1.110",
226
+ reason: "Play file commands now require top-level definePlay descriptions so agents and play surfaces can explain local plays."
227
+ },
228
+ {
229
+ command: "plays check",
230
+ minimumSupported: "0.1.110",
231
+ reason: "Play file commands now require top-level definePlay descriptions so agents and play surfaces can explain local plays."
232
+ },
233
+ {
234
+ command: "check",
235
+ displayCommand: "plays check",
236
+ minimumSupported: "0.1.110",
237
+ reason: "Play file commands now require top-level definePlay descriptions so agents and play surfaces can explain local plays."
238
+ },
239
+ {
240
+ command: "plays publish",
241
+ minimumSupported: "0.1.110",
242
+ reason: "Play file commands now require top-level definePlay descriptions so agents and play surfaces can explain local plays."
243
+ },
244
+ {
245
+ command: "publish",
246
+ displayCommand: "plays publish",
247
+ minimumSupported: "0.1.110",
248
+ reason: "Play file commands now require top-level definePlay descriptions so agents and play surfaces can explain local plays."
249
+ },
250
+ {
251
+ command: "plays set-live",
252
+ minimumSupported: "0.1.110",
253
+ reason: "Play file commands now require top-level definePlay descriptions so agents and play surfaces can explain local plays."
254
+ },
255
+ {
256
+ command: "set-live",
257
+ displayCommand: "plays set-live",
258
+ minimumSupported: "0.1.110",
259
+ reason: "Play file commands now require top-level definePlay descriptions so agents and play surfaces can explain local plays."
210
260
  }
211
261
  ],
212
262
  autoUpdatePatchLag: 2
@@ -1813,7 +1863,8 @@ var DeeplineClient = class {
1813
1863
  tail: (runId, options2) => this.tailRun(runId, options2),
1814
1864
  logs: (runId, options2) => this.getRunLogs(runId, options2),
1815
1865
  exportDatasetRows: (input) => this.getPlaySheetRows(input),
1816
- stop: (runId, options2) => this.stopRun(runId, options2)
1866
+ stop: (runId, options2) => this.stopRun(runId, options2),
1867
+ stopAll: (options2) => this.stopAllRuns(options2)
1817
1868
  };
1818
1869
  this.billing = {
1819
1870
  plans: () => this.getBillingPlans(),
@@ -1878,12 +1929,14 @@ var DeeplineClient = class {
1878
1929
  play.outputSchema,
1879
1930
  "rowOutputSchema"
1880
1931
  );
1932
+ const description = play.description?.trim() || play.currentRevision?.description?.trim() || play.liveRevision?.description?.trim() || null;
1881
1933
  const runCommand = this.playRunCommand(play, { csvInput });
1882
1934
  const cloneEditStarter = this.playCloneEditStarter(play);
1883
1935
  return {
1884
1936
  name: play.name,
1885
1937
  ...play.reference ? { reference: play.reference } : {},
1886
1938
  ...play.displayName ? { displayName: play.displayName } : {},
1939
+ ...description ? { description } : {},
1887
1940
  origin: play.origin,
1888
1941
  ownerType: play.ownerType,
1889
1942
  canEdit: play.canEdit,
@@ -2104,6 +2157,7 @@ var DeeplineClient = class {
2104
2157
  ...request.artifactStorageKey ? { artifactStorageKey: request.artifactStorageKey } : {},
2105
2158
  ...request.sourceCode ? { sourceCode: request.sourceCode } : {},
2106
2159
  ...request.sourceFiles ? { sourceFiles: request.sourceFiles } : {},
2160
+ ...request.description ? { description: request.description } : {},
2107
2161
  ..."staticPipeline" in request ? { staticPipeline: request.staticPipeline } : {},
2108
2162
  ...request.artifactHash ? { artifactHash: request.artifactHash } : {},
2109
2163
  ...request.graphHash ? { graphHash: request.graphHash } : {},
@@ -2142,6 +2196,7 @@ var DeeplineClient = class {
2142
2196
  ...request.artifactStorageKey ? { artifactStorageKey: request.artifactStorageKey } : {},
2143
2197
  ...request.sourceCode ? { sourceCode: request.sourceCode } : {},
2144
2198
  ...request.sourceFiles ? { sourceFiles: request.sourceFiles } : {},
2199
+ ...request.description ? { description: request.description } : {},
2145
2200
  ..."staticPipeline" in request ? { staticPipeline: request.staticPipeline } : {},
2146
2201
  ...request.artifactHash ? { artifactHash: request.artifactHash } : {},
2147
2202
  ...request.graphHash ? { graphHash: request.graphHash } : {},
@@ -2299,6 +2354,7 @@ var DeeplineClient = class {
2299
2354
  name: input.name,
2300
2355
  sourceCode: input.sourceCode,
2301
2356
  sourceFiles: input.sourceFiles,
2357
+ description: input.description,
2302
2358
  artifact: input.artifact,
2303
2359
  compilerManifest,
2304
2360
  publish: false
@@ -2311,6 +2367,7 @@ var DeeplineClient = class {
2311
2367
  return this.startPlayRun({
2312
2368
  name: input.name,
2313
2369
  artifactStorageKey: registeredArtifact.artifactStorageKey,
2370
+ description: input.description,
2314
2371
  compilerManifest,
2315
2372
  ...input.input ? { input: input.input } : {},
2316
2373
  ...input.inputFile ? { inputFile: input.inputFile } : {},
@@ -2365,6 +2422,7 @@ var DeeplineClient = class {
2365
2422
  name,
2366
2423
  sourceCode,
2367
2424
  sourceFiles: options?.sourceFiles,
2425
+ description: options?.description,
2368
2426
  artifact,
2369
2427
  compilerManifest,
2370
2428
  publish: false
@@ -2378,6 +2436,7 @@ var DeeplineClient = class {
2378
2436
  name,
2379
2437
  artifactStorageKey: registeredArtifact.artifactStorageKey,
2380
2438
  sourceCode,
2439
+ description: options?.description,
2381
2440
  staticPipeline: registeredArtifact.staticPipeline ?? null,
2382
2441
  artifactHash: typeof artifact.artifactHash === "string" ? artifact.artifactHash : void 0,
2383
2442
  graphHash: typeof artifact.graphHash === "string" ? artifact.graphHash : void 0,
@@ -2677,15 +2736,21 @@ var DeeplineClient = class {
2677
2736
  * ```
2678
2737
  */
2679
2738
  async listRuns(options) {
2680
- const playName = options.play.trim();
2681
- if (!playName) {
2682
- throw new Error("runs.list requires options.play.");
2739
+ const playName = options.play?.trim();
2740
+ const params = new URLSearchParams();
2741
+ if (playName) {
2742
+ params.set("play", playName);
2683
2743
  }
2684
- const params = new URLSearchParams({ play: playName });
2685
2744
  const status = options.status?.trim();
2686
2745
  if (status) {
2687
2746
  params.set("status", status);
2688
2747
  }
2748
+ if (typeof options.limit === "number" && Number.isFinite(options.limit)) {
2749
+ params.set("limit", String(Math.max(1, Math.floor(options.limit))));
2750
+ }
2751
+ if (!playName && !status) {
2752
+ throw new Error("runs.list requires options.play or options.status.");
2753
+ }
2689
2754
  params.set("compact", "true");
2690
2755
  const response = await this.http.get(
2691
2756
  `/api/v2/runs?${params.toString()}`
@@ -2992,6 +3057,24 @@ var DeeplineClient = class {
2992
3057
  options?.reason ? { reason: options.reason } : {}
2993
3058
  );
2994
3059
  }
3060
+ /**
3061
+ * Stop every active run visible to the current workspace.
3062
+ *
3063
+ * This is the SDK equivalent of:
3064
+ *
3065
+ * ```bash
3066
+ * deepline runs stop-all --reason "stale lock" --json
3067
+ * ```
3068
+ *
3069
+ * Use this when a failed parent run left child or waiting runs active and you
3070
+ * need to clear the workspace run-slot state without knowing each run id.
3071
+ */
3072
+ async stopAllRuns(options) {
3073
+ return this.http.post(
3074
+ "/api/v2/runs/stop-all",
3075
+ options?.reason ? { reason: options.reason } : {}
3076
+ );
3077
+ }
2995
3078
  /**
2996
3079
  * List callable plays visible to the workspace.
2997
3080
  *
@@ -4616,18 +4699,21 @@ function definePlay(nameOrConfig, maybeFn, maybeBindings) {
4616
4699
  name: nameOrConfig,
4617
4700
  fn: maybeFn,
4618
4701
  bindings: maybeBindings,
4702
+ description: maybeBindings?.description,
4619
4703
  inputSchema: void 0,
4620
4704
  billing: maybeBindings?.billing
4621
4705
  } : {
4622
4706
  name: nameOrConfig.id,
4623
4707
  fn: nameOrConfig.run,
4624
4708
  bindings: nameOrConfig.bindings,
4709
+ description: nameOrConfig.description,
4625
4710
  inputSchema: nameOrConfig.input.schema,
4626
4711
  billing: nameOrConfig.billing
4627
4712
  };
4628
4713
  const name = config.name;
4629
4714
  const fn = config.fn;
4630
4715
  const bindings = config.bindings;
4716
+ const description = config.description?.trim();
4631
4717
  const billing = config.billing;
4632
4718
  const inputSchema = config.inputSchema;
4633
4719
  if (typeof fn !== "function") {
@@ -4651,6 +4737,7 @@ function definePlay(nameOrConfig, maybeFn, maybeBindings) {
4651
4737
  }
4652
4738
  const metadata = {
4653
4739
  name,
4740
+ ...description ? { description } : {},
4654
4741
  ...bindings ? { bindings } : {},
4655
4742
  ...inputSchema ? { inputSchema } : {},
4656
4743
  ...billing ? { billing } : {}
@@ -89,6 +89,7 @@ type BundledPlayFileSuccess = {
89
89
  sourceFiles: Record<string, string>;
90
90
  filePath: string;
91
91
  playName: string | null;
92
+ playDescription: string | null;
92
93
  compilerManifest?: PlayCompilerManifest;
93
94
  packagedFiles: PlayLocalFileReference[];
94
95
  unresolvedFileReferences: PlayLocalFileDiscoveryError[];
@@ -89,6 +89,7 @@ type BundledPlayFileSuccess = {
89
89
  sourceFiles: Record<string, string>;
90
90
  filePath: string;
91
91
  playName: string | null;
92
+ playDescription: string | null;
92
93
  compilerManifest?: PlayCompilerManifest;
93
94
  packagedFiles: PlayLocalFileReference[];
94
95
  unresolvedFileReferences: PlayLocalFileDiscoveryError[];
@@ -211,6 +211,93 @@ function stripCommentsToSpaces(source) {
211
211
  (match, prefix) => prefix + " ".repeat(Math.max(0, match.length - prefix.length))
212
212
  );
213
213
  }
214
+ function previousSignificantToken(source, index) {
215
+ let cursor = index - 1;
216
+ while (cursor >= 0 && /\s/.test(source[cursor])) cursor -= 1;
217
+ if (cursor < 0) return "";
218
+ const char = source[cursor];
219
+ if (!/[A-Za-z0-9_$]/.test(char)) return char;
220
+ let start = cursor;
221
+ while (start > 0 && /[A-Za-z0-9_$]/.test(source[start - 1])) start -= 1;
222
+ return source.slice(start, cursor + 1);
223
+ }
224
+ function canStartRegexLiteral(source, slashIndex) {
225
+ const token = previousSignificantToken(source, slashIndex);
226
+ return !token || token === "return" || token === "throw" || token === "case" || token === "delete" || token === "typeof" || token === "void" || token === "instanceof" || /^(?:[({[=,:;!&|?+\-*~^<>%]|\.\.\.)$/.test(token);
227
+ }
228
+ function maskSourceForStructure(source) {
229
+ const chars = source.split("");
230
+ const maskRange = (start, end) => {
231
+ for (let cursor = start; cursor < end; cursor += 1) {
232
+ if (chars[cursor] !== "\n") chars[cursor] = " ";
233
+ }
234
+ };
235
+ for (let index = 0; index < source.length; index += 1) {
236
+ const char = source[index];
237
+ const next = source[index + 1];
238
+ if (char === "/" && next === "/") {
239
+ let end = index + 2;
240
+ while (end < source.length && source[end] !== "\n") end += 1;
241
+ maskRange(index, end);
242
+ index = end;
243
+ continue;
244
+ }
245
+ if (char === "/" && next === "*") {
246
+ const close = source.indexOf("*/", index + 2);
247
+ const end = close >= 0 ? close + 2 : source.length;
248
+ maskRange(index, end);
249
+ index = end - 1;
250
+ continue;
251
+ }
252
+ if (char === '"' || char === "'" || char === "`") {
253
+ const quote = char;
254
+ let end = index + 1;
255
+ let escaped = false;
256
+ while (end < source.length) {
257
+ const current = source[end];
258
+ if (escaped) {
259
+ escaped = false;
260
+ } else if (current === "\\") {
261
+ escaped = true;
262
+ } else if (current === quote) {
263
+ end += 1;
264
+ break;
265
+ }
266
+ end += 1;
267
+ }
268
+ maskRange(index, end);
269
+ index = end - 1;
270
+ continue;
271
+ }
272
+ if (char === "/" && canStartRegexLiteral(source, index)) {
273
+ let end = index + 1;
274
+ let escaped = false;
275
+ let inCharacterClass = false;
276
+ while (end < source.length) {
277
+ const current = source[end];
278
+ if (escaped) {
279
+ escaped = false;
280
+ } else if (current === "\\") {
281
+ escaped = true;
282
+ } else if (current === "[") {
283
+ inCharacterClass = true;
284
+ } else if (current === "]") {
285
+ inCharacterClass = false;
286
+ } else if (current === "/" && !inCharacterClass) {
287
+ end += 1;
288
+ while (/[A-Za-z]/.test(source[end] ?? "")) end += 1;
289
+ break;
290
+ } else if (current === "\n") {
291
+ break;
292
+ }
293
+ end += 1;
294
+ }
295
+ maskRange(index, end);
296
+ index = end - 1;
297
+ }
298
+ }
299
+ return chars.join("");
300
+ }
214
301
  function lineAndColumnAt(source, index) {
215
302
  const prefix = source.slice(0, index);
216
303
  const lines = prefix.split("\n");
@@ -280,9 +367,13 @@ function findSourceImportReferences(sourceCode) {
280
367
  function unquoteStringLiteral(literal) {
281
368
  const trimmed = literal.trim();
282
369
  const quote = trimmed[0];
283
- if (quote !== '"' && quote !== "'" || trimmed[trimmed.length - 1] !== quote) {
370
+ if (quote !== '"' && quote !== "'" && quote !== "`" || trimmed[trimmed.length - 1] !== quote) {
284
371
  return null;
285
372
  }
373
+ if (quote === "`") {
374
+ const value = trimmed.slice(1, -1);
375
+ return value.includes("${") ? null : value;
376
+ }
286
377
  try {
287
378
  return JSON.parse(
288
379
  quote === '"' ? trimmed : `"${trimmed.slice(1, -1).replace(/"/g, '\\"')}"`
@@ -292,25 +383,10 @@ function unquoteStringLiteral(literal) {
292
383
  }
293
384
  }
294
385
  function findMatchingBrace(source, openIndex) {
386
+ const structuralSource = maskSourceForStructure(source);
295
387
  let depth = 0;
296
- let quote = null;
297
- let escaped = false;
298
- for (let index = openIndex; index < source.length; index += 1) {
299
- const char = source[index];
300
- if (quote) {
301
- if (escaped) {
302
- escaped = false;
303
- } else if (char === "\\") {
304
- escaped = true;
305
- } else if (char === quote) {
306
- quote = null;
307
- }
308
- continue;
309
- }
310
- if (char === '"' || char === "'" || char === "`") {
311
- quote = char;
312
- continue;
313
- }
388
+ for (let index = openIndex; index < structuralSource.length; index += 1) {
389
+ const char = structuralSource[index];
314
390
  if (char === "{") depth += 1;
315
391
  if (char === "}") {
316
392
  depth -= 1;
@@ -319,35 +395,198 @@ function findMatchingBrace(source, openIndex) {
319
395
  }
320
396
  return -1;
321
397
  }
398
+ function findMatchingParen(source, openIndex) {
399
+ const structuralSource = maskSourceForStructure(source);
400
+ let depth = 0;
401
+ for (let index = openIndex; index < structuralSource.length; index += 1) {
402
+ const char = structuralSource[index];
403
+ if (char === "(") depth += 1;
404
+ if (char === ")") {
405
+ depth -= 1;
406
+ if (depth === 0) return index;
407
+ }
408
+ }
409
+ return -1;
410
+ }
411
+ function splitTopLevelArguments(source) {
412
+ const args = [];
413
+ const structuralSource = maskSourceForStructure(source);
414
+ let start = 0;
415
+ let parenDepth = 0;
416
+ let braceDepth = 0;
417
+ let bracketDepth = 0;
418
+ for (let index = 0; index < structuralSource.length; index += 1) {
419
+ const char = structuralSource[index];
420
+ if (char === "(") parenDepth += 1;
421
+ if (char === ")") parenDepth -= 1;
422
+ if (char === "{") braceDepth += 1;
423
+ if (char === "}") braceDepth -= 1;
424
+ if (char === "[") bracketDepth += 1;
425
+ if (char === "]") bracketDepth -= 1;
426
+ if (char === "," && parenDepth === 0 && braceDepth === 0 && bracketDepth === 0) {
427
+ args.push(source.slice(start, index).trim());
428
+ start = index + 1;
429
+ }
430
+ }
431
+ const finalArg = source.slice(start).trim();
432
+ if (finalArg) args.push(finalArg);
433
+ return args;
434
+ }
435
+ function extractStringProperty(objectSource, propertyName) {
436
+ for (const entry of splitTopLevelArguments(objectSource)) {
437
+ const structuralEntry = stripCommentsToSpaces(entry).trim();
438
+ const match = structuralEntry.match(
439
+ new RegExp(
440
+ `^(?:${propertyName}|['"]${propertyName}['"])\\s*:\\s*((['"\`])(?:\\\\.|(?!\\2)[\\s\\S])*\\2)\\s*$`
441
+ )
442
+ );
443
+ const value = match?.[1] ? unquoteStringLiteral(match[1]) : null;
444
+ if (value?.trim()) return value.trim();
445
+ }
446
+ return null;
447
+ }
322
448
  function extractDefinedPlayName(sourceCode) {
323
- const source = stripCommentsToSpaces(sourceCode);
449
+ for (const call of findDefinePlayCalls(sourceCode)) {
450
+ const name = nameFromDefinePlayArguments(sourceCode, call.arguments);
451
+ if (name) return name;
452
+ }
453
+ return null;
454
+ }
455
+ function extractDefinedPlayNameForExport(sourceCode, exportName) {
456
+ return findDefinedPlayMetadata(
457
+ sourceCode,
458
+ exportName,
459
+ nameFromDefinePlayArguments
460
+ );
461
+ }
462
+ function extractDefinedPlayDescription(sourceCode) {
463
+ return findDefinedPlayMetadata(
464
+ sourceCode,
465
+ null,
466
+ descriptionFromDefinePlayArguments
467
+ );
468
+ }
469
+ function extractDefinedPlayDescriptionForExport(sourceCode, exportName) {
470
+ return findDefinedPlayMetadata(
471
+ sourceCode,
472
+ exportName,
473
+ descriptionFromDefinePlayArguments
474
+ );
475
+ }
476
+ function findDefinedPlayMetadata(sourceCode, exportName, getMetadata) {
477
+ const resolvedExportName = exportName === "default" ? findDefaultExportIdentifier(sourceCode) ?? exportName : exportName;
478
+ for (const call of findDefinePlayCalls(sourceCode)) {
479
+ if (resolvedExportName && call.exportName !== resolvedExportName) {
480
+ continue;
481
+ }
482
+ const value = getMetadata(sourceCode, call.arguments);
483
+ if (value) return value;
484
+ }
485
+ return null;
486
+ }
487
+ function findDefinePlayCalls(sourceCode) {
488
+ const source = maskSourceForStructure(sourceCode);
324
489
  const callPattern = /(?:\b[A-Za-z_$][\w$]*\s*\.\s*)?\b(?:definePlay|defineWorkflow)\s*\(/g;
490
+ const calls = [];
325
491
  for (const match of source.matchAll(callPattern)) {
326
- const openParen = match.index + match[0].length - 1;
327
- const firstArgStart = openParen + 1;
328
- const firstNonSpace = source.slice(firstArgStart).search(/\S/);
329
- if (firstNonSpace < 0) continue;
330
- const argIndex = firstArgStart + firstNonSpace;
331
- const quote = source[argIndex];
332
- if (quote === '"' || quote === "'") {
333
- const literalMatch = source.slice(argIndex).match(/^(['"])(?:\\.|(?!\1)[\s\S])*\1/);
334
- const value = literalMatch ? unquoteStringLiteral(literalMatch[0]) : null;
335
- if (value?.trim()) return value.trim();
336
- }
337
- if (quote === "{") {
338
- const closeBrace = findMatchingBrace(source, argIndex);
339
- if (closeBrace < 0) continue;
340
- const objectSource = source.slice(argIndex + 1, closeBrace);
341
- const idMatch = objectSource.match(
342
- /(?:^|[,{\s])(?:id|['"]id['"])\s*:\s*(['"])([\s\S]*?)\1/
343
- );
344
- if (idMatch?.[2]?.trim()) {
345
- return idMatch[2].trim();
346
- }
347
- }
492
+ const callStart = match.index;
493
+ const openParen = callStart + match[0].length - 1;
494
+ const closeParen = findMatchingParen(sourceCode, openParen);
495
+ if (closeParen < 0) continue;
496
+ calls.push({
497
+ arguments: splitTopLevelArguments(
498
+ sourceCode.slice(openParen + 1, closeParen)
499
+ ),
500
+ exportName: exportNameForDefinePlayCall(sourceCode, callStart)
501
+ });
502
+ }
503
+ return calls;
504
+ }
505
+ function findDefaultExportIdentifier(sourceCode) {
506
+ const source = maskSourceForStructure(sourceCode);
507
+ const pattern = /\bexport\s+default\s+([A-Za-z_$][\w$]*)/g;
508
+ for (const match of source.matchAll(pattern)) {
509
+ const afterIdentifier = match.index + match[0].length;
510
+ const nextNonSpace = source.slice(afterIdentifier).match(/\S/)?.[0] ?? "";
511
+ if (nextNonSpace !== "(") return match[1] ?? null;
512
+ }
513
+ return null;
514
+ }
515
+ function nameFromDefinePlayArguments(sourceCode, args) {
516
+ const firstArg = args[0]?.trim();
517
+ if (!firstArg) return null;
518
+ if (/^(['"`])/.test(firstArg))
519
+ return unquoteStringLiteral(firstArg)?.trim() ?? null;
520
+ const objectSource = objectLiteralBodyFromArgument(sourceCode, firstArg);
521
+ if (objectSource) {
522
+ return extractStringProperty(objectSource, "id");
523
+ }
524
+ return null;
525
+ }
526
+ function descriptionFromDefinePlayArguments(sourceCode, args) {
527
+ const firstArgDescription = descriptionFromDefinePlayArgument(
528
+ sourceCode,
529
+ args[0]
530
+ );
531
+ if (firstArgDescription) return firstArgDescription;
532
+ for (let index = args.length - 1; index >= 2; index -= 1) {
533
+ const description = descriptionFromDefinePlayArgument(
534
+ sourceCode,
535
+ args[index]
536
+ );
537
+ if (description) return description;
348
538
  }
349
539
  return null;
350
540
  }
541
+ function descriptionFromDefinePlayArgument(sourceCode, arg) {
542
+ const trimmed = arg?.trim();
543
+ if (!trimmed) return null;
544
+ const objectSource = objectLiteralBodyFromArgument(sourceCode, trimmed);
545
+ if (!objectSource) return null;
546
+ return extractStringProperty(objectSource, "description");
547
+ }
548
+ function objectLiteralBodyFromArgument(sourceCode, arg) {
549
+ const trimmed = arg.trim();
550
+ if (trimmed.startsWith("{")) {
551
+ const closeBrace = findMatchingBrace(trimmed, 0);
552
+ return closeBrace >= 0 ? trimmed.slice(1, closeBrace) : trimmed.slice(1);
553
+ }
554
+ if (!/^[A-Za-z_$][\w$]*$/.test(trimmed)) return null;
555
+ return findTopLevelObjectLiteralBody(sourceCode, trimmed);
556
+ }
557
+ function escapeRegExp(value) {
558
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
559
+ }
560
+ function findTopLevelObjectLiteralBody(sourceCode, identifier) {
561
+ const source = maskSourceForStructure(sourceCode);
562
+ const pattern = new RegExp(
563
+ `(?:^|[;\\n])\\s*(?:export\\s+)?(?:const|let|var)\\s+${escapeRegExp(
564
+ identifier
565
+ )}(?:\\s*:[^=;]+)?\\s*=\\s*{`,
566
+ "g"
567
+ );
568
+ for (const match of source.matchAll(pattern)) {
569
+ const openBrace = source.indexOf("{", match.index);
570
+ if (openBrace < 0) continue;
571
+ const closeBrace = findMatchingBrace(sourceCode, openBrace);
572
+ if (closeBrace < 0) continue;
573
+ return sourceCode.slice(openBrace + 1, closeBrace);
574
+ }
575
+ return null;
576
+ }
577
+ function exportNameForDefinePlayCall(sourceCode, callStart) {
578
+ const source = maskSourceForStructure(sourceCode);
579
+ const structuralPrefix = source.slice(Math.max(0, callStart - 500), callStart).trimEnd();
580
+ if (/\bexport\s+default\s*$/.test(structuralPrefix)) return "default";
581
+ const variableMatch = structuralPrefix.match(
582
+ /\bexport\s+(?:declare\s+)?(?:const|let|var)\s+([A-Za-z_$][\w$]*)(?:\s*:[^=;]+)?\s*=\s*$/
583
+ );
584
+ if (variableMatch?.[1]) return variableMatch[1];
585
+ const localVariableMatch = structuralPrefix.match(
586
+ /\b(?:const|let|var)\s+([A-Za-z_$][\w$]*)(?:\s*:[^=;]+)?\s*=\s*$/
587
+ );
588
+ return localVariableMatch?.[1] ?? null;
589
+ }
351
590
  function canonicalizeRootPlayNameForWorkersRuntimeHash(sourceCode) {
352
591
  const source = stripCommentsToSpaces(sourceCode);
353
592
  const callPattern = /(?:\b[A-Za-z_$][\w$]*\s*\.\s*)?\b(?:definePlay|defineWorkflow)\s*\(/g;
@@ -748,7 +987,7 @@ function resolvePackageImport(specifier, fromFile, adapter) {
748
987
  version: readPackageVersionFromPackageJson(packageJsonPath, packageName)
749
988
  };
750
989
  }
751
- async function analyzeSourceGraph(entryFile, adapter) {
990
+ async function analyzeSourceGraph(entryFile, adapter, exportName) {
752
991
  const absoluteEntryFile = await normalizeLocalPath(entryFile);
753
992
  const workspace = createPlayWorkspace(absoluteEntryFile);
754
993
  const localFiles = /* @__PURE__ */ new Map();
@@ -849,7 +1088,8 @@ async function analyzeSourceGraph(entryFile, adapter) {
849
1088
  })).sort((left, right) => left.filePath.localeCompare(right.filePath))
850
1089
  })
851
1090
  );
852
- const playName = extractDefinedPlayName(sourceCode);
1091
+ const playName = extractDefinedPlayNameForExport(sourceCode, exportName) ?? (exportName === "default" ? extractDefinedPlayName(sourceCode) : null);
1092
+ const playDescription = extractDefinedPlayDescriptionForExport(sourceCode, exportName) ?? (exportName === "default" ? extractDefinedPlayDescription(sourceCode) : null);
853
1093
  return {
854
1094
  sourceCode,
855
1095
  sourceFiles: Object.fromEntries(
@@ -865,6 +1105,7 @@ async function analyzeSourceGraph(entryFile, adapter) {
865
1105
  packages: [...packages.entries()].map(([name, version]) => ({ name, version })).sort((left, right) => left.name.localeCompare(right.name))
866
1106
  },
867
1107
  playName,
1108
+ playDescription,
868
1109
  importedPlayDependencies: [...importedPlayDependencies.values()].sort(
869
1110
  (left, right) => left.filePath.localeCompare(right.filePath)
870
1111
  )
@@ -1144,7 +1385,11 @@ async function bundlePlayFile(filePath, options) {
1144
1385
  const absolutePath = await normalizeLocalPath(filePath);
1145
1386
  adapter.warnAboutNonDevelopmentBundling?.(absolutePath);
1146
1387
  try {
1147
- const analysis = await analyzeSourceGraph(absolutePath, adapter);
1388
+ const analysis = await analyzeSourceGraph(
1389
+ absolutePath,
1390
+ adapter,
1391
+ exportName
1392
+ );
1148
1393
  analysis.graphHash = target === PLAY_ARTIFACT_KINDS.esmWorkers ? buildWorkersRuntimeGraphHash({
1149
1394
  analysis,
1150
1395
  entryFile: absolutePath,
@@ -1216,6 +1461,7 @@ workers-harness:${harnessFingerprint}`
1216
1461
  sourceFiles: analysis.sourceFiles,
1217
1462
  filePath: absolutePath,
1218
1463
  playName: analysis.playName,
1464
+ playDescription: analysis.playDescription,
1219
1465
  packagedFiles: discoveredFiles.files,
1220
1466
  unresolvedFileReferences: discoveredFiles.unresolved,
1221
1467
  importedPlayDependencies: analysis.importedPlayDependencies
@@ -1282,6 +1528,7 @@ workers-harness:${harnessFingerprint}`
1282
1528
  sourceFiles: analysis.sourceFiles,
1283
1529
  filePath: absolutePath,
1284
1530
  playName: analysis.playName,
1531
+ playDescription: analysis.playDescription,
1285
1532
  packagedFiles: discoveredFiles.files,
1286
1533
  unresolvedFileReferences: discoveredFiles.unresolved,
1287
1534
  importedPlayDependencies: analysis.importedPlayDependencies
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deepline",
3
- "version": "0.1.122",
3
+ "version": "0.1.124",
4
4
  "description": "Deepline SDK + CLI — B2B data enrichment powered by durable cloud execution",
5
5
  "license": "MIT",
6
6
  "repository": {