deepline 0.2.69 → 0.2.71

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 CHANGED
@@ -1044,7 +1044,7 @@ var SDK_RELEASE = {
1044
1044
  // 0.2.0 makes Dataset Handles uniformly async-only after 0.1.320 briefly
1045
1045
  // exposed storage-dependent synchronous access. This deliberate minor
1046
1046
  // release keeps lazy paging semantics independent of row residency.
1047
- version: "0.2.69",
1047
+ version: "0.2.71",
1048
1048
  contracts: {
1049
1049
  api: {
1050
1050
  name: "sdk-http-api",
@@ -3983,16 +3983,9 @@ function isPrebuiltPlayDescription(play) {
3983
3983
  return play.origin === "prebuilt" || play.ownerType === "deepline";
3984
3984
  }
3985
3985
  function preferPrebuiltPlayDescriptions(plays) {
3986
- const prebuilt = [];
3987
- const owned = [];
3988
- for (const play of plays) {
3989
- if (isPrebuiltPlayDescription(play)) {
3990
- prebuilt.push(play);
3991
- } else {
3992
- owned.push(play);
3993
- }
3994
- }
3995
- return [...prebuilt, ...owned];
3986
+ return plays.map((play, index) => ({ play, index })).sort(
3987
+ (left, right) => Number(right.play.pinned) - Number(left.play.pinned) || Number(isPrebuiltPlayDescription(right.play)) - Number(isPrebuiltPlayDescription(left.play)) || left.index - right.index
3988
+ ).map(({ play }) => play);
3996
3989
  }
3997
3990
  function isPlayRunPackage(value) {
3998
3991
  return Boolean(
@@ -4339,6 +4332,8 @@ var DeeplineClient = class {
4339
4332
  ...play.reference ? { reference: play.reference } : {},
4340
4333
  ...play.displayName ? { displayName: play.displayName } : {},
4341
4334
  ...description ? { description } : {},
4335
+ pinned: Boolean(play.pinned),
4336
+ toolCategories: play.toolCategories ?? [],
4342
4337
  origin: play.origin,
4343
4338
  ownerType: play.ownerType,
4344
4339
  canEdit: play.canEdit,
@@ -5837,6 +5832,16 @@ var DeeplineClient = class {
5837
5832
  async listPlays(options) {
5838
5833
  const params = new URLSearchParams();
5839
5834
  if (options?.origin) params.set("origin", options.origin);
5835
+ if (options?.categories) {
5836
+ params.set(
5837
+ "categories",
5838
+ Array.isArray(options.categories) ? options.categories.join(",") : options.categories
5839
+ );
5840
+ }
5841
+ if (options?.categories || options?.includeToolCategories) {
5842
+ params.set("include_tool_categories", "1");
5843
+ }
5844
+ if (options?.includeArchived) params.set("include_archived", "1");
5840
5845
  if (options?.grep?.trim()) {
5841
5846
  params.set("grep", options.grep.trim());
5842
5847
  params.set("grep_mode", options.grepMode ?? "all");
@@ -5848,6 +5853,12 @@ var DeeplineClient = class {
5848
5853
  );
5849
5854
  return response.plays ?? [];
5850
5855
  }
5856
+ /** Set whether an org-owned Play sorts before unpinned Plays. */
5857
+ async setPlayPinned(playName, pinned) {
5858
+ return this.http.post(`/api/v2/plays/${encodeURIComponent(playName)}/pin`, {
5859
+ pinned
5860
+ });
5861
+ }
5851
5862
  /** Read product-notification destinations, subscriptions, event catalog, and DLQ health. */
5852
5863
  async getNotificationSettings() {
5853
5864
  return this.http.get("/api/v2/settings/notifications");
@@ -6050,13 +6061,22 @@ var DeeplineClient = class {
6050
6061
  );
6051
6062
  }
6052
6063
  /**
6053
- * Delete an org-owned play definition, including its revisions, trigger
6054
- * bindings, and local run records. Deepline prebuilt plays are read-only.
6064
+ * Move an org-owned play to Trash. This disables its active triggers while
6065
+ * retaining its revisions and run history so it can be restored. Deepline
6066
+ * prebuilt plays are read-only.
6055
6067
  */
6056
6068
  async deletePlay(name) {
6057
6069
  const encodedName = encodeURIComponent(name);
6058
6070
  return this.http.delete(`/api/v2/plays/${encodedName}`);
6059
6071
  }
6072
+ /** Restore an org-owned play that was previously moved to Trash. */
6073
+ async restorePlay(name) {
6074
+ const encodedName = encodeURIComponent(name);
6075
+ return this.http.post(
6076
+ `/api/v2/plays/${encodedName}/restore`,
6077
+ {}
6078
+ );
6079
+ }
6060
6080
  // ——————————————————————————————————————————————————————————
6061
6081
  // Plays — public share pages
6062
6082
  // ——————————————————————————————————————————————————————————
@@ -22839,6 +22859,29 @@ function resolvePlayCheckExportNames(sourceCode) {
22839
22859
  if (!exports2 || exports2.length === 0) return [PLAY_DEFAULT_EXPORT];
22840
22860
  return exports2.map((entry) => entry.name);
22841
22861
  }
22862
+ function artifactForProductionCompatibilityCheck(artifact) {
22863
+ const rawEdition = process.env.DEEPLINE_PROD_CHECK_AUTHORING_CONTRACT_EDITION?.trim();
22864
+ if (!rawEdition) return artifact;
22865
+ if (!/^\d+$/.test(rawEdition)) {
22866
+ throw new Error(
22867
+ "DEEPLINE_PROD_CHECK_AUTHORING_CONTRACT_EDITION must be a positive integer."
22868
+ );
22869
+ }
22870
+ const edition = Number(rawEdition);
22871
+ if (edition < 1) {
22872
+ throw new Error(
22873
+ "DEEPLINE_PROD_CHECK_AUTHORING_CONTRACT_EDITION must be a positive integer."
22874
+ );
22875
+ }
22876
+ const compatibility = isRecord10(artifact.compatibility) ? artifact.compatibility : {};
22877
+ return {
22878
+ ...artifact,
22879
+ compatibility: {
22880
+ ...compatibility,
22881
+ authoringContractEdition: edition
22882
+ }
22883
+ };
22884
+ }
22842
22885
  async function checkOneExportedPlay(input2) {
22843
22886
  const { absolutePlayPath, sourceCode, exportName } = input2;
22844
22887
  const fallbackName = extractPlayName(sourceCode, absolutePlayPath);
@@ -22878,7 +22921,7 @@ async function checkOneExportedPlay(input2) {
22878
22921
  sourceCode: graph.root.sourceCode,
22879
22922
  sourceFiles: graph.root.sourceFiles,
22880
22923
  description: graph.root.playDescription ?? void 0,
22881
- artifact: graph.root.artifact,
22924
+ artifact: artifactForProductionCompatibilityCheck(graph.root.artifact),
22882
22925
  ...exportName === PLAY_DEFAULT_EXPORT ? {} : { exportName },
22883
22926
  ...importedPlays.length > 0 ? { importedPlays } : {},
22884
22927
  ...integrationMode ? { integrationMode } : {}
@@ -24064,7 +24107,12 @@ async function handlePlayVersions(args) {
24064
24107
  async function handlePlayList(args) {
24065
24108
  const jsonOutput = argsWantJson(args);
24066
24109
  const client2 = new DeeplineClient();
24067
- const plays = await client2.listPlays();
24110
+ const categoriesIndex = args.indexOf("--categories");
24111
+ const categories = categoriesIndex >= 0 ? args[categoriesIndex + 1]?.trim() : void 0;
24112
+ const plays = await client2.listPlays({
24113
+ categories,
24114
+ includeToolCategories: true
24115
+ });
24068
24116
  if (jsonOutput) {
24069
24117
  process.stdout.write(`${JSON.stringify(plays)}
24070
24118
  `);
@@ -24075,6 +24123,8 @@ async function handlePlayList(args) {
24075
24123
  `);
24076
24124
  for (const play of plays) {
24077
24125
  const flags = [
24126
+ play.pinned ? "pinned" : null,
24127
+ ...(play.toolCategories ?? []).map((category) => `category:${category}`),
24078
24128
  play.origin === "prebuilt" || play.ownerType === "deepline" ? "prebuilt" : "owned",
24079
24129
  play.canEdit ? "editable" : "readonly",
24080
24130
  play.isDraftDirty ? "draft-dirty" : null
@@ -24104,6 +24154,36 @@ async function handlePlayList(args) {
24104
24154
  }
24105
24155
  return 0;
24106
24156
  }
24157
+ async function handlePlayPin(args, pinned) {
24158
+ const target = args.find((arg) => !arg.startsWith("-"))?.trim();
24159
+ const jsonOutput = argsWantJson(args);
24160
+ const dryRun = args.includes("--dry-run");
24161
+ if (!target) {
24162
+ console.error(
24163
+ `Usage: deepline plays ${pinned ? "pin" : "unpin"} <play> [--dry-run] [--json]`
24164
+ );
24165
+ return 2;
24166
+ }
24167
+ const parsedTarget = parseReferencedPlayTarget2(target);
24168
+ if (parsedTarget.ownerSlug) {
24169
+ console.error(
24170
+ `deepline plays ${pinned ? "pin" : "unpin"} accepts an org-owned Play identifier without a namespace. Use "${parsedTarget.unqualifiedPlayName}" instead of "${target}".`
24171
+ );
24172
+ return 2;
24173
+ }
24174
+ const name = parsedTarget.playName;
24175
+ const plan = { name, pinned, dryRun };
24176
+ if (dryRun) {
24177
+ process.stdout.write(`${JSON.stringify(plan)}
24178
+ `);
24179
+ return 0;
24180
+ }
24181
+ const result = await new DeeplineClient().setPlayPinned(name, pinned);
24182
+ if (jsonOutput) process.stdout.write(`${JSON.stringify(result)}
24183
+ `);
24184
+ else console.log(`${result.pinned ? "Pinned" : "Unpinned"} ${result.name}.`);
24185
+ return 0;
24186
+ }
24107
24187
  function parsePlaySearchOptions(args) {
24108
24188
  const query = args[0]?.trim();
24109
24189
  if (!query) {
@@ -24138,6 +24218,12 @@ function printPlayDescription(play) {
24138
24218
  if (play.description) {
24139
24219
  console.log(` Description: ${play.description}`);
24140
24220
  }
24221
+ if (play.pinned) {
24222
+ console.log(" Pinned: yes");
24223
+ }
24224
+ if (play.toolCategories?.length) {
24225
+ console.log(` Tool categories: ${play.toolCategories.join(", ")}`);
24226
+ }
24141
24227
  if (play.aliases.length > 0) {
24142
24228
  console.log(` Aliases: ${play.aliases.join(", ")}`);
24143
24229
  }
@@ -24243,6 +24329,8 @@ function summarizePlayListItemForCli(play, options) {
24243
24329
  name: play.name,
24244
24330
  ...play.reference ? { reference: play.reference } : {},
24245
24331
  ...play.displayName ? { displayName: play.displayName } : {},
24332
+ pinned: Boolean(play.pinned),
24333
+ toolCategories: play.toolCategories ?? [],
24246
24334
  origin: play.origin,
24247
24335
  ownerType: play.ownerType,
24248
24336
  canEdit: play.canEdit,
@@ -24373,6 +24461,7 @@ async function handlePlayGrep(args) {
24373
24461
  origin: play.origin,
24374
24462
  ownerType: play.ownerType,
24375
24463
  aliases: play.aliases,
24464
+ toolCategories: play.toolCategories,
24376
24465
  inputSchema: play.inputSchema,
24377
24466
  outputSchema: play.outputSchema
24378
24467
  },
@@ -24673,15 +24762,32 @@ async function handlePlayPublish(args) {
24673
24762
  async function handlePlayDelete(args) {
24674
24763
  const playName = args[0];
24675
24764
  if (!playName) {
24676
- console.error("Usage: deepline plays delete <play-name> --yes [--json]");
24677
- return 1;
24765
+ console.error(
24766
+ "Usage: deepline plays delete <play-name> --yes [--dry-run] [--json]"
24767
+ );
24768
+ return 2;
24769
+ }
24770
+ if (looksLikeRunId(playName)) {
24771
+ console.error(
24772
+ formatPlayCommandReceivedRunIdError({
24773
+ command: "delete",
24774
+ runId: playName
24775
+ })
24776
+ );
24777
+ return 2;
24778
+ }
24779
+ if (isFileTarget(playName) || looksLikeFilePath(playName)) {
24780
+ console.error(
24781
+ "Refusing to delete a local file. This command only moves a saved org-owned play to Trash."
24782
+ );
24783
+ return 2;
24678
24784
  }
24679
- const confirmed = args.includes("--yes") || args.includes("-y") || args.includes("--force");
24785
+ const confirmed = args.includes("--yes") || args.includes("-y");
24680
24786
  if (!confirmed) {
24681
24787
  console.error(
24682
- "Refusing to delete without --yes. This deletes the org-owned play, its revisions, trigger bindings, and local run records."
24788
+ "Refusing to move the play to Trash without --yes. This stops active triggers; the play can be restored later."
24683
24789
  );
24684
- return 1;
24790
+ return 2;
24685
24791
  }
24686
24792
  const client2 = new DeeplineClient();
24687
24793
  let detail;
@@ -24689,27 +24795,103 @@ async function handlePlayDelete(args) {
24689
24795
  detail = await client2.getPlay(parseReferencedPlayTarget2(playName).playName);
24690
24796
  } catch (error) {
24691
24797
  console.error(error instanceof Error ? error.message : String(error));
24692
- return 1;
24798
+ return 5;
24693
24799
  }
24694
24800
  if (detail.play.ownerType === "deepline" || detail.play.origin === "prebuilt") {
24695
24801
  console.error(
24696
- `Cannot delete prebuilt play: ${formatPlayReference(detail.play)}`
24802
+ `Cannot move prebuilt play to Trash: ${formatPlayReference(detail.play)}`
24697
24803
  );
24698
- return 1;
24804
+ return 2;
24699
24805
  }
24700
- const result = await client2.deletePlay(
24701
- parseReferencedPlayTarget2(formatPlayReference(detail.play)).playName
24702
- );
24806
+ const resolvedName = parseReferencedPlayTarget2(
24807
+ formatPlayReference(detail.play)
24808
+ ).playName;
24809
+ if (args.includes("--dry-run")) {
24810
+ const result2 = {
24811
+ ok: true,
24812
+ dryRun: true,
24813
+ name: resolvedName,
24814
+ plannedMutation: "move saved org-owned play to Trash and stop triggers"
24815
+ };
24816
+ if (argsWantJson(args)) {
24817
+ process.stdout.write(`${JSON.stringify(result2)}
24818
+ `);
24819
+ } else {
24820
+ process.stdout.write(
24821
+ `Dry run: would move ${result2.name} to Trash and stop its active triggers.
24822
+ `
24823
+ );
24824
+ }
24825
+ return 0;
24826
+ }
24827
+ const result = await client2.deletePlay(resolvedName);
24703
24828
  if (argsWantJson(args)) {
24704
24829
  process.stdout.write(`${JSON.stringify(result)}
24705
24830
  `);
24706
- return result.deleted ? 0 : 1;
24831
+ return result.archived || result.alreadyArchived ? 0 : 4;
24832
+ }
24833
+ if (result.alreadyArchived) {
24834
+ process.stdout.write(`Play ${result.name} is already in Trash.
24835
+ `);
24836
+ return 0;
24837
+ }
24838
+ if (!result.archived) {
24839
+ console.error(`Play not found: ${result.name}`);
24840
+ return 4;
24707
24841
  }
24708
24842
  process.stdout.write(
24709
- `Deleted ${result.name}: revisions=${result.deletedRevisionCount}, bindings=${result.deletedBindingCount}, runs=${result.deletedRunCount}
24843
+ `Moved ${result.name} to Trash: stopped bindings=${result.archivedBindingCount}
24710
24844
  `
24711
24845
  );
24712
- return result.deleted ? 0 : 1;
24846
+ return 0;
24847
+ }
24848
+ async function handlePlayRestore(args) {
24849
+ const playName = args[0];
24850
+ if (!playName) {
24851
+ console.error("Usage: deepline plays restore <play-name> [--json]");
24852
+ return 2;
24853
+ }
24854
+ if (looksLikeRunId(playName)) {
24855
+ console.error(
24856
+ formatPlayCommandReceivedRunIdError({
24857
+ command: "restore",
24858
+ runId: playName
24859
+ })
24860
+ );
24861
+ return 2;
24862
+ }
24863
+ if (isFileTarget(playName) || looksLikeFilePath(playName)) {
24864
+ console.error(
24865
+ "Refusing to restore a local file. This command only restores a saved org-owned play from Trash."
24866
+ );
24867
+ return 2;
24868
+ }
24869
+ const client2 = new DeeplineClient();
24870
+ try {
24871
+ const result = await client2.restorePlay(
24872
+ parseReferencedPlayTarget2(playName).playName
24873
+ );
24874
+ if (argsWantJson(args)) {
24875
+ process.stdout.write(`${JSON.stringify(result)}
24876
+ `);
24877
+ return result.restored || result.alreadyActive ? 0 : 4;
24878
+ }
24879
+ if (result.alreadyActive) {
24880
+ process.stdout.write(`Play ${result.name} is already active.
24881
+ `);
24882
+ return 0;
24883
+ }
24884
+ if (!result.restored) {
24885
+ console.error(`Play not found: ${result.name}`);
24886
+ return 4;
24887
+ }
24888
+ process.stdout.write(`Restored ${result.name} from Trash.
24889
+ `);
24890
+ return 0;
24891
+ } catch (error) {
24892
+ console.error(error instanceof Error ? error.message : String(error));
24893
+ return 5;
24894
+ }
24713
24895
  }
24714
24896
  function registerPlayCommands(program) {
24715
24897
  const play = program.command("plays").description("Search, validate, run, and manage cloud plays.").addHelpText(
@@ -24943,11 +25125,35 @@ Examples:
24943
25125
  deepline plays list
24944
25126
  deepline plays search email --json
24945
25127
  `
24946
- ).option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (options) => {
25128
+ ).option("--json", "Emit JSON output. Also automatic when stdout is piped").option(
25129
+ "--categories <categories>",
25130
+ "Filter by comma-separated canonical tool categories"
25131
+ ).action(async (options) => {
24947
25132
  process.exitCode = await handlePlayList([
25133
+ ...options.categories ? ["--categories", options.categories] : [],
24948
25134
  ...options.json ? ["--json"] : []
24949
25135
  ]);
24950
25136
  });
25137
+ play.command("pin <target>").description("Pin an org-owned play to the top of play listings.").option("--dry-run", "Print the planned change without saving it").option("--json", "Emit JSON output").action(async (target, options) => {
25138
+ process.exitCode = await handlePlayPin(
25139
+ [
25140
+ target,
25141
+ ...options.dryRun ? ["--dry-run"] : [],
25142
+ ...options.json ? ["--json"] : []
25143
+ ],
25144
+ true
25145
+ );
25146
+ });
25147
+ play.command("unpin <target>").description("Remove an org-owned play from the pinned group.").option("--dry-run", "Print the planned change without saving it").option("--json", "Emit JSON output").action(async (target, options) => {
25148
+ process.exitCode = await handlePlayPin(
25149
+ [
25150
+ target,
25151
+ ...options.dryRun ? ["--dry-run"] : [],
25152
+ ...options.json ? ["--json"] : []
25153
+ ],
25154
+ false
25155
+ );
25156
+ });
24951
25157
  const addPlaySearchCommand = (command) => command.description("Search Deepline prebuilt plays by task.").option(
24952
25158
  "--prebuilt",
24953
25159
  "Only show Deepline-managed prebuilt plays (default)"
@@ -25094,21 +25300,40 @@ Examples:
25094
25300
  ...options.json ? ["--json"] : []
25095
25301
  ]);
25096
25302
  });
25097
- play.command("delete <target>").description("Delete an org-owned play and its saved revisions/runs.").addHelpText(
25303
+ play.command("delete <target>").description("Move an org-owned play to Trash and stop its triggers.").addHelpText(
25098
25304
  "after",
25099
25305
  `
25100
25306
  Notes:
25101
- Destructive mutation. Deletes an org-owned play plus saved revisions and run
25102
- records. Prebuilt/read-only plays are refused. Use --yes for noninteractive runs.
25307
+ Soft delete. Moves an org-owned play to Trash and stops active triggers while
25308
+ retaining revisions and run history. Prebuilt/read-only plays are refused.
25309
+ Use --yes for noninteractive runs. Restore later with \`plays restore\`.
25103
25310
 
25104
25311
  Examples:
25105
- deepline plays delete my-play
25312
+ deepline plays delete my-play --yes
25106
25313
  deepline plays delete my-play --yes --json
25314
+ deepline plays delete my-play --yes --dry-run --json
25107
25315
  `
25108
- ).option("-y, --yes", "Confirm deletion").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (target, options) => {
25316
+ ).option("-y, --yes", "Confirm deletion").option("--dry-run", "Show the planned archive without mutating the play").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (target, options) => {
25109
25317
  process.exitCode = await handlePlayDelete([
25110
25318
  target,
25111
25319
  ...options.yes ? ["--yes"] : [],
25320
+ ...options.dryRun ? ["--dry-run"] : [],
25321
+ ...options.json ? ["--json"] : []
25322
+ ]);
25323
+ });
25324
+ play.command("restore <target>").description("Restore an org-owned play from Trash.").addHelpText(
25325
+ "after",
25326
+ `
25327
+ Notes:
25328
+ Restoring re-enables the saved play and recreates its trigger bindings.
25329
+
25330
+ Examples:
25331
+ deepline plays restore my-play
25332
+ deepline plays restore my-play --json
25333
+ `
25334
+ ).option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (target, options) => {
25335
+ process.exitCode = await handlePlayRestore([
25336
+ target,
25112
25337
  ...options.json ? ["--json"] : []
25113
25338
  ]);
25114
25339
  });
@@ -26283,10 +26508,12 @@ function compileEnrichConfigToPlaySource(config, options = {}) {
26283
26508
  const metadataColumnSource = renderMetadataColumnStep(config);
26284
26509
  const generatedAliases = collectGeneratedAliases(config.commands);
26285
26510
  const runOptionsSource = options.failFast ? `{ key: (row, index) => __dlEnrichRowKey(row, index + rowStart), onRowError: 'fail' as const }` : `{ key: (row, index) => __dlEnrichRowKey(row, index + rowStart) }`;
26511
+ const describedColumns = config.commands.filter((command) => isWaterfall(command) || !command.disabled).map(
26512
+ (command) => (isWaterfall(command) ? command.with_waterfall : command.alias).replace(/[_-]+/g, " ").trim()
26513
+ ).filter(Boolean).slice(0, 3);
26514
+ const generatedDescription = describedColumns.length ? `Enrich CSV rows with ${describedColumns.join(", ")}.` : "Prepare CSV rows for enrichment.";
26286
26515
  const playOptionsSource = [
26287
- `description: ${stringLiteral(
26288
- "Read a CSV file, run the configured Deepline enrich commands, and return enriched rows."
26289
- )}`,
26516
+ `description: ${stringLiteral(generatedDescription)}`,
26290
26517
  ...options.maxCreditsPerRun === void 0 ? [] : [`billing: { maxCreditsPerRun: ${String(options.maxCreditsPerRun)} }`]
26291
26518
  ].join(", ");
26292
26519
  const body = [