deepline 0.1.56 → 0.1.58

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.
@@ -197,10 +197,10 @@ function resolveConfig(options) {
197
197
 
198
198
  // src/release.ts
199
199
  var SDK_RELEASE = {
200
- version: "0.1.56",
200
+ version: "0.1.58",
201
201
  apiContract: "2026-05-play-tool-describe-starters",
202
202
  supportPolicy: {
203
- latest: "0.1.56",
203
+ latest: "0.1.58",
204
204
  minimumSupported: "0.1.53",
205
205
  deprecatedBelow: "0.1.53"
206
206
  }
@@ -338,8 +338,8 @@ var HttpClient = class {
338
338
  if (lastError instanceof DeeplineError) {
339
339
  throw lastError;
340
340
  }
341
- const errorMessage = lastError?.message ? `Unable to connect to ${baseUrl}. ${lastError.message}` : `Unable to connect to ${baseUrl}. Is the computer able to access the url?`;
342
- throw new DeeplineError(errorMessage);
341
+ const errorMessage2 = lastError?.message ? `Unable to connect to ${baseUrl}. ${lastError.message}` : `Unable to connect to ${baseUrl}. Is the computer able to access the url?`;
342
+ throw new DeeplineError(errorMessage2);
343
343
  }
344
344
  /**
345
345
  * Send a GET request.
@@ -512,7 +512,7 @@ function decodeSseFrame(frame) {
512
512
  return parsed;
513
513
  }
514
514
  function sleep(ms) {
515
- return new Promise((resolve11) => setTimeout(resolve11, ms));
515
+ return new Promise((resolve12) => setTimeout(resolve12, ms));
516
516
  }
517
517
 
518
518
  // src/client.ts
@@ -522,7 +522,7 @@ var EXECUTE_RESPONSE_CONTRACT_HEADER = "x-deepline-execute-response-contract";
522
522
  var V2_EXECUTE_RESPONSE_CONTRACT = "v2-tool-response";
523
523
  var COMPILE_MANIFEST_RETRY_DELAYS_MS = [250, 1e3];
524
524
  function sleep2(ms) {
525
- return new Promise((resolve11) => setTimeout(resolve11, ms));
525
+ return new Promise((resolve12) => setTimeout(resolve12, ms));
526
526
  }
527
527
  function isTransientCompileManifestError(error) {
528
528
  if (error instanceof DeeplineError && typeof error.statusCode === "number") {
@@ -2258,7 +2258,7 @@ function buildCandidateUrls2(url) {
2258
2258
  }
2259
2259
  }
2260
2260
  function sleep3(ms) {
2261
- return new Promise((resolve11) => setTimeout(resolve11, ms));
2261
+ return new Promise((resolve12) => setTimeout(resolve12, ms));
2262
2262
  }
2263
2263
  function printDeeplineLogo() {
2264
2264
  if (process.stdout.isTTY && (process.stdout.columns ?? 80) >= 70) {
@@ -4014,7 +4014,7 @@ import {
4014
4014
  realpathSync,
4015
4015
  writeFileSync as writeFileSync6
4016
4016
  } from "fs";
4017
- import { basename as basename3, dirname as dirname8, join as join6, resolve as resolve9 } from "path";
4017
+ import { basename as basename3, dirname as dirname8, join as join6, resolve as resolve10 } from "path";
4018
4018
 
4019
4019
  // src/plays/bundle-play-file.ts
4020
4020
  import { tmpdir as tmpdir2 } from "os";
@@ -4374,6 +4374,9 @@ function localSdkAliasPlugin(adapter, options) {
4374
4374
  buildContext.onResolve({ filter: /^deepline$/ }, () => ({
4375
4375
  path: entryFile
4376
4376
  }));
4377
+ buildContext.onResolve({ filter: /^deepline\/helpers$/ }, () => ({
4378
+ path: join3(adapter.sdkSourceRoot, "helpers.ts")
4379
+ }));
4377
4380
  }
4378
4381
  };
4379
4382
  }
@@ -5550,37 +5553,1474 @@ function warnAboutNonDevelopmentBundling(filePath) {
5550
5553
  console.warn(
5551
5554
  `[deepline] Warning: live play bundling was invoked while NODE_ENV=${nodeEnv} for ${filePath}. This source-first SDK path is intended for local development. For preview/production, run a published or prebuilt play reference instead of bundling source at runtime.`
5552
5555
  );
5553
- console.warn(
5554
- '[deepline] Preferred production call pattern: client.play("person-to-email").run(...) or run a previously registered/published org play.'
5556
+ console.warn(
5557
+ '[deepline] Preferred production call pattern: client.play("person-to-email").run(...) or run a previously registered/published org play.'
5558
+ );
5559
+ }
5560
+ function defaultPlayBundleTarget() {
5561
+ return resolveExecutionProfile(null).artifactKind;
5562
+ }
5563
+ function createSdkPlayBundlingAdapter() {
5564
+ return {
5565
+ projectRoot: PROJECT_ROOT,
5566
+ nodeModulesDir: resolve8(PROJECT_ROOT, "node_modules"),
5567
+ cacheDir: join5(
5568
+ tmpdir2(),
5569
+ `deepline-play-artifacts-v${PLAY_BUNDLE_CACHE_VERSION2}`
5570
+ ),
5571
+ sdkSourceRoot: SDK_SOURCE_ROOT,
5572
+ sdkPackageJson: SDK_PACKAGE_JSON,
5573
+ sdkEntryFile: SDK_ENTRY_FILE,
5574
+ sdkTypesEntryFile: HAS_SOURCE_BUNDLING_SOURCES || !existsSync5(SDK_TYPES_ENTRY_FILE) ? SDK_ENTRY_FILE : SDK_TYPES_ENTRY_FILE,
5575
+ sdkWorkersEntryFile: SDK_WORKERS_ENTRY_FILE,
5576
+ workersHarnessEntryFile: WORKERS_HARNESS_ENTRY_FILE,
5577
+ workersHarnessFilesDir: WORKERS_HARNESS_FILES_DIR,
5578
+ discoverPackagedLocalFiles,
5579
+ warnAboutNonDevelopmentBundling
5580
+ };
5581
+ }
5582
+ async function bundlePlayFile2(filePath, options = {}) {
5583
+ return bundlePlayFile(filePath, {
5584
+ target: options.target ?? defaultPlayBundleTarget(),
5585
+ exportName: options.exportName,
5586
+ adapter: createSdkPlayBundlingAdapter()
5587
+ });
5588
+ }
5589
+
5590
+ // src/cli/commands/plays/bootstrap.ts
5591
+ import { closeSync, openSync, readSync, statSync } from "fs";
5592
+ import { isAbsolute as isAbsolute3, relative as relative2, resolve as resolve9 } from "path";
5593
+ import { parse as parseCsvSync } from "csv-parse/sync";
5594
+
5595
+ // ../shared_libs/plays/bootstrap-routes.ts
5596
+ var PLAY_BOOTSTRAP_TEMPLATES = [
5597
+ "people-list",
5598
+ "company-list",
5599
+ "people-email",
5600
+ "people-phone",
5601
+ "company-people",
5602
+ "company-people-email",
5603
+ "company-people-phone"
5604
+ ];
5605
+ var PLAY_BOOTSTRAP_COMPANY_PROVIDER_CATEGORY = "company_search";
5606
+ var PLAY_BOOTSTRAP_PEOPLE_PROVIDER_CATEGORY = "people_search";
5607
+ var PLAY_BOOTSTRAP_PROVIDER_CATEGORY_BY_FINDER = {
5608
+ email_finder: "email_finder",
5609
+ phone_finder: "phone_finder"
5610
+ };
5611
+ var PLAY_BOOTSTRAP_OUTPUT_FIELD_BY_FINDER = {
5612
+ email_finder: "email",
5613
+ phone_finder: "phone"
5614
+ };
5615
+ function isPlayBootstrapTemplate(value) {
5616
+ return PLAY_BOOTSTRAP_TEMPLATES.includes(value);
5617
+ }
5618
+ function formatPlayBootstrapTemplates() {
5619
+ return PLAY_BOOTSTRAP_TEMPLATES.join("|");
5620
+ }
5621
+
5622
+ // src/cli/commands/plays/bootstrap.ts
5623
+ function parseReferencedPlayTarget(target) {
5624
+ const trimmed = target.trim();
5625
+ const slashIndex = trimmed.indexOf("/");
5626
+ if (slashIndex <= 0 || slashIndex === trimmed.length - 1) {
5627
+ return { ownerSlug: null, playName: trimmed, unqualifiedPlayName: trimmed };
5628
+ }
5629
+ return {
5630
+ ownerSlug: trimmed.slice(0, slashIndex),
5631
+ playName: trimmed,
5632
+ unqualifiedPlayName: trimmed.slice(slashIndex + 1)
5633
+ };
5634
+ }
5635
+ function parsePositiveInteger2(value, flagName) {
5636
+ const parsed = Number.parseInt(value, 10);
5637
+ if (!Number.isFinite(parsed) || parsed <= 0) {
5638
+ throw new PlayBootstrapUsageError(
5639
+ `${flagName} must be a positive integer.`
5640
+ );
5641
+ }
5642
+ return parsed;
5643
+ }
5644
+ function isRecord3(value) {
5645
+ return Boolean(value && typeof value === "object" && !Array.isArray(value));
5646
+ }
5647
+ function stringValue(value) {
5648
+ return typeof value === "string" ? value.trim() : "";
5649
+ }
5650
+ function extractionEntries(value) {
5651
+ if (Array.isArray(value)) return value.filter(isRecord3);
5652
+ if (!isRecord3(value)) return [];
5653
+ return Object.entries(value).map(
5654
+ ([name, entry]) => isRecord3(entry) ? { name, ...entry } : { name }
5655
+ );
5656
+ }
5657
+ var PlayBootstrapError = class extends Error {
5658
+ constructor(message, exitCode) {
5659
+ super(message);
5660
+ this.exitCode = exitCode;
5661
+ }
5662
+ exitCode;
5663
+ };
5664
+ var PlayBootstrapUsageError = class extends PlayBootstrapError {
5665
+ constructor(message) {
5666
+ super(message, 2);
5667
+ }
5668
+ };
5669
+ var PlayBootstrapValidationError = class extends PlayBootstrapError {
5670
+ constructor(message) {
5671
+ super(message, 7);
5672
+ }
5673
+ };
5674
+ var CSV_HEADER_SAMPLE_BYTES = 64 * 1024;
5675
+ function parseCsvList(value) {
5676
+ return value.split(",").map((item) => item.trim()).filter(Boolean);
5677
+ }
5678
+ function parseProviderList(value, flag) {
5679
+ const providers = parseCsvList(value);
5680
+ if (providers.length === 0) {
5681
+ throw new PlayBootstrapUsageError(`${flag} provider list cannot be empty.`);
5682
+ }
5683
+ return providers;
5684
+ }
5685
+ function parseBootstrapPrefixedRef(value, flag) {
5686
+ const separatorIndex = value.indexOf(":");
5687
+ if (separatorIndex <= 0 || separatorIndex === value.length - 1) {
5688
+ throw new PlayBootstrapUsageError(
5689
+ `${flag} expects a typed resource reference like csv:data/leads.csv, play:prebuilt/name-and-domain-to-email-waterfall, provider:dropleads_search_people, or providers:hunter_email_finder,leadmagic_email_finder.`
5690
+ );
5691
+ }
5692
+ return {
5693
+ prefix: value.slice(0, separatorIndex).trim(),
5694
+ body: value.slice(separatorIndex + 1).trim()
5695
+ };
5696
+ }
5697
+ function parseBootstrapSourceRef(value, flag = "--from") {
5698
+ const { prefix, body } = parseBootstrapPrefixedRef(value, flag);
5699
+ switch (prefix) {
5700
+ case "csv":
5701
+ return { kind: "csv", value: body };
5702
+ case "play":
5703
+ return { kind: "play", value: parseReferencedPlayTarget(body).playName };
5704
+ case "provider":
5705
+ case "providers":
5706
+ return { kind: "providers", values: parseProviderList(body, flag) };
5707
+ }
5708
+ throw new PlayBootstrapUsageError(
5709
+ `${flag} does not support ${prefix}:. Use csv:, play:, provider:, or providers:.`
5710
+ );
5711
+ }
5712
+ function parseBootstrapStageRef(value, flag) {
5713
+ const { prefix, body } = parseBootstrapPrefixedRef(value, flag);
5714
+ switch (prefix) {
5715
+ case "play":
5716
+ return { kind: "play", value: parseReferencedPlayTarget(body).playName };
5717
+ case "provider":
5718
+ case "providers":
5719
+ return { kind: "providers", values: parseProviderList(body, flag) };
5720
+ }
5721
+ throw new PlayBootstrapUsageError(
5722
+ `${flag} does not support ${prefix}:. Use play:, provider:, or providers:.`
5723
+ );
5724
+ }
5725
+ function playBootstrapTemplateConfig(template) {
5726
+ switch (template) {
5727
+ case "company-list":
5728
+ return { sourceEntity: "company", usingStage: null, requiredStages: [] };
5729
+ case "people-list":
5730
+ return { sourceEntity: "people", usingStage: null, requiredStages: [] };
5731
+ case "people-email":
5732
+ return {
5733
+ sourceEntity: "people",
5734
+ usingStage: "email",
5735
+ requiredStages: []
5736
+ };
5737
+ case "people-phone":
5738
+ return {
5739
+ sourceEntity: "people",
5740
+ usingStage: "phone",
5741
+ requiredStages: []
5742
+ };
5743
+ case "company-people":
5744
+ return {
5745
+ sourceEntity: "company",
5746
+ usingStage: "people",
5747
+ requiredStages: []
5748
+ };
5749
+ case "company-people-email":
5750
+ return {
5751
+ sourceEntity: "company",
5752
+ usingStage: null,
5753
+ requiredStages: ["people", "email"]
5754
+ };
5755
+ case "company-people-phone":
5756
+ return {
5757
+ sourceEntity: "company",
5758
+ usingStage: null,
5759
+ requiredStages: ["people", "phone"]
5760
+ };
5761
+ }
5762
+ }
5763
+ function templateExample(template) {
5764
+ switch (template) {
5765
+ case "people-list":
5766
+ return "deepline plays bootstrap people-list --from provider:dropleads_search_people > people.play.ts";
5767
+ case "company-list":
5768
+ return "deepline plays bootstrap company-list --from provider:apollo_company_search > companies.play.ts";
5769
+ case "people-email":
5770
+ return "deepline plays bootstrap people-email --from csv:data/leads.csv --using play:prebuilt/name-and-domain-to-email-waterfall > email-flow.play.ts";
5771
+ case "people-phone":
5772
+ return "deepline plays bootstrap people-phone --from csv:data/vp_contacts.csv --using play:prebuilt/person-to-phone > phone-flow.play.ts";
5773
+ case "company-people":
5774
+ return "deepline plays bootstrap company-people --from provider:apollo_company_search --using play:prebuilt/company-to-contact > company-people.play.ts";
5775
+ case "company-people-email":
5776
+ return "deepline plays bootstrap company-people-email --from provider:apollo_company_search --people play:prebuilt/company-to-contact --email providers:hunter_email_finder,leadmagic_email_finder > account-emails.play.ts";
5777
+ case "company-people-phone":
5778
+ return "deepline plays bootstrap company-people-phone --from provider:apollo_company_search --people play:prebuilt/company-to-contact --phone providers:ai_ark_mobile_phone_finder > account-phones.play.ts";
5779
+ }
5780
+ }
5781
+ var PLAY_BOOTSTRAP_STAGE_NAMES = [
5782
+ "people",
5783
+ "email",
5784
+ "phone"
5785
+ ];
5786
+ function playBootstrapUsageLine() {
5787
+ return `Usage: deepline plays bootstrap <${formatPlayBootstrapTemplates()}> --from <csv:PATH|play:REF|provider:ID|providers:ID,ID> [--using <play:REF|providers:ID,ID>] [--people play:REF] [--email <play:REF|providers:ID,ID>] [--phone <play:REF|providers:ID,ID>] [--limit 5] > flow.play.ts`;
5788
+ }
5789
+ function requireBootstrapTemplate(rawTemplate) {
5790
+ if (!rawTemplate) {
5791
+ throw new PlayBootstrapUsageError(
5792
+ `plays bootstrap needs a route template: ${formatPlayBootstrapTemplates()}.
5793
+ Example: deepline plays bootstrap people-email --from csv:data/leads.csv --using play:prebuilt/name-and-domain-to-email-waterfall > email-flow.play.ts`
5794
+ );
5795
+ }
5796
+ if (!isPlayBootstrapTemplate(rawTemplate)) {
5797
+ throw new PlayBootstrapUsageError(
5798
+ `Unknown plays bootstrap template: ${rawTemplate}
5799
+ Supported templates: ${formatPlayBootstrapTemplates()}`
5800
+ );
5801
+ }
5802
+ return rawTemplate;
5803
+ }
5804
+ function nextFlagValue(args, index, flag) {
5805
+ const value = args[index + 1];
5806
+ if (!value || value.startsWith("--")) {
5807
+ throw new PlayBootstrapUsageError(`${flag} needs a value.`);
5808
+ }
5809
+ return value;
5810
+ }
5811
+ function stageFlag(stage) {
5812
+ return `--${stage}`;
5813
+ }
5814
+ function stageRefHelp(stage) {
5815
+ switch (stage) {
5816
+ case "people":
5817
+ return "play:<people-play>";
5818
+ case "email":
5819
+ case "phone":
5820
+ return "<play:REF|provider:ID|providers:ID,ID>";
5821
+ }
5822
+ }
5823
+ function getStageRef(options, stage) {
5824
+ switch (stage) {
5825
+ case "people":
5826
+ return options.people;
5827
+ case "email":
5828
+ return options.email;
5829
+ case "phone":
5830
+ return options.phone;
5831
+ }
5832
+ }
5833
+ function setStageRef(options, stage, ref) {
5834
+ switch (stage) {
5835
+ case "people":
5836
+ options.people = ref;
5837
+ return;
5838
+ case "email":
5839
+ options.email = ref;
5840
+ return;
5841
+ case "phone":
5842
+ options.phone = ref;
5843
+ return;
5844
+ }
5845
+ }
5846
+ function unsupportedStageMessage(template, stage) {
5847
+ switch (stage) {
5848
+ case "people":
5849
+ return `${template} does not accept --people. Use company-people, company-people-email, or company-people-phone.`;
5850
+ case "email":
5851
+ return `${template} does not accept --email. Use people-email or company-people-email.`;
5852
+ case "phone":
5853
+ return `${template} does not accept --phone. Use people-phone or company-people-phone.`;
5854
+ }
5855
+ }
5856
+ function requireSource(options) {
5857
+ if (!options.from) {
5858
+ throw new PlayBootstrapUsageError(
5859
+ `${options.template} needs --from.
5860
+ Example: ${templateExample(options.template)}`
5861
+ );
5862
+ }
5863
+ return options.from;
5864
+ }
5865
+ function assertAllowedStageFlags(options, allowedStages) {
5866
+ const allowed = new Set(allowedStages);
5867
+ for (const stage of PLAY_BOOTSTRAP_STAGE_NAMES) {
5868
+ if (!allowed.has(stage) && getStageRef(options, stage)) {
5869
+ throw new PlayBootstrapUsageError(
5870
+ unsupportedStageMessage(options.template, stage)
5871
+ );
5872
+ }
5873
+ }
5874
+ }
5875
+ function assertRequiredStages(options, stages) {
5876
+ for (const stage of stages) {
5877
+ if (!getStageRef(options, stage)) {
5878
+ throw new PlayBootstrapUsageError(
5879
+ `${options.template} needs ${stageFlag(stage)} ${stageRefHelp(stage)}.
5880
+ Example: ${templateExample(options.template)}`
5881
+ );
5882
+ }
5883
+ }
5884
+ }
5885
+ function normalizeSingleStageRoute(options, stage) {
5886
+ const explicitStage = getStageRef(options, stage);
5887
+ if (options.using && explicitStage) {
5888
+ throw new PlayBootstrapUsageError(
5889
+ `${options.template} received both --using and ${stageFlag(stage)}. Choose one stage binding.`
5890
+ );
5891
+ }
5892
+ const selectedStage = options.using ?? explicitStage;
5893
+ if (!selectedStage) {
5894
+ throw new PlayBootstrapUsageError(
5895
+ `${options.template} needs --using ${stageRefHelp(stage)} or ${stageFlag(stage)} ${stageRefHelp(stage)}.
5896
+ Example: ${templateExample(options.template)}`
5897
+ );
5898
+ }
5899
+ setStageRef(options, stage, selectedStage);
5900
+ options.using = selectedStage;
5901
+ assertAllowedStageFlags(options, [stage]);
5902
+ }
5903
+ function normalizeMultiStageRoute(options, stages) {
5904
+ if (options.using) {
5905
+ throw new PlayBootstrapUsageError(
5906
+ `${options.template} does not accept --using. Use the explicit stage flags shown in: ${templateExample(options.template)}`
5907
+ );
5908
+ }
5909
+ assertRequiredStages(options, stages);
5910
+ assertAllowedStageFlags(options, stages);
5911
+ }
5912
+ function normalizeTemplateStages(options) {
5913
+ const config = playBootstrapTemplateConfig(options.template);
5914
+ const from = requireSource(options);
5915
+ switch (config.usingStage) {
5916
+ case "people":
5917
+ case "email":
5918
+ case "phone":
5919
+ normalizeSingleStageRoute(options, config.usingStage);
5920
+ break;
5921
+ case null:
5922
+ normalizeMultiStageRoute(options, config.requiredStages);
5923
+ break;
5924
+ }
5925
+ return {
5926
+ ...options,
5927
+ from
5928
+ };
5929
+ }
5930
+ function parsePlayBootstrapOptions(args) {
5931
+ const [rawTemplate, ...rest] = args;
5932
+ const template = requireBootstrapTemplate(rawTemplate);
5933
+ const options = {
5934
+ template,
5935
+ name: `gtm-${template}`,
5936
+ from: null,
5937
+ using: null,
5938
+ people: null,
5939
+ email: null,
5940
+ phone: null,
5941
+ limit: 5
5942
+ };
5943
+ for (let index = 0; index < rest.length; index += 1) {
5944
+ const arg = rest[index];
5945
+ const value = () => nextFlagValue(rest, index, arg);
5946
+ switch (arg) {
5947
+ case "--name":
5948
+ options.name = value();
5949
+ index += 1;
5950
+ break;
5951
+ case "--from":
5952
+ options.from = parseBootstrapSourceRef(value(), "--from");
5953
+ index += 1;
5954
+ break;
5955
+ case "--using":
5956
+ options.using = parseBootstrapStageRef(value(), "--using");
5957
+ index += 1;
5958
+ break;
5959
+ case "--people":
5960
+ options.people = parseBootstrapStageRef(value(), "--people");
5961
+ index += 1;
5962
+ break;
5963
+ case "--email":
5964
+ options.email = parseBootstrapStageRef(value(), "--email");
5965
+ index += 1;
5966
+ break;
5967
+ case "--phone":
5968
+ options.phone = parseBootstrapStageRef(value(), "--phone");
5969
+ index += 1;
5970
+ break;
5971
+ case "--limit":
5972
+ options.limit = parsePositiveInteger2(value(), "--limit");
5973
+ index += 1;
5974
+ break;
5975
+ default:
5976
+ throw new PlayBootstrapUsageError(
5977
+ `Unknown plays bootstrap option: ${arg}
5978
+ ${playBootstrapUsageLine()}`
5979
+ );
5980
+ }
5981
+ }
5982
+ return normalizeTemplateStages(options);
5983
+ }
5984
+ function jsString(value) {
5985
+ return JSON.stringify(value);
5986
+ }
5987
+ function inferCsvCellTypeExpression(values) {
5988
+ const nonEmptyValues = values.map((value) => value.trim()).filter((value) => value.length > 0);
5989
+ const hasEmptyValue = values.some((value) => value.trim().length === 0);
5990
+ if (nonEmptyValues.length === 0) return "string";
5991
+ const numericPattern = /^[+-]?(?:(?:\d+\.?\d*)|(?:\.\d+))(?:[eE][+-]?\d+)?$/;
5992
+ const booleanPattern = /^(?:true|false)$/i;
5993
+ let inferred = "string";
5994
+ if (nonEmptyValues.every((value) => numericPattern.test(value))) {
5995
+ inferred = "`${number}`";
5996
+ } else if (nonEmptyValues.every((value) => booleanPattern.test(value))) {
5997
+ const canonicalBooleanValues = nonEmptyValues.every(
5998
+ (value) => value === "true" || value === "false"
5999
+ );
6000
+ inferred = canonicalBooleanValues ? '"false" | "true"' : [...new Set(nonEmptyValues)].sort().map(jsString).join(" | ");
6001
+ }
6002
+ return hasEmptyValue && inferred !== "string" ? `${inferred} | ""` : inferred;
6003
+ }
6004
+ function inferCsvColumnSpecs(headers, rows) {
6005
+ return headers.map((header) => ({
6006
+ name: header,
6007
+ typeExpression: inferCsvCellTypeExpression(
6008
+ rows.map((row) => String(row[header] ?? ""))
6009
+ )
6010
+ }));
6011
+ }
6012
+ function readCsvSample(csvPath) {
6013
+ const resolvedPath = resolve9(csvPath);
6014
+ const size = statSync(resolvedPath).size;
6015
+ const fd = openSync(resolvedPath, "r");
6016
+ const byteLength = Math.min(size, CSV_HEADER_SAMPLE_BYTES);
6017
+ const buffer = Buffer.alloc(byteLength);
6018
+ const bytesRead = readSync(fd, buffer, 0, byteLength, 0);
6019
+ closeSync(fd);
6020
+ if (bytesRead === 0) {
6021
+ throw new PlayBootstrapUsageError(`--from csv:${csvPath} is empty.`);
6022
+ }
6023
+ return {
6024
+ content: buffer.subarray(0, bytesRead).toString("utf8"),
6025
+ truncated: size > bytesRead
6026
+ };
6027
+ }
6028
+ function completeCsvSample(csvPath, sample) {
6029
+ if (!sample.truncated) return sample.content;
6030
+ const lastLineBreak = Math.max(
6031
+ sample.content.lastIndexOf("\n"),
6032
+ sample.content.lastIndexOf("\r")
6033
+ );
6034
+ if (lastLineBreak < 0) {
6035
+ throw new PlayBootstrapUsageError(
6036
+ `CSV header in ${csvPath} is longer than ${CSV_HEADER_SAMPLE_BYTES} bytes; shorten the header row before bootstrapping.`
6037
+ );
6038
+ }
6039
+ return sample.content.slice(0, lastLineBreak + 1);
6040
+ }
6041
+ function readCsvHeaderFields(csvPath, sample) {
6042
+ const records = parseCsvSync(sample, {
6043
+ bom: true,
6044
+ to_line: 1,
6045
+ relax_column_count: true,
6046
+ skip_empty_lines: false
6047
+ });
6048
+ const firstRecord = Array.isArray(records) ? records[0] : null;
6049
+ const fields = Array.isArray(firstRecord) ? firstRecord.map((field) => String(field ?? "").trim()).filter(Boolean) : [];
6050
+ const uniqueFields = [...new Set(fields)];
6051
+ if (uniqueFields.length === 0) {
6052
+ throw new PlayBootstrapUsageError(
6053
+ `Could not read a header row from --from csv:${csvPath}.`
6054
+ );
6055
+ }
6056
+ return uniqueFields;
6057
+ }
6058
+ function readCsvSampleRows(sample) {
6059
+ const parsedRows = parseCsvSync(sample, {
6060
+ bom: true,
6061
+ columns: true,
6062
+ skip_empty_lines: true,
6063
+ relax_column_count: true,
6064
+ trim: true
6065
+ });
6066
+ return Array.isArray(parsedRows) ? parsedRows.filter(isRecord3) : [];
6067
+ }
6068
+ function readSourceCsvColumnSpecs(csvPath) {
6069
+ const sample = readCsvSample(csvPath);
6070
+ const completeSample = completeCsvSample(csvPath, sample);
6071
+ return inferCsvColumnSpecs(
6072
+ readCsvHeaderFields(csvPath, sample.content),
6073
+ readCsvSampleRows(completeSample)
6074
+ );
6075
+ }
6076
+ function renderSourceCsvRowType(columns) {
6077
+ if (columns.length === 0) return "";
6078
+ const properties = columns.map((column) => ` ${jsString(column.name)}: ${column.typeExpression};`).join("\n");
6079
+ return `// CSV cells are strings at runtime. \`${"${number}"}\` means a numeric-looking CSV string; cast before math.
6080
+ type SourceCsvRow = {
6081
+ ${properties}
6082
+ };
6083
+
6084
+ `;
6085
+ }
6086
+ function packagedCsvPathForPlay(csvPath) {
6087
+ const playDir = process.cwd();
6088
+ const absoluteCsvPath = resolve9(csvPath);
6089
+ const relativePath = relative2(playDir, absoluteCsvPath);
6090
+ if (relativePath === "" || relativePath.startsWith("..") || isAbsolute3(relativePath)) {
6091
+ throw new PlayBootstrapUsageError(
6092
+ `--from csv:${csvPath} must point to a file inside the directory where you run plays bootstrap. Run bootstrap from the intended play directory, then redirect stdout to a .play.ts file there.`
6093
+ );
6094
+ }
6095
+ const portablePath = relativePath.split("\\").join("/");
6096
+ return portablePath.startsWith(".") ? portablePath : `./${portablePath}`;
6097
+ }
6098
+ function getterNamesFromTool(tool, kind) {
6099
+ const usageGuidance = isRecord3(tool?.usageGuidance) ? tool.usageGuidance : {};
6100
+ const resultGuidance = isRecord3(usageGuidance.toolExecutionResult) ? usageGuidance.toolExecutionResult : isRecord3(usageGuidance.tool_execution_result) ? usageGuidance.tool_execution_result : {};
6101
+ const key = kind === "list" ? "extractedLists" : "extractedValues";
6102
+ const snakeKey = kind === "list" ? "extracted_lists" : "extracted_values";
6103
+ return extractionEntries(resultGuidance[key] ?? resultGuidance[snakeKey]).map((entry) => stringValue(entry.name)).filter(Boolean);
6104
+ }
6105
+ function targetGettersFromTool(tool) {
6106
+ const record = isRecord3(tool) ? tool : {};
6107
+ const raw = record.targetGetters ?? record.target_getters;
6108
+ if (!isRecord3(raw)) return {};
6109
+ const entries = [];
6110
+ for (const [target, value] of Object.entries(raw)) {
6111
+ const paths = Array.isArray(value) ? value.map((path) => typeof path === "string" ? path.trim() : "").filter(Boolean) : [];
6112
+ if (target.trim() && paths.length > 0) {
6113
+ entries.push([target.trim(), paths]);
6114
+ }
6115
+ }
6116
+ return Object.fromEntries(entries);
6117
+ }
6118
+ function listRowCandidateKeysFromTool(tool) {
6119
+ const keys = /* @__PURE__ */ new Set();
6120
+ for (const paths of Object.values(targetGettersFromTool(tool))) {
6121
+ for (const path of paths) {
6122
+ const key = path.replace(/\[(?:\*|\d+)\]/g, "").split(/[.[\]]/, 1)[0]?.trim();
6123
+ if (key) keys.add(key);
6124
+ }
6125
+ }
6126
+ return [...keys].sort();
6127
+ }
6128
+ function inputPropertyNames(schema) {
6129
+ if (!isRecord3(schema)) return [];
6130
+ if (isRecord3(schema.properties)) return Object.keys(schema.properties);
6131
+ if (Array.isArray(schema.fields)) {
6132
+ return schema.fields.filter(isRecord3).map((field) => stringValue(field.name)).filter(Boolean);
6133
+ }
6134
+ return [];
6135
+ }
6136
+ function schemaFieldDetails(schema) {
6137
+ const required = requiredPlayInputFields({
6138
+ inputSchema: schema
6139
+ });
6140
+ const optional = inputPropertyNames(schema).filter(
6141
+ (field) => !required.includes(field)
6142
+ );
6143
+ return { required, optional };
6144
+ }
6145
+ function jsonSchemaTypeExpression(schema) {
6146
+ if (!isRecord3(schema)) return "unknown";
6147
+ const type = schema.type;
6148
+ if (Array.isArray(type)) {
6149
+ return type.map((entry) => jsonSchemaTypeExpression({ ...schema, type: entry })).join(" | ");
6150
+ }
6151
+ if (Array.isArray(schema.anyOf)) {
6152
+ return schema.anyOf.map(jsonSchemaTypeExpression).join(" | ");
6153
+ }
6154
+ if (Array.isArray(schema.oneOf)) {
6155
+ return schema.oneOf.map(jsonSchemaTypeExpression).join(" | ");
6156
+ }
6157
+ switch (type) {
6158
+ case "string":
6159
+ return "string";
6160
+ case "number":
6161
+ case "integer":
6162
+ return "number";
6163
+ case "boolean":
6164
+ return "boolean";
6165
+ case "null":
6166
+ return "null";
6167
+ case "array":
6168
+ return `Array<${jsonSchemaTypeExpression(schema.items)}>`;
6169
+ case "object":
6170
+ return "Record<string, unknown>";
6171
+ default:
6172
+ return "unknown";
6173
+ }
6174
+ }
6175
+ function objectPropertySchema(schema, property) {
6176
+ return isRecord3(schema) && isRecord3(schema.properties) ? schema.properties[property] : null;
6177
+ }
6178
+ function finderResultTypeName(finder) {
6179
+ return finder === "email_finder" ? "EmailFinderPlayResult" : "PhoneFinderPlayResult";
6180
+ }
6181
+ function renderFinderPlayResultType(input) {
6182
+ if (!input.play) return null;
6183
+ const outputField = PLAY_BOOTSTRAP_OUTPUT_FIELD_BY_FINDER[input.finder];
6184
+ const fieldSchema = objectPropertySchema(
6185
+ input.play.outputSchema,
6186
+ outputField
6187
+ );
6188
+ const fieldType = fieldSchema ? jsonSchemaTypeExpression(fieldSchema) : "string | null";
6189
+ return `type ${finderResultTypeName(input.finder)} =
6190
+ | string
6191
+ | null
6192
+ | {
6193
+ ${outputField}?: ${fieldType};
6194
+ };`;
6195
+ }
6196
+ function generatedFinderPlayResultTypes(input) {
6197
+ return ["email_finder", "phone_finder"].flatMap((finder) => {
6198
+ const stage = finderStage(input.options, finder);
6199
+ if (stage?.kind !== "play") return [];
6200
+ const typeDefinition = renderFinderPlayResultType({
6201
+ finder,
6202
+ play: input.finderPlays[finder]
6203
+ });
6204
+ return typeDefinition ? [typeDefinition] : [];
6205
+ }).join("\n\n");
6206
+ }
6207
+ function exampleValueComment(field) {
6208
+ if (field === "limit" || field === "numResults" || field === "num_results" || field === "page_size") {
6209
+ return "limit";
6210
+ }
6211
+ if (field === "roles" || field.endsWith("s")) return '["..."]';
6212
+ return '"..."';
6213
+ }
6214
+ function generateContactInputObjectFromSchema(schema, indent, label, fallbackFields = ["first_name", "last_name", "domain"]) {
6215
+ const details = schemaFieldDetails(schema);
6216
+ const required = details.required.length ? details.required : fallbackFields;
6217
+ const optional = details.optional;
6218
+ const lines = [
6219
+ `${indent}// TODO: map row fields into ${label}.`,
6220
+ ...playInspectionComments(label, indent),
6221
+ `${indent}// Required: ${required.join(", ") || "none declared"}.`
6222
+ ];
6223
+ for (const field of required) {
6224
+ lines.push(`${indent}// ${field}: row["TODO_SOURCE_FIELD"],`);
6225
+ }
6226
+ if (optional.length > 0) {
6227
+ lines.push("");
6228
+ lines.push(`${indent}// optional (delete unused):`);
6229
+ for (const field of optional) {
6230
+ lines.push(`${indent}// ${field}: row["TODO_SOURCE_FIELD"],`);
6231
+ }
6232
+ }
6233
+ return `{
6234
+ ${lines.join("\n")}
6235
+ ${indent.slice(2)}}`;
6236
+ }
6237
+ function generateCompanyInputObjectFromSchema(schema, indent, label, fallbackFields = ["domain", "company_name"]) {
6238
+ const details = schemaFieldDetails(schema);
6239
+ const required = details.required.length ? details.required : fallbackFields;
6240
+ const optional = details.optional;
6241
+ const lines = [
6242
+ `${indent}// TODO: map company fields into ${label}.`,
6243
+ ...playInspectionComments(label, indent),
6244
+ `${indent}// Required: ${required.join(", ") || "none declared"}.`
6245
+ ];
6246
+ for (const field of required) {
6247
+ lines.push(`${indent}// ${field}: company["TODO_SOURCE_FIELD"],`);
6248
+ }
6249
+ if (optional.length > 0) {
6250
+ lines.push("");
6251
+ lines.push(`${indent}// optional (delete unused):`);
6252
+ for (const field of optional) {
6253
+ lines.push(`${indent}// ${field}: company["TODO_SOURCE_FIELD"],`);
6254
+ }
6255
+ }
6256
+ return `{
6257
+ ${lines.join("\n")}
6258
+ ${indent.slice(2)}}`;
6259
+ }
6260
+ function generateSourceProviderInputObject(input) {
6261
+ const { tool, indent, label, entity } = input;
6262
+ const properties = inputPropertyNames(tool?.inputSchema);
6263
+ const details = schemaFieldDetails(tool?.inputSchema);
6264
+ const required = details.required;
6265
+ const includeOptional = properties.length === 0 ? ["query", "title", "domain", "limit"] : properties.filter(
6266
+ (field) => [
6267
+ "query",
6268
+ "q",
6269
+ "search",
6270
+ "title",
6271
+ "role",
6272
+ "persona",
6273
+ "domain",
6274
+ "company_domain",
6275
+ "limit",
6276
+ "numResults",
6277
+ "num_results",
6278
+ "page_size"
6279
+ ].includes(field)
6280
+ );
6281
+ const lines = [
6282
+ `${indent}// TODO: fill ${entity} source inputs for ${label}.`,
6283
+ `${indent}// Inspect: deepline tools describe ${label} --json`
6284
+ ];
6285
+ for (const field of required) {
6286
+ lines.push(`${indent}// ${field}: ${exampleValueComment(field)},`);
6287
+ }
6288
+ const activeTodoField = required.length === 0 ? ["query", "q", "search", "title", "role", "persona"].find(
6289
+ (field) => includeOptional.includes(field)
6290
+ ) ?? "query" : null;
6291
+ if (activeTodoField) {
6292
+ lines.push(
6293
+ `${indent}// ${activeTodoField}: ${exampleValueComment(activeTodoField)},`
6294
+ );
6295
+ }
6296
+ const optionalExamples = includeOptional.filter(
6297
+ (field) => !required.includes(field) && field !== activeTodoField
6298
+ );
6299
+ if (optionalExamples.length > 0) {
6300
+ lines.push("");
6301
+ lines.push(`${indent}// optional - uncomment what this provider supports:`);
6302
+ for (const field of optionalExamples) {
6303
+ if (field === "limit" || field === "numResults" || field === "num_results" || field === "page_size") {
6304
+ lines.push(`${indent}// ${field}: limit,`);
6305
+ } else {
6306
+ lines.push(`${indent}// ${field}: ${exampleValueComment(field)},`);
6307
+ }
6308
+ }
6309
+ }
6310
+ if (!required.some(
6311
+ (field) => ["limit", "numResults", "num_results", "page_size"].includes(field)
6312
+ )) {
6313
+ lines.push(`${indent}limit,`);
6314
+ }
6315
+ return `{
6316
+ ${lines.join("\n")}
6317
+ ${indent.slice(2)}}`;
6318
+ }
6319
+ function generatePlayInputObject(input) {
6320
+ const { schema, indent, label, entity } = input;
6321
+ const details = schemaFieldDetails(schema);
6322
+ const fallback = entity === "company" ? ["domain", "company_name"] : ["first_name", "last_name", "domain"];
6323
+ const required = details.required.length ? details.required : fallback;
6324
+ const lines = [
6325
+ `${indent}// TODO: fill source play inputs for ${label}.`,
6326
+ ...playInspectionComments(label, indent)
6327
+ ];
6328
+ for (const field of required) {
6329
+ lines.push(`${indent}// ${field}: ${exampleValueComment(field)},`);
6330
+ }
6331
+ if (!required.includes("limit")) lines.push(`${indent}limit,`);
6332
+ return `{
6333
+ ${lines.join("\n")}
6334
+ ${indent.slice(2)}}`;
6335
+ }
6336
+ function requiredPlayInputFields(play) {
6337
+ const schema = play?.inputSchema;
6338
+ if (!isRecord3(schema)) return [];
6339
+ if (Array.isArray(schema.required)) {
6340
+ return schema.required.filter(
6341
+ (value) => typeof value === "string"
6342
+ );
6343
+ }
6344
+ if (Array.isArray(schema.fields)) {
6345
+ return schema.fields.filter(isRecord3).filter(
6346
+ (field) => field.required === true && typeof field.name === "string"
6347
+ ).map((field) => String(field.name));
6348
+ }
6349
+ return [];
6350
+ }
6351
+ function sourceProviders(options) {
6352
+ return options.from.kind === "providers" ? options.from.values : [];
6353
+ }
6354
+ function sourcePlayRef(options) {
6355
+ return options.from.kind === "play" ? options.from.value : null;
6356
+ }
6357
+ function stagePlayRef(stage) {
6358
+ return stage?.kind === "play" ? stage.value : null;
6359
+ }
6360
+ function stageProviders(stage) {
6361
+ return stage?.kind === "providers" ? stage.values : [];
6362
+ }
6363
+ function finderStage(options, finder) {
6364
+ return finder === "email_finder" ? options.email : options.phone;
6365
+ }
6366
+ function stepFieldName(finder) {
6367
+ return PLAY_BOOTSTRAP_OUTPUT_FIELD_BY_FINDER[finder];
6368
+ }
6369
+ function finderProviderStepPrefix(finder) {
6370
+ return finder === "email_finder" ? "emailFinder" : "phoneFinder";
6371
+ }
6372
+ function safeIdentifier(value) {
6373
+ return value.replace(/[^A-Za-z0-9_]+/g, "_");
6374
+ }
6375
+ function playInspectionComments(playRef, indent) {
6376
+ return [`${indent}// Inspect: deepline plays describe ${playRef} --json`];
6377
+ }
6378
+ function accessorExpression(base, field) {
6379
+ return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(field) ? `${base}.${field}` : `${base}[${jsString(field)}]`;
6380
+ }
6381
+ function needsWhenImport(options) {
6382
+ return stageProviders(options.email).length > 1 || stageProviders(options.phone).length > 1;
6383
+ }
6384
+ function sourceCollectionTypeName(entity) {
6385
+ return entity === "company" ? "CompanySourceRow" : "ContactSourceRow";
6386
+ }
6387
+ function renderPartialRowType(input) {
6388
+ if (input.fields.length === 0) {
6389
+ return `type ${input.typeName} = Record<string, unknown>;`;
6390
+ }
6391
+ const properties = input.fields.map((field) => ` ${jsString(field)}?: unknown;`).join("\n");
6392
+ return `type ${input.typeName} = Record<string, unknown> & Partial<{
6393
+ // ${input.comment}
6394
+ ${properties}
6395
+ }>;`;
6396
+ }
6397
+ function fieldsFromSchemaDetails(input) {
6398
+ return [
6399
+ ...input.details.required.length ? input.details.required : input.fallbackFields,
6400
+ ...input.details.optional
6401
+ ];
6402
+ }
6403
+ function schemaFieldsForStage(stage, input) {
6404
+ switch (stage?.kind) {
6405
+ case void 0:
6406
+ return [];
6407
+ case "play":
6408
+ return fieldsFromSchemaDetails({
6409
+ details: schemaFieldDetails(input.play?.inputSchema),
6410
+ fallbackFields: input.fallbackFields
6411
+ });
6412
+ case "providers":
6413
+ return input.tools.flatMap(
6414
+ (tool) => fieldsFromSchemaDetails({
6415
+ details: schemaFieldDetails(tool.inputSchema),
6416
+ fallbackFields: input.fallbackFields
6417
+ })
6418
+ );
6419
+ }
6420
+ }
6421
+ function sourceRowTypeDefinition(input) {
6422
+ switch (input.options.from.kind) {
6423
+ case "csv":
6424
+ return `type ${input.sourceTypeName} = SourceCsvRow;`;
6425
+ case "providers":
6426
+ return renderPartialRowType({
6427
+ typeName: input.sourceTypeName,
6428
+ fields: [
6429
+ ...new Set(input.sourceTools.flatMap(listRowCandidateKeysFromTool))
6430
+ ].sort(),
6431
+ comment: "Candidate source row keys from described list getters; confirm the actual provider keys with source_*.extractedLists.*.keys before mapping."
6432
+ });
6433
+ case "play": {
6434
+ const details = schemaFieldDetails(input.sourcePlay?.outputSchema);
6435
+ return renderPartialRowType({
6436
+ typeName: input.sourceTypeName,
6437
+ fields: [...details.required, ...details.optional].sort(),
6438
+ comment: "Candidate source play output fields; confirm the selected rows field before mapping."
6439
+ });
6440
+ }
6441
+ }
6442
+ }
6443
+ function contactBridgeRowTypeDefinition(input) {
6444
+ const config = playBootstrapTemplateConfig(input.options.template);
6445
+ if (config.sourceEntity !== "company" || !input.options.people) return null;
6446
+ const emailFields = schemaFieldsForStage(input.options.email, {
6447
+ tools: input.finderTools.email_finder ?? [],
6448
+ play: input.finderPlays.email_finder,
6449
+ fallbackFields: ["first_name", "last_name", "domain"]
6450
+ });
6451
+ const phoneFields = schemaFieldsForStage(input.options.phone, {
6452
+ tools: input.finderTools.phone_finder ?? [],
6453
+ play: input.finderPlays.phone_finder,
6454
+ fallbackFields: ["first_name", "last_name", "domain"]
6455
+ });
6456
+ return renderPartialRowType({
6457
+ typeName: "ContactSourceRow",
6458
+ fields: [
6459
+ .../* @__PURE__ */ new Set([
6460
+ ...inputPropertyNames(input.peoplePlay?.outputSchema),
6461
+ ...emailFields,
6462
+ ...phoneFields
6463
+ ])
6464
+ ].sort(),
6465
+ comment: "Fields the people play or later finder stages may need; the generated code still requires explicit mapping."
6466
+ });
6467
+ }
6468
+ function generateRowTypeDefinitions(input) {
6469
+ const config = playBootstrapTemplateConfig(input.options.template);
6470
+ const sourceTypeName = sourceCollectionTypeName(config.sourceEntity);
6471
+ const definitions = [
6472
+ sourceRowTypeDefinition({
6473
+ options: input.options,
6474
+ sourceTypeName,
6475
+ sourceTools: input.sourceTools,
6476
+ sourcePlay: input.sourcePlay
6477
+ }),
6478
+ contactBridgeRowTypeDefinition(input)
6479
+ ];
6480
+ return definitions.filter(Boolean).join("\n\n");
6481
+ }
6482
+ function validateBootstrapRoutes(input) {
6483
+ const config = playBootstrapTemplateConfig(input.options.template);
6484
+ const sourceCategory = config.sourceEntity === "company" ? PLAY_BOOTSTRAP_COMPANY_PROVIDER_CATEGORY : PLAY_BOOTSTRAP_PEOPLE_PROVIDER_CATEGORY;
6485
+ for (const tool of input.sourceTools) {
6486
+ if (!tool.categories.includes(sourceCategory)) {
6487
+ throw new PlayBootstrapValidationError(
6488
+ `Cannot use ${tool.toolId} as a ${config.sourceEntity} source for ${input.options.template}: expected category ${sourceCategory}, got ${tool.categories.join(", ") || "none"}. Run: deepline tools grep ${sourceCategory} --categories ${sourceCategory} --json`
6489
+ );
6490
+ }
6491
+ if (getterNamesFromTool(tool, "list").length === 0) {
6492
+ throw new PlayBootstrapValidationError(
6493
+ `Cannot use ${tool.toolId} as a ${config.sourceEntity} source: it exposes no extracted list getters. Run: deepline tools describe ${tool.toolId} --json`
6494
+ );
6495
+ }
6496
+ }
6497
+ if (input.options.people?.kind === "providers") {
6498
+ throw new PlayBootstrapValidationError(
6499
+ "Company-to-people bootstrap only accepts --people play:<play-ref> for now. Providers are too task-specific; choose or create a people play so the generated file can show the mapping contract."
6500
+ );
6501
+ }
6502
+ for (const finder of ["email_finder", "phone_finder"]) {
6503
+ const requiredCategory = PLAY_BOOTSTRAP_PROVIDER_CATEGORY_BY_FINDER[finder];
6504
+ for (const tool of input.finderTools[finder] ?? []) {
6505
+ if (!tool.categories.includes(requiredCategory)) {
6506
+ throw new PlayBootstrapValidationError(
6507
+ `Cannot use ${tool.toolId} for ${finder}: expected category ${requiredCategory}, got ${tool.categories.join(", ") || "none"}. Run: deepline tools grep ${requiredCategory} --categories ${requiredCategory} --json`
6508
+ );
6509
+ }
6510
+ if (getterNamesFromTool(tool, "value").length === 0) {
6511
+ throw new PlayBootstrapValidationError(
6512
+ `Cannot use ${tool.toolId} as a ${finder}: it exposes no extracted value getters. Run: deepline tools describe ${tool.toolId} --json`
6513
+ );
6514
+ }
6515
+ }
6516
+ }
6517
+ }
6518
+ function sourceCollectionName(entity) {
6519
+ switch (entity) {
6520
+ case "company":
6521
+ return "companies";
6522
+ case "people":
6523
+ return "contacts";
6524
+ }
6525
+ }
6526
+ function requiredGetterName(input) {
6527
+ const getter = getterNamesFromTool(input.tool, input.kind)[0];
6528
+ if (!getter) {
6529
+ switch (input.kind) {
6530
+ case "list":
6531
+ throw new PlayBootstrapValidationError(
6532
+ `Cannot use ${input.label} as a source: it exposes no extracted list getters.`
6533
+ );
6534
+ case "value":
6535
+ throw new PlayBootstrapValidationError(
6536
+ `Cannot use ${input.label} as a finder: it exposes no extracted value getters.`
6537
+ );
6538
+ }
6539
+ }
6540
+ return getter;
6541
+ }
6542
+ function generateCsvSourceRowsBlock(input) {
6543
+ return `const sourceDataset = await ctx.csv<SourceCsvRow>(${jsString(input.packagedSourceCsvPath ?? input.source.value)});
6544
+ const ${input.collection}: ${input.collectionType}[] = await sourceDataset.peek(limit);`;
6545
+ }
6546
+ function generatePlaySourceRowsBlock(input) {
6547
+ const playInput = generatePlayInputObject({
6548
+ schema: input.sourcePlay?.inputSchema,
6549
+ indent: " ",
6550
+ label: input.source.value,
6551
+ entity: input.entity
6552
+ });
6553
+ return `const sourceInput = ${playInput};
6554
+ throw new Error(${jsString(`TODO: map sourceInput for ${input.source.value}, choose the play output rows field, then delete this throw.`)});
6555
+ const sourceResult = await ctx.runPlay('source_play', ${jsString(input.source.value)}, sourceInput, {
6556
+ description: ${jsString(`Seed ${input.entity} rows from the selected play.`)},
6557
+ });
6558
+ // TODO: Replace sourceResult.rows with the selected play's actual row output field.
6559
+ const ${input.collection}: ${input.collectionType}[] = (sourceResult.rows ?? []) as ${input.collectionType}[];`;
6560
+ }
6561
+ function generateProviderSourceBlock(input) {
6562
+ const getter = requiredGetterName({
6563
+ tool: input.tool,
6564
+ kind: "list",
6565
+ label: input.provider
6566
+ });
6567
+ const inputName = `${input.entity}Input_${input.index}`;
6568
+ return `// ${input.entity === "company" ? "Company" : "People"} source provider: ${input.provider}
6569
+ const ${inputName}: Record<string, unknown> = ${generateSourceProviderInputObject(
6570
+ {
6571
+ tool: input.tool,
6572
+ indent: " ",
6573
+ label: input.provider,
6574
+ entity: input.entity
6575
+ }
6576
+ )};
6577
+ throw new Error(${jsString(`TODO: fill ${inputName} for ${input.provider}, then delete this throw.`)});
6578
+ const source_${input.index} = await ctx.tools.execute({
6579
+ id: ${jsString(`${input.entity}_source_${input.index}`)},
6580
+ tool: ${jsString(input.provider)},
6581
+ input: ${inputName},
6582
+ description: ${jsString(`Seed ${input.entity} rows from ${input.provider}.`)},
6583
+ });
6584
+ // extractedLists.${getter}.get() returns provider-shaped rows. Do not assume canonical fields;
6585
+ // inspect source_${input.index}.extractedLists.${getter}.keys or the provider output schema, then map explicitly below.
6586
+ const sourceRows_${input.index} = ${accessorExpression(`source_${input.index}.extractedLists`, getter)}.get() as ${input.collectionType}[];`;
6587
+ }
6588
+ function generateProviderSourceRowsBlock(input) {
6589
+ const blocks = input.source.values.map(
6590
+ (provider, index) => generateProviderSourceBlock({
6591
+ provider,
6592
+ index,
6593
+ tool: input.sourceTools[index] ?? null,
6594
+ entity: input.entity,
6595
+ collectionType: input.collectionType
6596
+ })
6597
+ );
6598
+ return `${blocks.join("\n\n ")}
6599
+ const ${input.collection}: ${input.collectionType}[] = [${input.source.values.map((_, index) => `...sourceRows_${index}`).join(", ")}];`;
6600
+ }
6601
+ function generateSourceRowsBlock(input) {
6602
+ const config = playBootstrapTemplateConfig(input.options.template);
6603
+ const entity = config.sourceEntity;
6604
+ const collection = sourceCollectionName(entity);
6605
+ const collectionType = sourceCollectionTypeName(entity);
6606
+ switch (input.options.from.kind) {
6607
+ case "csv":
6608
+ return generateCsvSourceRowsBlock({
6609
+ source: input.options.from,
6610
+ collection,
6611
+ collectionType,
6612
+ packagedSourceCsvPath: input.packagedSourceCsvPath
6613
+ });
6614
+ case "play":
6615
+ return generatePlaySourceRowsBlock({
6616
+ source: input.options.from,
6617
+ sourcePlay: input.sourcePlay,
6618
+ entity,
6619
+ collection,
6620
+ collectionType
6621
+ });
6622
+ case "providers":
6623
+ return generateProviderSourceRowsBlock({
6624
+ source: input.options.from,
6625
+ sourceTools: input.sourceTools,
6626
+ entity,
6627
+ collection,
6628
+ collectionType
6629
+ });
6630
+ }
6631
+ }
6632
+ function generateSourceSeedBlock(input) {
6633
+ const sourceRows = generateSourceRowsBlock(input);
6634
+ const peoplePlayRef = stagePlayRef(input.options.people);
6635
+ if (!peoplePlayRef) return sourceRows;
6636
+ const peopleInput = generateCompanyInputObjectFromSchema(
6637
+ input.peoplePlay?.inputSchema,
6638
+ " ",
6639
+ peoplePlayRef,
6640
+ ["domain", "company_name"]
6641
+ );
6642
+ return `${sourceRows}
6643
+ const contacts: ContactSourceRow[] = [];
6644
+ for (const [index, company] of companies.slice(0, limit).entries()) {
6645
+ const peopleInput = ${peopleInput};
6646
+ throw new Error(${jsString(`TODO: map company fields into peopleInput for ${peoplePlayRef}, choose the play output rows field, then delete this throw.`)});
6647
+ const peopleResult = await ctx.runPlay(
6648
+ \`people_play_\${index}\`,
6649
+ ${jsString(peoplePlayRef)},
6650
+ peopleInput,
6651
+ {
6652
+ description: 'Map one company row into people/contact rows with the selected play.',
6653
+ },
6654
+ );
6655
+ // TODO: Replace peopleResult.rows with the selected play's actual contact rows field.
6656
+ contacts.push(...((peopleResult.rows ?? []) as ContactSourceRow[]));
6657
+ }`;
6658
+ }
6659
+ function finderProviderStepName(input) {
6660
+ return `${input.aggregateStepName}${input.index}_${safeIdentifier(input.provider)}`;
6661
+ }
6662
+ function finderValueGetter(input) {
6663
+ const getters = getterNamesFromTool(input.tool, "value");
6664
+ const getter = getters.find((name) => name === input.outputField) ?? requiredGetterName({
6665
+ tool: input.tool,
6666
+ kind: "value",
6667
+ label: input.provider
6668
+ });
6669
+ return getter;
6670
+ }
6671
+ function optionalFinderValueExpression(candidateExpression, outputField) {
6672
+ const valueExpression = /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(outputField) ? `${candidateExpression}?.${outputField}` : `${candidateExpression}?.[${jsString(outputField)}]`;
6673
+ return `${valueExpression}?.trim()`;
6674
+ }
6675
+ function generateFinderPlayStep(input) {
6676
+ const outputField = PLAY_BOOTSTRAP_OUTPUT_FIELD_BY_FINDER[input.finder];
6677
+ const resultTypeName = finderResultTypeName(input.finder);
6678
+ const payload = generateContactInputObjectFromSchema(
6679
+ input.play?.inputSchema,
6680
+ " ",
6681
+ input.stage.value
6682
+ );
6683
+ return `.step(${jsString(outputField)}, async (row, rowCtx) => {
6684
+ const ${input.aggregateStepName}Input = ${payload};
6685
+ throw new Error(${jsString(`TODO: map ${input.aggregateStepName}Input for ${input.stage.value}, then delete this throw.`)});
6686
+ const ${input.aggregateStepName}Result = await rowCtx.runPlay<${resultTypeName}>(
6687
+ ${jsString(`${input.aggregateStepName}Play`)},
6688
+ ${jsString(input.stage.value)},
6689
+ ${input.aggregateStepName}Input,
6690
+ {
6691
+ description: ${jsString(`Run ${input.finder} play.`)},
6692
+ },
6693
+ );
6694
+ return typeof ${input.aggregateStepName}Result === 'string'
6695
+ ? ${input.aggregateStepName}Result.trim() || null
6696
+ : ${input.aggregateStepName}Result?.${outputField} ?? null;
6697
+ })`;
6698
+ }
6699
+ function generateFinderProviderResolver(input) {
6700
+ const payload = generateContactInputObjectFromSchema(
6701
+ input.tool?.inputSchema,
6702
+ " ",
6703
+ input.provider
6704
+ );
6705
+ const getter = finderValueGetter({
6706
+ tool: input.tool,
6707
+ provider: input.provider,
6708
+ outputField: input.outputField
6709
+ });
6710
+ return `async (row, rowCtx) => {
6711
+ const providerInput = ${payload};
6712
+ throw new Error(${jsString(`TODO: map providerInput for ${input.provider}, then delete this throw.`)});
6713
+ const result = await rowCtx.tools.execute({
6714
+ id: ${jsString(`${input.aggregateStepName}_${input.providerIndex}`)},
6715
+ tool: ${jsString(input.provider)},
6716
+ input: providerInput,
6717
+ description: ${jsString(`Try ${input.provider} as a ${input.finder}.`)},
6718
+ });
6719
+ return {
6720
+ ${input.outputField}: (${accessorExpression("result.extractedValues", getter)}.get() as string | null) ?? null,
6721
+ result,
6722
+ };
6723
+ }`;
6724
+ }
6725
+ function generateFinderProviderStep(input) {
6726
+ const stepName = input.stepNames[input.index];
6727
+ switch (input.index) {
6728
+ case 0:
6729
+ return `.step(${jsString(stepName)}, ${input.resolver})`;
6730
+ default: {
6731
+ const priorCandidates = input.stepNames.slice(0, input.index).map((name) => `row.${name}`).join(", ");
6732
+ return `.step(
6733
+ ${jsString(stepName)},
6734
+ when(
6735
+ (row) => ![${priorCandidates}].some((candidate) => ${optionalFinderValueExpression("candidate", input.outputField)}),
6736
+ ${input.resolver},
6737
+ ),
6738
+ )`;
6739
+ }
6740
+ }
6741
+ }
6742
+ function generateFinderProviderWaterfall(input) {
6743
+ const legPrefix = finderProviderStepPrefix(input.finder);
6744
+ const stepNames = input.stage.values.map(
6745
+ (provider, index) => finderProviderStepName({
6746
+ aggregateStepName: legPrefix,
6747
+ provider,
6748
+ index
6749
+ })
6750
+ );
6751
+ const providerSteps = input.stage.values.map(
6752
+ (provider, index) => generateFinderProviderStep({
6753
+ index,
6754
+ stepNames,
6755
+ outputField: input.outputField,
6756
+ resolver: generateFinderProviderResolver({
6757
+ finder: input.finder,
6758
+ provider,
6759
+ providerIndex: index,
6760
+ tool: input.tools[index] ?? null,
6761
+ aggregateStepName: input.aggregateStepName,
6762
+ outputField: input.outputField
6763
+ })
6764
+ })
5555
6765
  );
6766
+ const candidateNames = stepNames.map((name) => `row.${name}`).join(", ");
6767
+ return `// ${input.aggregateStepName} provider waterfall. Each provider leg is active once its TODO throw is removed;
6768
+ // delete or comment out legs you do not want before running. Later legs are gated with when(...).
6769
+ ${providerSteps.join("\n ")}
6770
+ .step(${jsString(input.aggregateStepName)}, (row) => {
6771
+ const candidates = [${candidateNames}];
6772
+ const match = candidates.find((candidate) => ${optionalFinderValueExpression("candidate", input.outputField)});
6773
+ return ${optionalFinderValueExpression("match", input.outputField)} ?? null;
6774
+ })`;
6775
+ }
6776
+ function generateFinderStageSteps(input) {
6777
+ const outputField = PLAY_BOOTSTRAP_OUTPUT_FIELD_BY_FINDER[input.finder];
6778
+ const aggregateStepName = stepFieldName(input.finder);
6779
+ switch (input.stage.kind) {
6780
+ case "play":
6781
+ return generateFinderPlayStep({
6782
+ finder: input.finder,
6783
+ stage: input.stage,
6784
+ play: input.finderPlays[input.finder],
6785
+ aggregateStepName
6786
+ });
6787
+ case "providers":
6788
+ return generateFinderProviderWaterfall({
6789
+ finder: input.finder,
6790
+ stage: input.stage,
6791
+ tools: input.finderTools[input.finder] ?? [],
6792
+ aggregateStepName,
6793
+ outputField
6794
+ });
6795
+ }
5556
6796
  }
5557
- function defaultPlayBundleTarget() {
5558
- return resolveExecutionProfile(null).artifactKind;
5559
- }
5560
- function createSdkPlayBundlingAdapter() {
6797
+ function generateFinderSteps(input) {
6798
+ return ["email_finder", "phone_finder"].flatMap((finder) => {
6799
+ const stage = finderStage(input.options, finder);
6800
+ return stage ? [
6801
+ generateFinderStageSteps({
6802
+ ...input,
6803
+ finder,
6804
+ stage
6805
+ })
6806
+ ] : [];
6807
+ }).join("\n ");
6808
+ }
6809
+ function generateBootstrapPlaySource(input) {
6810
+ const config = playBootstrapTemplateConfig(input.options.template);
6811
+ const sourceSeedBlock = generateSourceSeedBlock(input);
6812
+ const finderSteps = generateFinderSteps(input);
6813
+ const hasPeople = config.sourceEntity === "people" || Boolean(input.options.people);
6814
+ const sourceCollection = hasPeople ? "contacts" : "companies";
6815
+ const mapSteps = finderSteps ? `
6816
+ ${finderSteps}` : "";
6817
+ const sourceCsvRowType = input.options.from.kind === "csv" ? renderSourceCsvRowType(input.sourceCsvColumns) : "";
6818
+ const rowTypeDefinitions = generateRowTypeDefinitions(input);
6819
+ const finderPlayResultTypes = generatedFinderPlayResultTypes(input);
6820
+ const typeDefinitions = [
6821
+ sourceCsvRowType.trimEnd(),
6822
+ rowTypeDefinitions,
6823
+ finderPlayResultTypes
6824
+ ].filter((definition) => definition.trim().length > 0).join("\n\n");
6825
+ const importNames = needsWhenImport(input.options) ? "definePlay, when" : "definePlay";
6826
+ return `import { ${importNames} } from 'deepline';
6827
+
6828
+ ${typeDefinitions}
6829
+
6830
+ type Input = {
6831
+ limit?: number;
6832
+ };
6833
+
6834
+ export default definePlay(${jsString(input.options.name)}, async (ctx, input: Input = {}) => {
6835
+ const limit = Math.max(1, Math.min(Number(input.limit ?? ${input.options.limit}), ${input.options.limit}));
6836
+ ${sourceSeedBlock}
6837
+
6838
+ const rowsToProcess = ${sourceCollection}.slice(0, limit);
6839
+ if (rowsToProcess.length === 0) {
6840
+ throw new Error('plays bootstrap found 0 source rows. Check the source provider/play/CSV output.');
6841
+ }
6842
+
6843
+ const rows = await ctx
6844
+ .map('bootstrap_rows', rowsToProcess)${mapSteps}
6845
+ .run({
6846
+ key: (_row, index) => index,
6847
+ description: ${jsString(`Bootstrap ${input.options.template}: seed source rows, run requested stages, then return the mapped rows.`)},
6848
+ });
6849
+
5561
6850
  return {
5562
- projectRoot: PROJECT_ROOT,
5563
- nodeModulesDir: resolve8(PROJECT_ROOT, "node_modules"),
5564
- cacheDir: join5(
5565
- tmpdir2(),
5566
- `deepline-play-artifacts-v${PLAY_BUNDLE_CACHE_VERSION2}`
5567
- ),
5568
- sdkSourceRoot: SDK_SOURCE_ROOT,
5569
- sdkPackageJson: SDK_PACKAGE_JSON,
5570
- sdkEntryFile: SDK_ENTRY_FILE,
5571
- sdkTypesEntryFile: HAS_SOURCE_BUNDLING_SOURCES || !existsSync5(SDK_TYPES_ENTRY_FILE) ? SDK_ENTRY_FILE : SDK_TYPES_ENTRY_FILE,
5572
- sdkWorkersEntryFile: SDK_WORKERS_ENTRY_FILE,
5573
- workersHarnessEntryFile: WORKERS_HARNESS_ENTRY_FILE,
5574
- workersHarnessFilesDir: WORKERS_HARNESS_FILES_DIR,
5575
- discoverPackagedLocalFiles,
5576
- warnAboutNonDevelopmentBundling
6851
+ count: await rows.count(),
6852
+ rows,
5577
6853
  };
6854
+ });
6855
+
6856
+ `;
5578
6857
  }
5579
- async function bundlePlayFile2(filePath, options = {}) {
5580
- return bundlePlayFile(filePath, {
5581
- target: options.target ?? defaultPlayBundleTarget(),
5582
- exportName: options.exportName,
5583
- adapter: createSdkPlayBundlingAdapter()
6858
+ async function describePlayMaybe(client, playRef) {
6859
+ return playRef ? client.describePlay(playRef, { compact: true }) : null;
6860
+ }
6861
+ function loadTools(client, providers) {
6862
+ return Promise.all(providers.map((provider) => client.getTool(provider)));
6863
+ }
6864
+ async function loadBootstrapContracts(client, options) {
6865
+ const [
6866
+ sourceTools,
6867
+ sourcePlay,
6868
+ peoplePlay,
6869
+ emailPlay,
6870
+ phonePlay,
6871
+ emailTools,
6872
+ phoneTools
6873
+ ] = await Promise.all([
6874
+ loadTools(client, sourceProviders(options)),
6875
+ describePlayMaybe(client, sourcePlayRef(options)),
6876
+ describePlayMaybe(client, stagePlayRef(options.people)),
6877
+ describePlayMaybe(client, stagePlayRef(options.email)),
6878
+ describePlayMaybe(client, stagePlayRef(options.phone)),
6879
+ loadTools(client, stageProviders(options.email)),
6880
+ loadTools(client, stageProviders(options.phone))
6881
+ ]);
6882
+ const contracts = {
6883
+ sourceTools,
6884
+ sourcePlay,
6885
+ peoplePlay,
6886
+ finderTools: {
6887
+ email_finder: emailTools,
6888
+ phone_finder: phoneTools
6889
+ },
6890
+ finderPlays: {
6891
+ email_finder: emailPlay,
6892
+ phone_finder: phonePlay
6893
+ }
6894
+ };
6895
+ validateBootstrapRoutes({
6896
+ options,
6897
+ sourceTools: contracts.sourceTools,
6898
+ peoplePlay: contracts.peoplePlay,
6899
+ finderTools: contracts.finderTools,
6900
+ finderPlays: contracts.finderPlays
6901
+ });
6902
+ return contracts;
6903
+ }
6904
+ function loadCsvContext(source) {
6905
+ switch (source.kind) {
6906
+ case "csv":
6907
+ return {
6908
+ packagedSourceCsvPath: packagedCsvPathForPlay(source.value),
6909
+ sourceCsvColumns: readSourceCsvColumnSpecs(source.value)
6910
+ };
6911
+ case "play":
6912
+ case "providers":
6913
+ return {
6914
+ packagedSourceCsvPath: null,
6915
+ sourceCsvColumns: []
6916
+ };
6917
+ }
6918
+ }
6919
+ function errorMessage(error) {
6920
+ return error instanceof Error ? error.message : String(error);
6921
+ }
6922
+ function renderPlayBootstrapError(error) {
6923
+ console.error(errorMessage(error));
6924
+ return error instanceof PlayBootstrapError ? error.exitCode : 1;
6925
+ }
6926
+ async function runPlayBootstrap(args) {
6927
+ const options = parsePlayBootstrapOptions(args);
6928
+ const client = new DeeplineClient();
6929
+ const contracts = await loadBootstrapContracts(client, options);
6930
+ const csvContext = loadCsvContext(options.from);
6931
+ const source = generateBootstrapPlaySource({
6932
+ options,
6933
+ ...contracts,
6934
+ ...csvContext
6935
+ });
6936
+ process.stdout.write(source);
6937
+ return 0;
6938
+ }
6939
+ async function handlePlayBootstrap(args) {
6940
+ return runPlayBootstrap(args).catch(renderPlayBootstrapError);
6941
+ }
6942
+ function registerPlayBootstrapCommand(play) {
6943
+ play.command("bootstrap <template>").description("Print a scratchpad play for a GTM route template.").addHelpText(
6944
+ "after",
6945
+ `
6946
+ Notes:
6947
+ Cloud-validated play generator for agents. Pick the JTBD as the positional
6948
+ template, bind resources with typed refs, redirect stdout to a .play.ts file,
6949
+ then edit the generated TODO mapping comments. Multiple finder providers are
6950
+ generated as a waterfall in the order you pass them.
6951
+
6952
+ This command requires auth because provider/play contracts are fetched from
6953
+ Deepline. It prints TypeScript source only and does not run paid tools; the
6954
+ generated play may spend credits later when you run it.
6955
+
6956
+ stdout is the generated .play.ts source. Errors and diagnostics go to stderr.
6957
+ There is no JSON mode and no --out; use shell redirection:
6958
+ deepline plays bootstrap ... > scratchpad.play.ts
6959
+
6960
+ Templates:
6961
+ people-list start from people/contact rows
6962
+ company-list start from company/account rows
6963
+ people-email people/contact rows -> email finder
6964
+ people-phone people/contact rows -> phone finder
6965
+ company-people company/account rows -> people play
6966
+ company-people-email company/account rows -> people play -> email finder
6967
+ company-people-phone company/account rows -> people play -> phone finder
6968
+
6969
+ Resource refs:
6970
+ csv:./contacts.csv
6971
+ play:prebuilt/name-and-domain-to-email-waterfall
6972
+ provider:dropleads_search_people
6973
+ providers:hunter_email_finder,leadmagic_email_finder
6974
+
6975
+ Validation:
6976
+ source providers must match the route entity: company_search or people_search
6977
+ source providers must expose list getters
6978
+ company -> people uses a play only; provider bridge is generated later when a play exists
6979
+ email/phone finder providers must match their category and expose value getters
6980
+ finder plays/providers must match the route; generated code leaves input mapping explicit
6981
+ business-specific provider inputs and company -> people persona fields are TODOs in code
6982
+ csv: paths are resolved from the directory where you run bootstrap; redirect the play file there too
6983
+
6984
+ Exit codes:
6985
+ 0 success
6986
+ 2 usage/local input error
6987
+ 7 route validation failed
6988
+
6989
+ Examples:
6990
+ deepline plays bootstrap people-email --from csv:data/leads.csv --using play:prebuilt/name-and-domain-to-email-waterfall --limit 5 > email-flow.play.ts
6991
+ deepline plays check email-flow.play.ts
6992
+ deepline plays run email-flow.play.ts --input '{"limit":5}' --watch
6993
+
6994
+ deepline plays bootstrap people-email --from provider:dropleads_search_people --using providers:hunter_email_finder,leadmagic_email_finder --limit 5 > prospecting.play.ts
6995
+ deepline plays bootstrap company-people-email --from provider:apollo_company_search --people play:prebuilt/company-to-contact --email play:prebuilt/name-and-domain-to-email-waterfall --limit 5 > account-contacts.play.ts
6996
+ deepline plays bootstrap company-list --from provider:apollo_company_search --limit 5 > companies.play.ts
6997
+ `
6998
+ ).option("--name <name>", "Generated play name").option(
6999
+ "--from <ref>",
7000
+ "Route source: csv:PATH, play:REF, provider:ID, or providers:ID,ID"
7001
+ ).option(
7002
+ "--using <ref>",
7003
+ "Single-stage route shorthand for people-email, people-phone, or company-people"
7004
+ ).option(
7005
+ "--people <ref>",
7006
+ "Company-to-people stage for company-people-email/phone; use play:REF"
7007
+ ).option(
7008
+ "--email <ref>",
7009
+ "Email finder stage: play:REF, provider:ID, or providers:ID,ID"
7010
+ ).option(
7011
+ "--phone <ref>",
7012
+ "Phone finder stage: play:REF, provider:ID, or providers:ID,ID"
7013
+ ).option("--limit <n>", "Maximum rows to fan out in the generated play").action(async (template, options) => {
7014
+ process.exitCode = await handlePlayBootstrap([
7015
+ template,
7016
+ ...options.name ? ["--name", options.name] : [],
7017
+ ...options.from ? ["--from", options.from] : [],
7018
+ ...options.using ? ["--using", options.using] : [],
7019
+ ...options.people ? ["--people", options.people] : [],
7020
+ ...options.email ? ["--email", options.email] : [],
7021
+ ...options.phone ? ["--phone", options.phone] : [],
7022
+ ...options.limit ? ["--limit", options.limit] : []
7023
+ ]);
5584
7024
  });
5585
7025
  }
5586
7026
 
@@ -6035,9 +7475,9 @@ function traceCliSync(phase, fields, run) {
6035
7475
  }
6036
7476
  }
6037
7477
  function sleep4(ms) {
6038
- return new Promise((resolve11) => setTimeout(resolve11, ms));
7478
+ return new Promise((resolve12) => setTimeout(resolve12, ms));
6039
7479
  }
6040
- function parseReferencedPlayTarget(target) {
7480
+ function parseReferencedPlayTarget2(target) {
6041
7481
  const trimmed = target.trim();
6042
7482
  const slashIndex = trimmed.indexOf("/");
6043
7483
  if (slashIndex <= 0 || slashIndex === trimmed.length - 1) {
@@ -6058,7 +7498,7 @@ function buildBarePrebuiltReferenceError(input) {
6058
7498
  );
6059
7499
  }
6060
7500
  async function assertCanonicalNamedPlayReference(client, target) {
6061
- const parsed = parseReferencedPlayTarget(target);
7501
+ const parsed = parseReferencedPlayTarget2(target);
6062
7502
  const detail = await client.getPlay(parsed.playName);
6063
7503
  if (detail.play.ownerType === "deepline" && !isPrebuiltReferenceTarget(target)) {
6064
7504
  throw buildBarePrebuiltReferenceError({
@@ -6079,10 +7519,10 @@ function formatPlayListReference(play) {
6079
7519
  return play.reference || play.name;
6080
7520
  }
6081
7521
  function defaultMaterializedPlayPath(reference) {
6082
- return resolve9(defaultStarterPlayPath(reference));
7522
+ return resolve10(defaultStarterPlayPath(reference));
6083
7523
  }
6084
7524
  function defaultStarterPlayPath(reference) {
6085
- const playName = parseReferencedPlayTarget(reference).unqualifiedPlayName;
7525
+ const playName = parseReferencedPlayTarget2(reference).unqualifiedPlayName;
6086
7526
  const safeName = playName.trim().toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
6087
7527
  return `./${safeName || "play"}.play.ts`;
6088
7528
  }
@@ -6138,7 +7578,7 @@ To make your own version:
6138
7578
  );
6139
7579
  }
6140
7580
  async function ensureEditableRemotePlay(client, target) {
6141
- const parsed = parseReferencedPlayTarget(target);
7581
+ const parsed = parseReferencedPlayTarget2(target);
6142
7582
  const detail = await client.getPlay(parsed.playName);
6143
7583
  if (detail.play.ownerType === "deepline") {
6144
7584
  throw buildReadonlyPrebuiltPlayError(formatPlayReference(detail.play));
@@ -6158,7 +7598,7 @@ function extractPlayName(code, filePath) {
6158
7598
  throw buildMissingDefinePlayError(filePath);
6159
7599
  }
6160
7600
  function isFileTarget(target) {
6161
- return existsSync6(resolve9(target));
7601
+ return existsSync6(resolve10(target));
6162
7602
  }
6163
7603
  function looksLikeRunId(target) {
6164
7604
  return /^play\/[^/]+\/run\/[^/]+/.test(target.trim());
@@ -6179,7 +7619,7 @@ function looksLikeFilePath(target) {
6179
7619
  }
6180
7620
  return target.includes("\\") || /\.(ts|js|mjs|play\.ts)$/.test(target);
6181
7621
  }
6182
- function parsePositiveInteger2(value, flagName) {
7622
+ function parsePositiveInteger3(value, flagName) {
6183
7623
  const parsed = Number.parseInt(value, 10);
6184
7624
  if (!Number.isFinite(parsed) || parsed <= 0) {
6185
7625
  throw new Error(`${flagName} must be a positive integer.`);
@@ -6187,7 +7627,7 @@ function parsePositiveInteger2(value, flagName) {
6187
7627
  return parsed;
6188
7628
  }
6189
7629
  function parseJsonInput(raw) {
6190
- const source = raw.startsWith("@") ? readFileSync5(resolve9(raw.slice(1)), "utf-8") : raw;
7630
+ const source = raw.startsWith("@") ? readFileSync5(resolve10(raw.slice(1)), "utf-8") : raw;
6191
7631
  const parsed = JSON.parse(source);
6192
7632
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
6193
7633
  throw new Error("--input must be a JSON object.");
@@ -6254,7 +7694,8 @@ function setDottedInputValue(input, path, value) {
6254
7694
  cursor[parts[parts.length - 1]] = value;
6255
7695
  }
6256
7696
  function schemaMetadata(schema, key) {
6257
- if (!schema || typeof schema !== "object" || Array.isArray(schema)) return null;
7697
+ if (!schema || typeof schema !== "object" || Array.isArray(schema))
7698
+ return null;
6258
7699
  const value = schema[key];
6259
7700
  return value && typeof value === "object" && !Array.isArray(value) ? value : null;
6260
7701
  }
@@ -6288,7 +7729,7 @@ function fileInputBindingsFromStaticPipeline(staticPipeline) {
6288
7729
  function isLocalFilePathValue(value) {
6289
7730
  if (typeof value !== "string" || !value.trim()) return false;
6290
7731
  if (/^[a-z][a-z0-9+.-]*:\/\//i.test(value.trim())) return false;
6291
- return existsSync6(resolve9(value));
7732
+ return existsSync6(resolve10(value));
6292
7733
  }
6293
7734
  function inputContainsLocalFilePath(value) {
6294
7735
  if (isLocalFilePathValue(value)) {
@@ -6309,12 +7750,14 @@ function namedRunNeedsPlayDefinition(input) {
6309
7750
  }
6310
7751
  async function stageFileInputArgs(input) {
6311
7752
  const uniqueBindings = [
6312
- ...new Map(input.bindings.map((binding) => [binding.inputPath, binding])).values()
7753
+ ...new Map(
7754
+ input.bindings.map((binding) => [binding.inputPath, binding])
7755
+ ).values()
6313
7756
  ];
6314
7757
  const localFiles = uniqueBindings.flatMap((binding) => {
6315
7758
  const value = getDottedInputValue(input.runtimeInput, binding.inputPath);
6316
7759
  if (!isLocalFilePathValue(value)) return [];
6317
- const absolutePath = resolve9(value);
7760
+ const absolutePath = resolve10(value);
6318
7761
  return [{ binding, absolutePath, logicalPath: basename3(absolutePath) }];
6319
7762
  });
6320
7763
  if (localFiles.length === 0) {
@@ -6327,10 +7770,18 @@ async function stageFileInputArgs(input) {
6327
7770
  localFiles.map((file) => stageFile(file.logicalPath, file.absolutePath))
6328
7771
  );
6329
7772
  for (const [index, file] of localFiles.entries()) {
6330
- setDottedInputValue(input.runtimeInput, file.binding.inputPath, file.logicalPath);
7773
+ setDottedInputValue(
7774
+ input.runtimeInput,
7775
+ file.binding.inputPath,
7776
+ file.logicalPath
7777
+ );
6331
7778
  const stagedFile = staged[index];
6332
7779
  if (stagedFile && stagedFile.logicalPath !== file.logicalPath) {
6333
- setDottedInputValue(input.runtimeInput, file.binding.inputPath, stagedFile.logicalPath);
7780
+ setDottedInputValue(
7781
+ input.runtimeInput,
7782
+ file.binding.inputPath,
7783
+ stagedFile.logicalPath
7784
+ );
6334
7785
  }
6335
7786
  }
6336
7787
  return {
@@ -6350,9 +7801,9 @@ function stageFile(logicalPath, absolutePath) {
6350
7801
  }
6351
7802
  function normalizePlayPath(filePath) {
6352
7803
  try {
6353
- return realpathSync.native(resolve9(filePath));
7804
+ return realpathSync.native(resolve10(filePath));
6354
7805
  } catch {
6355
- return resolve9(filePath);
7806
+ return resolve10(filePath);
6356
7807
  }
6357
7808
  }
6358
7809
  function formatBundlingErrors(filePath, errors) {
@@ -6710,7 +8161,10 @@ function formatProgressCounts(input) {
6710
8161
  if (completed === null || total === null || total <= 0) {
6711
8162
  return null;
6712
8163
  }
6713
- const percent = Math.max(0, Math.min(100, Math.round(completed / total * 100)));
8164
+ const percent = Math.max(
8165
+ 0,
8166
+ Math.min(100, Math.round(completed / total * 100))
8167
+ );
6714
8168
  const failed = typeof input.failed === "number" && Number.isFinite(input.failed) && input.failed > 0 ? `, failed ${formatInteger(input.failed)}` : "";
6715
8169
  return `${formatInteger(completed)}/${formatInteger(total)} (${percent}%)${failed}`;
6716
8170
  }
@@ -7424,7 +8878,9 @@ function buildInsufficientCreditsSummaryLines(input) {
7424
8878
  const runId = input.status.runId?.trim();
7425
8879
  if (runId) {
7426
8880
  lines.push(` inspect: deepline runs get ${runId} --json`);
7427
- lines.push(` export partial: deepline runs export ${runId} --out output.csv`);
8881
+ lines.push(
8882
+ ` export partial: deepline runs export ${runId} --out output.csv`
8883
+ );
7428
8884
  }
7429
8885
  return lines;
7430
8886
  }
@@ -7496,7 +8952,10 @@ function normalizeErrorsForEnvelope(status, error) {
7496
8952
  }
7497
8953
  return {
7498
8954
  ...entry,
7499
- message: formatInsufficientCreditsMessage({ billing: billing2, error: message2 }),
8955
+ message: formatInsufficientCreditsMessage({
8956
+ billing: billing2,
8957
+ error: message2
8958
+ }),
7500
8959
  billing: stripProviderSpendFromBilling(billing2)
7501
8960
  };
7502
8961
  });
@@ -7651,7 +9110,9 @@ function buildRunPackageTextLines(packaged) {
7651
9110
  const runId = typeof run.id === "string" ? run.id : "unknown";
7652
9111
  const status = typeof run.status === "string" ? run.status : "unknown";
7653
9112
  const playName = typeof run.playName === "string" ? run.playName : null;
7654
- const lines = [`${status === "completed" ? "\u2713" : status === "failed" ? "\u2717" : "\u2022"} ${status} ${runId}`];
9113
+ const lines = [
9114
+ `${status === "completed" ? "\u2713" : status === "failed" ? "\u2717" : "\u2022"} ${status} ${runId}`
9115
+ ];
7655
9116
  if (playName) {
7656
9117
  lines.push(` play: ${playName}`);
7657
9118
  }
@@ -7722,13 +9183,16 @@ function writePlayResult(status, jsonOutput, options) {
7722
9183
  }
7723
9184
  lines.push(...renderedServerView.actions);
7724
9185
  const payload = options?.fullJson ? enrichPlayStatusWithDatasetStats(status) : compactPlayStatus(status);
7725
- printCommandEnvelope({
7726
- ...payload,
7727
- render: {
7728
- sections: [{ title: "run result", lines }]
7729
- }
7730
- }, { json: jsonOutput, text: `${lines.join("\n")}
7731
- ` });
9186
+ printCommandEnvelope(
9187
+ {
9188
+ ...payload,
9189
+ render: {
9190
+ sections: [{ title: "run result", lines }]
9191
+ }
9192
+ },
9193
+ { json: jsonOutput, text: `${lines.join("\n")}
9194
+ ` }
9195
+ );
7732
9196
  }
7733
9197
  async function resolvePlayRunOutputStatus(input) {
7734
9198
  if (!input.fullJson || !getPlayRunPackage(input.status)) {
@@ -7753,7 +9217,7 @@ function sqlStringLiteral(value) {
7753
9217
  return `'${value.replace(/'/g, "''")}'`;
7754
9218
  }
7755
9219
  function runExportRetryCommand(runId, outPath, datasetPath) {
7756
- return `deepline runs export ${runId}${datasetPath ? ` --dataset ${shellSingleQuote(datasetPath)}` : ""} --out ${shellSingleQuote(resolve9(outPath))}`;
9220
+ return `deepline runs export ${runId}${datasetPath ? ` --dataset ${shellSingleQuote(datasetPath)}` : ""} --out ${shellSingleQuote(resolve10(outPath))}`;
7757
9221
  }
7758
9222
  function extractRunPlayName(status) {
7759
9223
  const run = status.run;
@@ -7787,7 +9251,7 @@ function buildCustomerDbQueryPlan(input) {
7787
9251
  return {
7788
9252
  sql,
7789
9253
  json: `${base} --json`,
7790
- csv: `${base} --format csv --out ${shellSingleQuote(resolve9(input.outPath))}`
9254
+ csv: `${base} --format csv --out ${shellSingleQuote(resolve10(input.outPath))}`
7791
9255
  };
7792
9256
  }
7793
9257
  function exportableSheetRow(row) {
@@ -8087,7 +9551,9 @@ function renderServerResultView(value) {
8087
9551
  (field) => typeof field === "string"
8088
9552
  ) : [];
8089
9553
  if (rawResultFields.length > 0) {
8090
- lines.push(` tool-result columns: ${rawResultFields.join(", ")}`);
9554
+ lines.push(
9555
+ ` tool-result columns: ${rawResultFields.join(", ")}`
9556
+ );
8091
9557
  }
8092
9558
  }
8093
9559
  if (typeof table.slowExportAsCsvCommand === "string") {
@@ -8140,10 +9606,13 @@ function writeStartedPlayRun(input) {
8140
9606
  ` stop run: deepline runs stop ${input.runId} --reason "stale lock" --json`
8141
9607
  ];
8142
9608
  if (input.jsonOutput) {
8143
- printCommandEnvelope({
8144
- ...payload,
8145
- render: { sections: [{ title: "play run", lines }] }
8146
- }, { json: true });
9609
+ printCommandEnvelope(
9610
+ {
9611
+ ...payload,
9612
+ render: { sections: [{ title: "play run", lines }] }
9613
+ },
9614
+ { json: true }
9615
+ );
8147
9616
  return;
8148
9617
  }
8149
9618
  if (input.dashboardUrl) {
@@ -8154,11 +9623,14 @@ function writeStartedPlayRun(input) {
8154
9623
  input.progress.writeLine(output, process.stdout);
8155
9624
  return;
8156
9625
  }
8157
- printCommandEnvelope({
8158
- ...payload,
8159
- render: { sections: [{ title: "play run", lines }] }
8160
- }, { json: false, text: `${output}
8161
- ` });
9626
+ printCommandEnvelope(
9627
+ {
9628
+ ...payload,
9629
+ render: { sections: [{ title: "play run", lines }] }
9630
+ },
9631
+ { json: false, text: `${output}
9632
+ ` }
9633
+ );
8162
9634
  }
8163
9635
  function parsePlayRunOptions(args) {
8164
9636
  const usage = "Usage: deepline plays run <play-name> [--input '{...}'] [--no-wait] [--tail-timeout-ms 30000] [--force] [--full] [--<input> value]\n deepline plays run <play-file.ts> [--input '{...}'] [--no-wait] [--tail-timeout-ms 30000] [--force] [--full] [--<input> value]\n deepline plays run --file <play-file.ts> [--input '{...}'] [--no-wait] [--tail-timeout-ms 30000] [--force] [--full] [--<input> value]\n deepline plays run --name <name> [--input '{...}'] [--live|--latest|--revision-id <id>] [--no-wait] [--tail-timeout-ms 30000] [--force] [--no-open] [--json] [--full] [--<input> value]\n Unknown --<input> value flags, such as --limit 5, are passed into play input.\nRun `deepline plays run --help` for idempotency, tool call id, and ctx.map guidance.";
@@ -8181,7 +9653,7 @@ function parsePlayRunOptions(args) {
8181
9653
  continue;
8182
9654
  }
8183
9655
  if (arg === "--name" && args[index + 1]) {
8184
- playName = parseReferencedPlayTarget(args[++index]).playName;
9656
+ playName = parseReferencedPlayTarget2(args[++index]).playName;
8185
9657
  continue;
8186
9658
  }
8187
9659
  if ((arg === "--input" || arg === "-i") && args[index + 1]) {
@@ -8211,7 +9683,7 @@ function parsePlayRunOptions(args) {
8211
9683
  );
8212
9684
  }
8213
9685
  if ((arg === "--tail-timeout-ms" || arg === "--timeout-ms") && args[index + 1]) {
8214
- waitTimeoutMs = parsePositiveInteger2(args[++index], arg);
9686
+ waitTimeoutMs = parsePositiveInteger3(args[++index], arg);
8215
9687
  continue;
8216
9688
  }
8217
9689
  if (PLAY_RUN_RESERVED_BOOLEAN_FLAGS.has(arg)) {
@@ -8245,7 +9717,7 @@ function parsePlayRunOptions(args) {
8245
9717
  if (isFileTarget(arg) || looksLikeFilePath(arg)) {
8246
9718
  filePath = arg;
8247
9719
  } else {
8248
- playName = parseReferencedPlayTarget(arg).playName;
9720
+ playName = parseReferencedPlayTarget2(arg).playName;
8249
9721
  }
8250
9722
  continue;
8251
9723
  }
@@ -8294,34 +9766,34 @@ function shouldUseLocalOnlyPlayCheck() {
8294
9766
  const value = process.env.DEEPLINE_PLAY_CHECK_LOCAL_ONLY?.trim().toLowerCase();
8295
9767
  return value === "1" || value === "true" || value === "yes" || value === "on";
8296
9768
  }
8297
- function isRecord3(value) {
9769
+ function isRecord4(value) {
8298
9770
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
8299
9771
  }
8300
- function stringValue(value) {
9772
+ function stringValue2(value) {
8301
9773
  return typeof value === "string" ? value.trim() : "";
8302
9774
  }
8303
9775
  function asArray(value) {
8304
9776
  return Array.isArray(value) ? value : [];
8305
9777
  }
8306
- function extractionEntries(value) {
8307
- if (Array.isArray(value)) return value.filter(isRecord3);
8308
- if (!isRecord3(value)) return [];
9778
+ function extractionEntries2(value) {
9779
+ if (Array.isArray(value)) return value.filter(isRecord4);
9780
+ if (!isRecord4(value)) return [];
8309
9781
  return Object.entries(value).map(
8310
- ([name, entry]) => isRecord3(entry) ? { name, ...entry } : { name }
9782
+ ([name, entry]) => isRecord4(entry) ? { name, ...entry } : { name }
8311
9783
  );
8312
9784
  }
8313
9785
  function firstRawPath(entry) {
8314
- const details = isRecord3(entry.details) ? entry.details : {};
9786
+ const details = isRecord4(entry.details) ? entry.details : {};
8315
9787
  const paths = [
8316
9788
  ...asArray(details.rawToolOutputPaths),
8317
9789
  ...asArray(details.raw_tool_output_paths),
8318
9790
  ...asArray(details.candidatePaths),
8319
9791
  ...asArray(details.candidate_paths)
8320
- ].map(stringValue).filter(Boolean);
9792
+ ].map(stringValue2).filter(Boolean);
8321
9793
  return paths[0];
8322
9794
  }
8323
9795
  function checkHintExpression(value) {
8324
- return stringValue(value).replace(/^toolExecutionResult\./, "result.");
9796
+ return stringValue2(value).replace(/^toolExecutionResult\./, "result.");
8325
9797
  }
8326
9798
  function checkHintRawPath(value) {
8327
9799
  return value?.replace(/^toolResponse\./, "result.toolResponse.");
@@ -8329,14 +9801,14 @@ function checkHintRawPath(value) {
8329
9801
  function collectStaticPipelineToolIds(staticPipeline) {
8330
9802
  const seen = /* @__PURE__ */ new Set();
8331
9803
  const visitPipeline = (pipeline) => {
8332
- if (!isRecord3(pipeline)) return;
9804
+ if (!isRecord4(pipeline)) return;
8333
9805
  for (const step of [
8334
9806
  ...asArray(pipeline.stages),
8335
9807
  ...asArray(pipeline.substeps)
8336
9808
  ]) {
8337
- if (!isRecord3(step)) continue;
9809
+ if (!isRecord4(step)) continue;
8338
9810
  if (step.type === "tool") {
8339
- const toolId = stringValue(step.toolId) || stringValue(step.tool);
9811
+ const toolId = stringValue2(step.toolId) || stringValue2(step.tool);
8340
9812
  if (toolId) seen.add(toolId);
8341
9813
  }
8342
9814
  if (step.type === "play_call") {
@@ -8348,20 +9820,20 @@ function collectStaticPipelineToolIds(staticPipeline) {
8348
9820
  return [...seen].sort();
8349
9821
  }
8350
9822
  function toolGetterHintFromMetadata(toolId, tool) {
8351
- const usageGuidance = isRecord3(tool.usageGuidance) ? tool.usageGuidance : {};
8352
- const resultGuidance = isRecord3(usageGuidance.toolExecutionResult) ? usageGuidance.toolExecutionResult : isRecord3(usageGuidance.tool_execution_result) ? usageGuidance.tool_execution_result : {};
8353
- const toolResponse = isRecord3(resultGuidance.toolResponse) ? resultGuidance.toolResponse : isRecord3(resultGuidance.tool_response) ? resultGuidance.tool_response : {};
8354
- const lists = extractionEntries(
9823
+ const usageGuidance = isRecord4(tool.usageGuidance) ? tool.usageGuidance : {};
9824
+ const resultGuidance = isRecord4(usageGuidance.toolExecutionResult) ? usageGuidance.toolExecutionResult : isRecord4(usageGuidance.tool_execution_result) ? usageGuidance.tool_execution_result : {};
9825
+ const toolResponse = isRecord4(resultGuidance.toolResponse) ? resultGuidance.toolResponse : isRecord4(resultGuidance.tool_response) ? resultGuidance.tool_response : {};
9826
+ const lists = extractionEntries2(
8355
9827
  resultGuidance.extractedLists ?? resultGuidance.extracted_lists
8356
9828
  ).map((entry) => ({
8357
- name: stringValue(entry.name),
9829
+ name: stringValue2(entry.name),
8358
9830
  expression: checkHintExpression(entry.expression),
8359
9831
  raw: checkHintRawPath(firstRawPath(entry))
8360
9832
  })).filter((entry) => entry.name && entry.expression);
8361
- const values = extractionEntries(
9833
+ const values = extractionEntries2(
8362
9834
  resultGuidance.extractedValues ?? resultGuidance.extracted_values
8363
9835
  ).map((entry) => ({
8364
- name: stringValue(entry.name),
9836
+ name: stringValue2(entry.name),
8365
9837
  expression: checkHintExpression(entry.expression),
8366
9838
  raw: checkHintRawPath(firstRawPath(entry))
8367
9839
  })).filter((entry) => entry.name && entry.expression);
@@ -8417,11 +9889,11 @@ function printToolGetterHints(hints) {
8417
9889
  async function handlePlayCheck(args) {
8418
9890
  const options = parsePlayCheckOptions(args);
8419
9891
  if (!isFileTarget(options.target)) {
8420
- const resolved = resolve9(options.target);
9892
+ const resolved = resolve10(options.target);
8421
9893
  console.error(`File not found: ${resolved}`);
8422
9894
  return 1;
8423
9895
  }
8424
- const absolutePlayPath = resolve9(options.target);
9896
+ const absolutePlayPath = resolve10(options.target);
8425
9897
  const sourceCode = readFileSync5(absolutePlayPath, "utf-8");
8426
9898
  let graph;
8427
9899
  try {
@@ -8449,8 +9921,10 @@ async function handlePlayCheck(args) {
8449
9921
  graphHash: graph.root.artifact.graphHash
8450
9922
  };
8451
9923
  if (options.jsonOutput) {
8452
- process.stdout.write(`${JSON.stringify({ name: playName, ...result2 })}
8453
- `);
9924
+ process.stdout.write(
9925
+ `${JSON.stringify({ name: playName, ...result2 })}
9926
+ `
9927
+ );
8454
9928
  } else {
8455
9929
  console.log(`\u2713 ${playName} passed local play check`);
8456
9930
  console.log(` artifact: ${result2.artifactHash.slice(0, 12)}`);
@@ -8474,8 +9948,10 @@ async function handlePlayCheck(args) {
8474
9948
  toolGetterHints: result.toolGetterHints ?? await buildToolGetterHints(client, result.staticPipeline)
8475
9949
  };
8476
9950
  if (options.jsonOutput) {
8477
- process.stdout.write(`${JSON.stringify({ name: playName, ...enrichedResult })}
8478
- `);
9951
+ process.stdout.write(
9952
+ `${JSON.stringify({ name: playName, ...enrichedResult })}
9953
+ `
9954
+ );
8479
9955
  } else if (enrichedResult.valid) {
8480
9956
  console.log(`\u2713 ${playName} passed cloud play check`);
8481
9957
  if (enrichedResult.artifactHash) {
@@ -8497,7 +9973,7 @@ async function handleFileBackedRun(options) {
8497
9973
  }
8498
9974
  const client = new DeeplineClient();
8499
9975
  const progress = getActiveCliProgress() ?? createCliProgress(!options.jsonOutput);
8500
- const absolutePlayPath = resolve9(options.target.path);
9976
+ const absolutePlayPath = resolve10(options.target.path);
8501
9977
  progress.phase("compiling play");
8502
9978
  const sourceCode = traceCliSync(
8503
9979
  "cli.play_file_read_source",
@@ -8786,7 +10262,7 @@ async function handlePlayRun(args) {
8786
10262
  if (isFileTarget(options.target.path)) {
8787
10263
  return handleFileBackedRun(options);
8788
10264
  }
8789
- const resolved = resolve9(options.target.path);
10265
+ const resolved = resolve10(options.target.path);
8790
10266
  console.error(`File not found: ${resolved}`);
8791
10267
  const dir = dirname8(resolved);
8792
10268
  if (existsSync6(dir)) {
@@ -8852,7 +10328,7 @@ async function handleRunsList(args) {
8852
10328
  for (let index = 0; index < args.length; index += 1) {
8853
10329
  const arg = args[index];
8854
10330
  if ((arg === "--play" || arg === "--name") && args[index + 1]) {
8855
- playName = parseReferencedPlayTarget(args[++index]).playName;
10331
+ playName = parseReferencedPlayTarget2(args[++index]).playName;
8856
10332
  continue;
8857
10333
  }
8858
10334
  if (arg === "--status" && args[index + 1]) {
@@ -8881,15 +10357,20 @@ async function handleRunsList(args) {
8881
10357
  executionTime: run.executionTime,
8882
10358
  playName: run.memo?.playName ?? playName
8883
10359
  }));
8884
- const lines = runs.length === 0 ? [`No runs found for ${playName}.`] : runs.map((run) => `${run.runId} ${run.status} ${formatTimestamp(run.startedAt)}`);
8885
- printCommandEnvelope({
8886
- runs,
8887
- count: runs.length,
8888
- next: {
8889
- get: runs[0]?.runId ? `deepline runs get ${runs[0].runId} --json` : null
10360
+ const lines = runs.length === 0 ? [`No runs found for ${playName}.`] : runs.map(
10361
+ (run) => `${run.runId} ${run.status} ${formatTimestamp(run.startedAt)}`
10362
+ );
10363
+ printCommandEnvelope(
10364
+ {
10365
+ runs,
10366
+ count: runs.length,
10367
+ next: {
10368
+ get: runs[0]?.runId ? `deepline runs get ${runs[0].runId} --json` : null
10369
+ },
10370
+ render: { sections: [{ title: "runs", lines }] }
8890
10371
  },
8891
- render: { sections: [{ title: "runs", lines }] }
8892
- }, { json: argsWantJson(args) });
10372
+ { json: argsWantJson(args) }
10373
+ );
8893
10374
  return 0;
8894
10375
  }
8895
10376
  async function handleRunTail(args) {
@@ -8904,7 +10385,9 @@ async function handleRunTail(args) {
8904
10385
  for (let index = 0; index < args.length; index += 1) {
8905
10386
  const arg = args[index];
8906
10387
  if (arg === "--cursor") {
8907
- console.error("--cursor was removed. deepline runs tail reads the canonical run stream.");
10388
+ console.error(
10389
+ "--cursor was removed. deepline runs tail reads the canonical run stream."
10390
+ );
8908
10391
  return 1;
8909
10392
  }
8910
10393
  if (arg.startsWith("--") && arg !== "--json" && arg !== "--compact") {
@@ -8931,11 +10414,11 @@ async function handleRunLogs(args) {
8931
10414
  for (let index = 0; index < args.length; index += 1) {
8932
10415
  const arg = args[index];
8933
10416
  if (arg === "--limit" && args[index + 1]) {
8934
- limit = parsePositiveInteger2(args[++index], "--limit");
10417
+ limit = parsePositiveInteger3(args[++index], "--limit");
8935
10418
  continue;
8936
10419
  }
8937
10420
  if (arg === "--out" && args[index + 1]) {
8938
- outPath = resolve9(args[++index]);
10421
+ outPath = resolve10(args[++index]);
8939
10422
  }
8940
10423
  }
8941
10424
  const client = new DeeplineClient();
@@ -8943,30 +10426,46 @@ async function handleRunLogs(args) {
8943
10426
  const logs = status.progress?.logs ?? [];
8944
10427
  if (outPath) {
8945
10428
  writeFileSync6(outPath, `${logs.join("\n")}${logs.length > 0 ? "\n" : ""}`);
8946
- printCommandEnvelope({
8947
- runId: status.runId,
8948
- log_path: outPath,
8949
- lineCount: logs.length,
8950
- local: { log_path: outPath },
8951
- render: { sections: [{ title: "run logs", lines: [`Wrote ${logs.length} log lines to ${outPath}`] }] }
8952
- }, { json: argsWantJson(args) });
10429
+ printCommandEnvelope(
10430
+ {
10431
+ runId: status.runId,
10432
+ log_path: outPath,
10433
+ lineCount: logs.length,
10434
+ local: { log_path: outPath },
10435
+ render: {
10436
+ sections: [
10437
+ {
10438
+ title: "run logs",
10439
+ lines: [`Wrote ${logs.length} log lines to ${outPath}`]
10440
+ }
10441
+ ]
10442
+ }
10443
+ },
10444
+ { json: argsWantJson(args) }
10445
+ );
8953
10446
  return 0;
8954
10447
  }
8955
10448
  const entries = logs.slice(Math.max(0, logs.length - limit));
8956
- printCommandEnvelope({
8957
- runId: status.runId,
8958
- totalCount: logs.length,
8959
- returnedCount: entries.length,
8960
- firstSequence: logs.length === 0 ? null : logs.length - entries.length + 1,
8961
- lastSequence: logs.length === 0 ? null : logs.length,
8962
- truncated: logs.length > entries.length,
8963
- hasMore: logs.length > entries.length,
8964
- entries,
8965
- next: {
8966
- export: `deepline runs logs ${status.runId} --out run.log --json`
10449
+ printCommandEnvelope(
10450
+ {
10451
+ runId: status.runId,
10452
+ totalCount: logs.length,
10453
+ returnedCount: entries.length,
10454
+ firstSequence: logs.length === 0 ? null : logs.length - entries.length + 1,
10455
+ lastSequence: logs.length === 0 ? null : logs.length,
10456
+ truncated: logs.length > entries.length,
10457
+ hasMore: logs.length > entries.length,
10458
+ entries,
10459
+ next: {
10460
+ export: `deepline runs logs ${status.runId} --out run.log --json`
10461
+ },
10462
+ render: { sections: [{ title: "run logs", lines: entries }] }
8967
10463
  },
8968
- render: { sections: [{ title: "run logs", lines: entries }] }
8969
- }, { json: argsWantJson(args), text: `${entries.join("\n")}${entries.length > 0 ? "\n" : ""}` });
10464
+ {
10465
+ json: argsWantJson(args),
10466
+ text: `${entries.join("\n")}${entries.length > 0 ? "\n" : ""}`
10467
+ }
10468
+ );
8970
10469
  return 0;
8971
10470
  }
8972
10471
  async function handleRunStop(args) {
@@ -8991,10 +10490,13 @@ async function handleRunStop(args) {
8991
10490
  `Stopped ${result.runId}`,
8992
10491
  ...result.hitlCancelledCount > 0 ? [`cancelled HITL waits: ${result.hitlCancelledCount}`] : []
8993
10492
  ];
8994
- printCommandEnvelope({
8995
- ...result,
8996
- render: { sections: [{ title: "run stop", lines }] }
8997
- }, { json: argsWantJson(args) });
10493
+ printCommandEnvelope(
10494
+ {
10495
+ ...result,
10496
+ render: { sections: [{ title: "run stop", lines }] }
10497
+ },
10498
+ { json: argsWantJson(args) }
10499
+ );
8998
10500
  return 0;
8999
10501
  }
9000
10502
  async function handleRunExport(args) {
@@ -9012,7 +10514,7 @@ async function handleRunExport(args) {
9012
10514
  for (let index = 0; index < args.length; index += 1) {
9013
10515
  const arg = args[index];
9014
10516
  if (arg === "--out" && args[index + 1]) {
9015
- outPath = resolve9(args[++index]);
10517
+ outPath = resolve10(args[++index]);
9016
10518
  continue;
9017
10519
  }
9018
10520
  if (arg === "--dataset" && args[index + 1]) {
@@ -9020,7 +10522,7 @@ async function handleRunExport(args) {
9020
10522
  continue;
9021
10523
  }
9022
10524
  if (arg === "--metadata-out" && args[index + 1]) {
9023
- metadataOutPath = resolve9(args[++index]);
10525
+ metadataOutPath = resolve10(args[++index]);
9024
10526
  }
9025
10527
  }
9026
10528
  if (!outPath) {
@@ -9107,10 +10609,10 @@ async function handlePlayGet(args) {
9107
10609
  for (let index = 1; index < args.length; index += 1) {
9108
10610
  const arg = args[index];
9109
10611
  if (arg === "--out" && args[index + 1]) {
9110
- outPath = resolve9(args[++index]);
10612
+ outPath = resolve10(args[++index]);
9111
10613
  }
9112
10614
  }
9113
- const playName = isFileTarget(target) ? extractPlayName(readFileSync5(resolve9(target), "utf-8"), resolve9(target)) : parseReferencedPlayTarget(target).playName;
10615
+ const playName = isFileTarget(target) ? extractPlayName(readFileSync5(resolve10(target), "utf-8"), resolve10(target)) : parseReferencedPlayTarget2(target).playName;
9114
10616
  const detail = isFileTarget(target) ? await client.getPlay(playName) : await assertCanonicalNamedPlayReference(client, target);
9115
10617
  const resolvedSource = detail.play.workingRevision?.sourceCode ?? detail.play.liveRevision?.sourceCode ?? detail.play.currentRevision?.sourceCode ?? detail.play.sourceCode ?? "";
9116
10618
  const materializedFile = outPath ? materializeRemotePlaySource({
@@ -9195,7 +10697,7 @@ async function handlePlayVersions(args) {
9195
10697
  const jsonOutput = argsWantJson(args);
9196
10698
  await assertCanonicalNamedPlayReference(client, playName);
9197
10699
  const versions = await client.listPlayVersions(
9198
- parseReferencedPlayTarget(playName).playName
10700
+ parseReferencedPlayTarget2(playName).playName
9199
10701
  );
9200
10702
  if (jsonOutput) {
9201
10703
  process.stdout.write(`${JSON.stringify({ versions })}
@@ -9329,7 +10831,8 @@ function compactPlaySchema(schema) {
9329
10831
  return fields.length > 0 ? { fields } : schema;
9330
10832
  }
9331
10833
  function playSchemaMetadata(schema, key) {
9332
- if (!schema || typeof schema !== "object" || Array.isArray(schema)) return null;
10834
+ if (!schema || typeof schema !== "object" || Array.isArray(schema))
10835
+ return null;
9333
10836
  const value = schema[key];
9334
10837
  return value && typeof value === "object" && !Array.isArray(value) ? value : null;
9335
10838
  }
@@ -9344,7 +10847,10 @@ function playRunCommand(play, options) {
9344
10847
  function summarizePlayListItemForCli(play, options) {
9345
10848
  const aliases = play.aliases?.length ? play.aliases : [play.name];
9346
10849
  const csvInput = playSchemaMetadata(play.inputSchema, "csvInput");
9347
- const rowOutputSchema = playSchemaMetadata(play.outputSchema, "rowOutputSchema");
10850
+ const rowOutputSchema = playSchemaMetadata(
10851
+ play.outputSchema,
10852
+ "rowOutputSchema"
10853
+ );
9348
10854
  const runCommand2 = playRunCommand(play, { csvInput });
9349
10855
  const cloneEditStarter = buildCloneEditStarter(play);
9350
10856
  return {
@@ -9494,7 +11000,7 @@ async function handlePlayDescribe(args) {
9494
11000
  const client = new DeeplineClient();
9495
11001
  await assertCanonicalNamedPlayReference(client, playName);
9496
11002
  const play = await client.describePlay(
9497
- parseReferencedPlayTarget(playName).playName,
11003
+ parseReferencedPlayTarget2(playName).playName,
9498
11004
  {
9499
11005
  compact: args.includes("--compact")
9500
11006
  }
@@ -9540,7 +11046,7 @@ async function handlePlayPublish(args) {
9540
11046
  }
9541
11047
  let graph;
9542
11048
  try {
9543
- graph = await collectBundledPlayGraph(resolve9(playName));
11049
+ graph = await collectBundledPlayGraph(resolve10(playName));
9544
11050
  await compileBundledPlayGraphManifests(client, graph);
9545
11051
  await publishImportedPlayDependencies(client, graph);
9546
11052
  } catch (error) {
@@ -9569,7 +11075,7 @@ async function handlePlayPublish(args) {
9569
11075
  );
9570
11076
  return 0;
9571
11077
  }
9572
- const resolvedName = parseReferencedPlayTarget(playName).playName;
11078
+ const resolvedName = parseReferencedPlayTarget2(playName).playName;
9573
11079
  if (useLatest) {
9574
11080
  const versions = await client.listPlayVersions(resolvedName);
9575
11081
  const latest = versions[0];
@@ -9609,17 +11115,19 @@ async function handlePlayDelete(args) {
9609
11115
  const client = new DeeplineClient();
9610
11116
  let detail;
9611
11117
  try {
9612
- detail = await client.getPlay(parseReferencedPlayTarget(playName).playName);
11118
+ detail = await client.getPlay(parseReferencedPlayTarget2(playName).playName);
9613
11119
  } catch (error) {
9614
11120
  console.error(error instanceof Error ? error.message : String(error));
9615
11121
  return 1;
9616
11122
  }
9617
11123
  if (detail.play.ownerType === "deepline" || detail.play.origin === "prebuilt") {
9618
- console.error(`Cannot delete prebuilt play: ${formatPlayReference(detail.play)}`);
11124
+ console.error(
11125
+ `Cannot delete prebuilt play: ${formatPlayReference(detail.play)}`
11126
+ );
9619
11127
  return 1;
9620
11128
  }
9621
11129
  const result = await client.deletePlay(
9622
- parseReferencedPlayTarget(formatPlayReference(detail.play)).playName
11130
+ parseReferencedPlayTarget2(formatPlayReference(detail.play)).playName
9623
11131
  );
9624
11132
  if (argsWantJson(args)) {
9625
11133
  process.stdout.write(`${JSON.stringify(result)}
@@ -9764,6 +11272,7 @@ Pass-through input flags:
9764
11272
  ...passthroughArgs
9765
11273
  ]);
9766
11274
  });
11275
+ registerPlayBootstrapCommand(play);
9767
11276
  play.command("get <target>").description("Fetch full play details.").addHelpText(
9768
11277
  "after",
9769
11278
  `
@@ -9778,7 +11287,10 @@ Examples:
9778
11287
  deepline plays get prebuilt/name-and-domain-to-email-waterfall-batch --source > email-waterfall.play.ts
9779
11288
  deepline plays get prebuilt/name-and-domain-to-email-waterfall-batch --source --out ./email-waterfall.play.ts
9780
11289
  `
9781
- ).option("--json", "Emit JSON output. Also automatic when stdout is piped").option("--source", "Print raw source code; combine with --out to write a file").option("--out <path>", "Write source to a specific path").action(async (target, options) => {
11290
+ ).option("--json", "Emit JSON output. Also automatic when stdout is piped").option(
11291
+ "--source",
11292
+ "Print raw source code; combine with --out to write a file"
11293
+ ).option("--out <path>", "Write source to a specific path").action(async (target, options) => {
9782
11294
  process.exitCode = await handlePlayGet([
9783
11295
  target,
9784
11296
  ...options.json ? ["--json"] : [],
@@ -9825,7 +11337,9 @@ Examples:
9825
11337
  ]);
9826
11338
  });
9827
11339
  addPlaySearchCommand(play.command("search <query>"));
9828
- play.command("grep <query>").description("Literal grep over play names, aliases, schemas, and descriptions.").addHelpText(
11340
+ play.command("grep <query>").description(
11341
+ "Literal grep over play names, aliases, schemas, and descriptions."
11342
+ ).addHelpText(
9829
11343
  "after",
9830
11344
  `
9831
11345
  Notes:
@@ -9911,7 +11425,9 @@ Examples:
9911
11425
  ]);
9912
11426
  });
9913
11427
  addPublishHelp(
9914
- play.command("set-live <target>").description("Promote a local file or saved revision as the live play revision.")
11428
+ play.command("set-live <target>").description(
11429
+ "Promote a local file or saved revision as the live play revision."
11430
+ )
9915
11431
  ).option("--latest", "Promote the newest saved revision").option("--revision-id <id>", "Revision to promote").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (target, options) => {
9916
11432
  process.exitCode = await handlePlayPublish([
9917
11433
  target,
@@ -9956,7 +11472,9 @@ Examples:
9956
11472
  deepline runs export play/my-play/run/20260501t000000-000 --out output.csv
9957
11473
  `
9958
11474
  );
9959
- runs.command("get <runId>").description("Get status, progress, result, errors, and recovery metadata for a play run.").addHelpText(
11475
+ runs.command("get <runId>").description(
11476
+ "Get status, progress, result, errors, and recovery metadata for a play run."
11477
+ ).addHelpText(
9960
11478
  "after",
9961
11479
  `
9962
11480
  Notes:
@@ -10024,7 +11542,11 @@ Examples:
10024
11542
  deepline runs logs play/my-play/run/20260501t000000-000 --limit 500
10025
11543
  deepline runs logs play/my-play/run/20260501t000000-000 --out run.log --json
10026
11544
  `
10027
- ).option("--limit <count>", "Maximum recent log lines to print without --out", "200").option("--out <path>", "Write the full persisted log stream to a file").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (runId, options) => {
11545
+ ).option(
11546
+ "--limit <count>",
11547
+ "Maximum recent log lines to print without --out",
11548
+ "200"
11549
+ ).option("--out <path>", "Write the full persisted log stream to a file").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (runId, options) => {
10028
11550
  process.exitCode = await handleRunLogs([
10029
11551
  runId,
10030
11552
  ...options.limit ? ["--limit", options.limit] : [],
@@ -10065,7 +11587,10 @@ Examples:
10065
11587
  deepline runs export play/my-play/run/20260501t000000-000 --out output.csv --metadata-out output.meta.json
10066
11588
  deepline runs export play/my-play/run/20260501t000000-000 --out output.csv --json
10067
11589
  `
10068
- ).requiredOption("--out <path>", "Output CSV path").option("--dataset <path>", "Returned dataset handle path, such as result.rows").option("--metadata-out <path>", "Write export metadata JSON to a file").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (runId, options) => {
11590
+ ).requiredOption("--out <path>", "Output CSV path").option(
11591
+ "--dataset <path>",
11592
+ "Returned dataset handle path, such as result.rows"
11593
+ ).option("--metadata-out <path>", "Write export metadata JSON to a file").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (runId, options) => {
10069
11594
  process.exitCode = await handleRunExport([
10070
11595
  runId,
10071
11596
  ...options.dataset ? ["--dataset", options.dataset] : [],
@@ -10293,11 +11818,14 @@ async function listTools(args) {
10293
11818
  const client = new DeeplineClient();
10294
11819
  const categoryArgIndex = args.findIndex((arg) => arg === "--categories");
10295
11820
  const categoryFilter = categoryArgIndex >= 0 ? args[categoryArgIndex + 1] : "";
11821
+ const compact = args.includes("--compact");
10296
11822
  const requestedCategories = categoryFilter ? categoryFilter.split(",").map((item) => item.trim()).filter(Boolean) : [];
10297
11823
  const items = (await client.listTools({
10298
11824
  ...categoryFilter ? { categories: categoryFilter } : {}
10299
11825
  })).map(toListedTool).filter(
10300
- (item) => requestedCategories.length === 0 || requestedCategories.some((category) => item.categories.includes(category))
11826
+ (item) => requestedCategories.length === 0 || requestedCategories.some(
11827
+ (category) => item.categories.includes(category)
11828
+ )
10301
11829
  );
10302
11830
  const render = {
10303
11831
  sections: [
@@ -10317,10 +11845,11 @@ async function listTools(args) {
10317
11845
  }
10318
11846
  ]
10319
11847
  };
11848
+ const outputItems = compact ? items.map(compactTool) : items;
10320
11849
  printCommandEnvelope(
10321
11850
  {
10322
- tools: items,
10323
- count: items.length,
11851
+ tools: outputItems,
11852
+ count: outputItems.length,
10324
11853
  filters: {
10325
11854
  categories: requestedCategories
10326
11855
  },
@@ -10345,7 +11874,11 @@ async function searchTools(queryInput, options = {}) {
10345
11874
  searchMode: options.searchMode,
10346
11875
  includeSearchDebug: options.includeSearchDebug
10347
11876
  });
10348
- printCommandEnvelope(result, {
11877
+ const payload = options.compact && Array.isArray(result.tools) ? {
11878
+ ...result,
11879
+ tools: result.tools.map(compactTool)
11880
+ } : result;
11881
+ printCommandEnvelope(payload, {
10349
11882
  json: options.json || shouldEmitJson()
10350
11883
  });
10351
11884
  return 0;
@@ -10364,7 +11897,9 @@ async function grepTools(queryInput, options = {}) {
10364
11897
  grepMode: mode,
10365
11898
  ...options.categories ? { categories: options.categories } : {}
10366
11899
  })).map(toListedTool).filter(
10367
- (item) => requestedCategories.length === 0 || requestedCategories.some((category) => item.categories.includes(category))
11900
+ (item) => requestedCategories.length === 0 || requestedCategories.some(
11901
+ (category) => item.categories.includes(category)
11902
+ )
10368
11903
  ).filter(
10369
11904
  (item) => matchesGrepQuery(
10370
11905
  {
@@ -10382,10 +11917,11 @@ async function grepTools(queryInput, options = {}) {
10382
11917
  mode
10383
11918
  )
10384
11919
  );
11920
+ const outputTools = options.compact ? tools.map(compactTool) : tools;
10385
11921
  printCommandEnvelope(
10386
11922
  {
10387
- tools,
10388
- count: tools.length,
11923
+ tools: outputTools,
11924
+ count: outputTools.length,
10389
11925
  query,
10390
11926
  grep: {
10391
11927
  mode,
@@ -10400,6 +11936,19 @@ async function grepTools(queryInput, options = {}) {
10400
11936
  );
10401
11937
  return 0;
10402
11938
  }
11939
+ function compactTool(tool) {
11940
+ const listed = toListedTool(tool);
11941
+ return {
11942
+ id: listed.id,
11943
+ toolId: listed.toolId,
11944
+ provider: listed.provider,
11945
+ displayName: listed.displayName,
11946
+ description: listed.description,
11947
+ categories: listed.categories,
11948
+ type: listed.type,
11949
+ executeCommand: listed.executeCommand
11950
+ };
11951
+ }
10403
11952
  function playIdentifiers(play) {
10404
11953
  return [play.name, play.reference, ...play.aliases ?? []].filter((value) => Boolean(value?.trim())).map((value) => value.trim());
10405
11954
  }
@@ -10472,9 +12021,13 @@ Examples:
10472
12021
  deepline tools list --categories email_finder --json
10473
12022
  deepline tools search email --json
10474
12023
  `
10475
- ).option("--categories <categories>", "Comma-separated categories to filter inventory").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (options) => {
12024
+ ).option(
12025
+ "--categories <categories>",
12026
+ "Comma-separated categories to filter inventory"
12027
+ ).option("--compact", "Drop verbose fields from JSON output").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (options) => {
10476
12028
  process.exitCode = await listTools([
10477
12029
  ...options.categories ? ["--categories", options.categories] : [],
12030
+ ...options.compact ? ["--compact"] : [],
10478
12031
  ...options.json ? ["--json"] : []
10479
12032
  ]);
10480
12033
  });
@@ -10492,9 +12045,19 @@ Examples:
10492
12045
  deepline tools grep "company enrichment" --categories enrichment --json
10493
12046
  deepline tools search verifier --search-mode v2 --json
10494
12047
  `
10495
- ).option("--categories <categories>", "Comma-separated categories to filter ranked search").option("--search_terms <terms>", "Structured search terms for ranked search").option("--search-terms <terms>", "Structured search terms for ranked search").option("--search-mode <mode>", "Ranked search mode: v1 or v2").option("--include-search-debug", "Include ranked search debug metadata").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (query, options) => {
12048
+ ).option(
12049
+ "--categories <categories>",
12050
+ "Comma-separated categories to filter ranked search"
12051
+ ).option(
12052
+ "--search_terms <terms>",
12053
+ "Structured search terms for ranked search"
12054
+ ).option(
12055
+ "--search-terms <terms>",
12056
+ "Structured search terms for ranked search"
12057
+ ).option("--search-mode <mode>", "Ranked search mode: v1 or v2").option("--include-search-debug", "Include ranked search debug metadata").option("--compact", "Drop verbose fields from JSON output").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (query, options) => {
10496
12058
  process.exitCode = await searchTools(query, {
10497
12059
  json: options.json,
12060
+ compact: options.compact,
10498
12061
  categories: options.categories,
10499
12062
  searchTerms: options.searchTerms ?? options.search_terms,
10500
12063
  searchMode: options.searchMode === "v1" || options.searchMode === "v2" ? options.searchMode : void 0,
@@ -10502,7 +12065,9 @@ Examples:
10502
12065
  });
10503
12066
  });
10504
12067
  addToolSearchCommand(tools.command("search <query>"));
10505
- tools.command("grep <query>").description("Literal grep over tool ids, descriptions, categories, and input fields.").addHelpText(
12068
+ tools.command("grep <query>").description(
12069
+ "Literal grep over tool ids, descriptions, categories, and input fields."
12070
+ ).addHelpText(
10506
12071
  "after",
10507
12072
  `
10508
12073
  Notes:
@@ -10516,10 +12081,14 @@ Examples:
10516
12081
  deepline tools grep "phone validate" --mode all --json
10517
12082
  deepline tools grep hunter --mode phrase --json
10518
12083
  `
10519
- ).option("--categories <categories>", "Comma-separated categories to filter inventory").option("--mode <mode>", "Grep matching mode: all, any, or phrase").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (query, options) => {
12084
+ ).option(
12085
+ "--categories <categories>",
12086
+ "Comma-separated categories to filter inventory"
12087
+ ).option("--mode <mode>", "Grep matching mode: all, any, or phrase").option("--compact", "Drop verbose fields from JSON output").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (query, options) => {
10520
12088
  const mode = options.mode === "any" || options.mode === "phrase" ? options.mode : "all";
10521
12089
  process.exitCode = await grepTools(query, {
10522
12090
  json: options.json,
12091
+ compact: options.compact,
10523
12092
  categories: options.categories,
10524
12093
  mode
10525
12094
  });
@@ -10540,7 +12109,20 @@ Examples:
10540
12109
  deepline tools describe hunter_email_verifier --json
10541
12110
  deepline tools execute hunter_email_verifier --input '{"email":"a@b.com"}'
10542
12111
  `
10543
- ).option("--json", "Emit JSON output. Also automatic when stdout is piped").option("--pricing-only", "Only print pricing and billing semantics").option("--schema-only", "Only print input schema fields").option("--examples-only", "Only print runnable examples and sample payloads").option("--getters-only", "Only print extracted list/value getters").addOption(new Option("--compact", "Compatibility alias for the default compact view").hideHelp()).addOption(new Option("--contract-json", "Compatibility alias for compact contract JSON").hideHelp()).action(async (toolId, options) => {
12112
+ ).option("--json", "Emit JSON output. Also automatic when stdout is piped").option("--pricing-only", "Only print pricing and billing semantics").option("--schema-only", "Only print input schema fields").option(
12113
+ "--examples-only",
12114
+ "Only print runnable examples and sample payloads"
12115
+ ).option("--getters-only", "Only print extracted list/value getters").addOption(
12116
+ new Option(
12117
+ "--compact",
12118
+ "Compatibility alias for the default compact view"
12119
+ ).hideHelp()
12120
+ ).addOption(
12121
+ new Option(
12122
+ "--contract-json",
12123
+ "Compatibility alias for compact contract JSON"
12124
+ ).hideHelp()
12125
+ ).action(async (toolId, options) => {
10544
12126
  process.exitCode = await getTool(toolId, {
10545
12127
  json: Boolean(options.json),
10546
12128
  compact: Boolean(options.compact),
@@ -10582,13 +12164,24 @@ Examples:
10582
12164
  deepline tools execute hunter_email_verifier -p email=a@b.com
10583
12165
  deepline tools execute test_rate_limit --input '{"key":"smoke"}' --json | jq '.status'
10584
12166
  `
10585
- ).option("-p, --param <key=value>", "Pass one parameter. Repeat for multiple values.", (value, acc) => {
10586
- acc.push(value);
10587
- return acc;
10588
- }, []).option("--json [payload]", "Emit JSON output. Use `--input` or `--payload` for passing JSON params.").option("--input <payload>", "Merge a JSON object into the tool params").option("--payload <payload>", "Merge a JSON object into the tool params").option(
12167
+ ).option(
12168
+ "-p, --param <key=value>",
12169
+ "Pass one parameter. Repeat for multiple values.",
12170
+ (value, acc) => {
12171
+ acc.push(value);
12172
+ return acc;
12173
+ },
12174
+ []
12175
+ ).option(
12176
+ "--json [payload]",
12177
+ "Emit JSON output. Use `--input` or `--payload` for passing JSON params."
12178
+ ).option("--input <payload>", "Merge a JSON object into the tool params").option("--payload <payload>", "Merge a JSON object into the tool params").option(
10589
12179
  "--output-format <format>",
10590
12180
  "Output format: auto, csv, csv_file, json, or json_file"
10591
- ).option("--no-preview", "Only print the extracted output path when applicable").action(async (toolId, options) => {
12181
+ ).option(
12182
+ "--no-preview",
12183
+ "Only print the extracted output path when applicable"
12184
+ ).action(async (toolId, options) => {
10592
12185
  const args = [
10593
12186
  toolId,
10594
12187
  ...options.param.flatMap((value) => ["--param", value]),
@@ -10620,14 +12213,18 @@ async function getTool(toolId, options = {}) {
10620
12213
  throw error;
10621
12214
  }
10622
12215
  if (options.contractJson) {
10623
- process.stdout.write(`${JSON.stringify(toolContractJsonForDescribe(tool, toolId))}
10624
- `);
12216
+ process.stdout.write(
12217
+ `${JSON.stringify(toolContractJsonForDescribe(tool, toolId))}
12218
+ `
12219
+ );
10625
12220
  return 0;
10626
12221
  }
10627
12222
  const emitJson = options.json === true;
10628
12223
  if (emitJson) {
10629
- process.stdout.write(`${JSON.stringify(toolMetadataJsonForDescribe(tool, toolId))}
10630
- `);
12224
+ process.stdout.write(
12225
+ `${JSON.stringify(toolMetadataJsonForDescribe(tool, toolId))}
12226
+ `
12227
+ );
10631
12228
  return 0;
10632
12229
  }
10633
12230
  const onlyModes = [
@@ -10637,7 +12234,9 @@ async function getTool(toolId, options = {}) {
10637
12234
  options.gettersOnly
10638
12235
  ].filter(Boolean).length;
10639
12236
  if (onlyModes > 1) {
10640
- console.error("Use only one of --pricing-only, --schema-only, --examples-only, or --getters-only.");
12237
+ console.error(
12238
+ "Use only one of --pricing-only, --schema-only, --examples-only, or --getters-only."
12239
+ );
10641
12240
  return 2;
10642
12241
  }
10643
12242
  if (options.pricingOnly) {
@@ -10661,8 +12260,10 @@ async function getTool(toolId, options = {}) {
10661
12260
  return 0;
10662
12261
  }
10663
12262
  if (shouldEmitJson()) {
10664
- process.stdout.write(`${JSON.stringify(toolMetadataJsonForDescribe(tool, toolId))}
10665
- `);
12263
+ process.stdout.write(
12264
+ `${JSON.stringify(toolMetadataJsonForDescribe(tool, toolId))}
12265
+ `
12266
+ );
10666
12267
  return 0;
10667
12268
  }
10668
12269
  printCompactToolContract(tool, toolId);
@@ -10670,9 +12271,15 @@ async function getTool(toolId, options = {}) {
10670
12271
  }
10671
12272
  function toolContractJsonForDescribe(tool, requestedToolId) {
10672
12273
  const toolId = String(tool.toolId || requestedToolId);
10673
- const inputFields = toolInputFieldsForDisplay(recordField(tool, "inputSchema", "input_schema"));
12274
+ const inputFields = toolInputFieldsForDisplay(
12275
+ recordField(tool, "inputSchema", "input_schema")
12276
+ );
10674
12277
  const usageGuidance = recordField(tool, "usageGuidance", "usage_guidance");
10675
- const toolExecutionResult = recordField(usageGuidance, "toolExecutionResult", "tool_execution_result");
12278
+ const toolExecutionResult = recordField(
12279
+ usageGuidance,
12280
+ "toolExecutionResult",
12281
+ "tool_execution_result"
12282
+ );
10676
12283
  const extractedLists = extractionContractEntries(
10677
12284
  arrayField(toolExecutionResult, "extractedLists", "extracted_lists")
10678
12285
  );
@@ -10725,7 +12332,7 @@ function toolContractJsonForDescribe(tool, requestedToolId) {
10725
12332
  }
10726
12333
  function extractionContractEntries(entries) {
10727
12334
  return entries.flatMap((entry) => {
10728
- if (!isRecord4(entry)) return [];
12335
+ if (!isRecord5(entry)) return [];
10729
12336
  const name = stringField(entry, "name");
10730
12337
  const expression = stringField(entry, "expression");
10731
12338
  return name && expression ? [{ name, expression }] : [];
@@ -10733,8 +12340,8 @@ function extractionContractEntries(entries) {
10733
12340
  }
10734
12341
  function printCompactToolContract(tool, requestedToolId) {
10735
12342
  const contract = toolContractJsonForDescribe(tool, requestedToolId);
10736
- const cost = isRecord4(contract.cost) ? contract.cost : {};
10737
- const getters = isRecord4(contract.getters) ? contract.getters : {};
12343
+ const cost = isRecord5(contract.cost) ? contract.cost : {};
12344
+ const getters = isRecord5(contract.getters) ? contract.getters : {};
10738
12345
  const listGetters = Array.isArray(getters.extractedLists) ? getters.extractedLists : [];
10739
12346
  const valueGetters = Array.isArray(getters.extractedValues) ? getters.extractedValues : [];
10740
12347
  const inputFields = Array.isArray(contract.inputFields) ? contract.inputFields : [];
@@ -10751,18 +12358,20 @@ function printCompactToolContract(tool, requestedToolId) {
10751
12358
  console.log("");
10752
12359
  console.log("Inputs:");
10753
12360
  for (const field of inputFields) {
10754
- if (!isRecord4(field)) continue;
12361
+ if (!isRecord5(field)) continue;
10755
12362
  const name = stringField(field, "name");
10756
12363
  if (!name) continue;
10757
12364
  const required = field.required ? "*" : "";
10758
12365
  const type = stringField(field, "type") || "unknown";
10759
12366
  const description = stringField(field, "description");
10760
- console.log(`- ${name}${required}: ${type}${description ? ` - ${description}` : ""}`);
12367
+ console.log(
12368
+ `- ${name}${required}: ${type}${description ? ` - ${description}` : ""}`
12369
+ );
10761
12370
  }
10762
12371
  }
10763
12372
  console.log("");
10764
12373
  printToolExamplesOnly(tool, requestedToolId, { includeSamples: false });
10765
- const starterScript = isRecord4(contract.starterScript) ? contract.starterScript : {};
12374
+ const starterScript = isRecord5(contract.starterScript) ? contract.starterScript : {};
10766
12375
  const starterPath = stringField(starterScript, "path");
10767
12376
  if (starterPath) {
10768
12377
  console.log("");
@@ -10774,19 +12383,27 @@ function printCompactToolContract(tool, requestedToolId) {
10774
12383
  console.log("Getters:");
10775
12384
  if (listGetters.length) console.log("Lists:");
10776
12385
  for (const entry of listGetters) {
10777
- if (isRecord4(entry)) console.log(`- ${stringField(entry, "name")}: ${playResultExpression(entry)}`);
12386
+ if (isRecord5(entry))
12387
+ console.log(
12388
+ `- ${stringField(entry, "name")}: ${playResultExpression(entry)}`
12389
+ );
10778
12390
  }
10779
12391
  if (valueGetters.length) console.log("Values:");
10780
12392
  for (const entry of valueGetters) {
10781
- if (isRecord4(entry)) console.log(`- ${stringField(entry, "name")}: ${playResultExpression(entry)}`);
12393
+ if (isRecord5(entry))
12394
+ console.log(
12395
+ `- ${stringField(entry, "name")}: ${playResultExpression(entry)}`
12396
+ );
10782
12397
  }
10783
12398
  }
10784
12399
  console.log("");
10785
- console.log(`More: deepline tools describe ${contract.toolId} --pricing-only | --schema-only | --examples-only | --getters-only | --json`);
12400
+ console.log(
12401
+ `More: deepline tools describe ${contract.toolId} --pricing-only | --schema-only | --examples-only | --getters-only | --json`
12402
+ );
10786
12403
  }
10787
12404
  function printToolPricingOnly(tool, requestedToolId, options = {}) {
10788
12405
  const contract = toolContractJsonForDescribe(tool, requestedToolId);
10789
- const cost = isRecord4(contract.cost) ? contract.cost : {};
12406
+ const cost = isRecord5(contract.cost) ? contract.cost : {};
10790
12407
  const pricingModel = stringField(cost, "pricingModel") || "unknown";
10791
12408
  const billingMode = stringField(cost, "billingMode") || "unknown";
10792
12409
  const unit = pricingModel === "per_page" ? "page" : pricingModel === "per_result" ? "result" : pricingModel === "fixed" ? "call" : pricingModel.replace(/^per_/, "") || "unit";
@@ -10806,14 +12423,16 @@ function printToolSchemaOnly(tool, requestedToolId) {
10806
12423
  }
10807
12424
  console.log("Inputs:");
10808
12425
  for (const field of inputFields) {
10809
- if (!isRecord4(field)) continue;
12426
+ if (!isRecord5(field)) continue;
10810
12427
  const name = stringField(field, "name");
10811
12428
  if (!name) continue;
10812
12429
  const required = field.required ? "*" : "";
10813
12430
  const type = stringField(field, "type") || "unknown";
10814
12431
  const description = stringField(field, "description");
10815
12432
  const defaultSuffix = Object.prototype.hasOwnProperty.call(field, "default") ? ` default=${JSON.stringify(field.default)}` : "";
10816
- console.log(`- ${name}${required}: ${type}${defaultSuffix}${description ? ` - ${description}` : ""}`);
12433
+ console.log(
12434
+ `- ${name}${required}: ${type}${defaultSuffix}${description ? ` - ${description}` : ""}`
12435
+ );
10817
12436
  }
10818
12437
  }
10819
12438
  function printToolExamplesOnly(tool, requestedToolId, options = {}) {
@@ -10826,16 +12445,21 @@ function printToolExamplesOnly(tool, requestedToolId, options = {}) {
10826
12445
  console.log("const result = await ctx.tools.execute({");
10827
12446
  console.log(` id: '${stableStepIdForTool(toolId)}',`);
10828
12447
  console.log(` tool: '${toolId}',`);
10829
- console.log(` input: ${JSON.stringify(sampleInput || {}, null, 2).replace(/\n/g, "\n ")},`);
12448
+ console.log(
12449
+ ` input: ${JSON.stringify(sampleInput || {}, null, 2).replace(/\n/g, "\n ")},`
12450
+ );
10830
12451
  console.log("});");
10831
- const getters = isRecord4(contract.getters) ? contract.getters : {};
12452
+ const getters = isRecord5(contract.getters) ? contract.getters : {};
10832
12453
  const valueGetters = Array.isArray(getters.extractedValues) ? getters.extractedValues : [];
10833
12454
  const listGetters = Array.isArray(getters.extractedLists) ? getters.extractedLists : [];
10834
- const firstGetter = [...valueGetters, ...listGetters].find(isRecord4);
12455
+ const firstGetter = [...valueGetters, ...listGetters].find(isRecord5);
10835
12456
  if (firstGetter) {
10836
12457
  const name = stringField(firstGetter, "name") || "value";
10837
12458
  const expression = stringField(firstGetter, "expression");
10838
- if (expression) console.log(`const ${safeIdentifier(name)} = ${expression.replace(/^toolExecutionResult\./, "result.")};`);
12459
+ if (expression)
12460
+ console.log(
12461
+ `const ${safeIdentifier2(name)} = ${expression.replace(/^toolExecutionResult\./, "result.")};`
12462
+ );
10839
12463
  }
10840
12464
  console.log("```");
10841
12465
  if (options.includeSamples !== false) {
@@ -10845,31 +12469,40 @@ function printToolExamplesOnly(tool, requestedToolId, options = {}) {
10845
12469
  }
10846
12470
  function printToolGettersOnly(tool, requestedToolId) {
10847
12471
  const contract = toolContractJsonForDescribe(tool, requestedToolId);
10848
- const getters = isRecord4(contract.getters) ? contract.getters : {};
12472
+ const getters = isRecord5(contract.getters) ? contract.getters : {};
10849
12473
  const listGetters = Array.isArray(getters.extractedLists) ? getters.extractedLists : [];
10850
12474
  const valueGetters = Array.isArray(getters.extractedValues) ? getters.extractedValues : [];
10851
12475
  console.log(`Getters: ${contract.toolId}`);
10852
12476
  if (!listGetters.length && !valueGetters.length) {
10853
- console.log("No generated getters declared. Use --json only if you need raw metadata.");
12477
+ console.log(
12478
+ "No generated getters declared. Use --json only if you need raw metadata."
12479
+ );
10854
12480
  return;
10855
12481
  }
10856
12482
  if (listGetters.length) {
10857
12483
  console.log("Lists:");
10858
12484
  for (const entry of listGetters) {
10859
- if (isRecord4(entry)) console.log(`- ${stringField(entry, "name")}: ${playResultExpression(entry)}`);
12485
+ if (isRecord5(entry))
12486
+ console.log(
12487
+ `- ${stringField(entry, "name")}: ${playResultExpression(entry)}`
12488
+ );
10860
12489
  }
10861
12490
  }
10862
12491
  if (valueGetters.length) {
10863
12492
  console.log("Values:");
10864
12493
  for (const entry of valueGetters) {
10865
- if (isRecord4(entry)) console.log(`- ${stringField(entry, "name")}: ${playResultExpression(entry)}`);
12494
+ if (isRecord5(entry))
12495
+ console.log(
12496
+ `- ${stringField(entry, "name")}: ${playResultExpression(entry)}`
12497
+ );
10866
12498
  }
10867
12499
  }
10868
12500
  }
10869
12501
  function sampleValueForField(field) {
10870
12502
  const name = stringField(field, "name").toLowerCase();
10871
12503
  const type = stringField(field, "type").toLowerCase();
10872
- if (Object.prototype.hasOwnProperty.call(field, "default")) return field.default;
12504
+ if (Object.prototype.hasOwnProperty.call(field, "default"))
12505
+ return field.default;
10873
12506
  if (name.includes("email")) return "ada@example.com";
10874
12507
  if (name.includes("domain") || name.includes("website")) return "example.com";
10875
12508
  if (name.includes("first")) return "Ada";
@@ -10884,7 +12517,7 @@ function sampleValueForField(field) {
10884
12517
  function samplePayloadForInputFields(fields) {
10885
12518
  return Object.fromEntries(
10886
12519
  fields.slice(0, 4).flatMap((field) => {
10887
- if (!isRecord4(field)) return [];
12520
+ if (!isRecord5(field)) return [];
10888
12521
  const name = stringField(field, "name");
10889
12522
  if (!name) return [];
10890
12523
  return [[name, sampleValueForField(field)]];
@@ -10894,12 +12527,15 @@ function samplePayloadForInputFields(fields) {
10894
12527
  function stableStepIdForTool(toolId) {
10895
12528
  return toolId.replace(/^[a-z0-9]+_/, "").replace(/[^a-z0-9_]+/gi, "_") || "tool_call";
10896
12529
  }
10897
- function safeIdentifier(name) {
12530
+ function safeIdentifier2(name) {
10898
12531
  const cleaned = name.replace(/[^a-zA-Z0-9_$]+/g, "_").replace(/^[^a-zA-Z_$]+/, "");
10899
12532
  return cleaned || "value";
10900
12533
  }
10901
12534
  function playResultExpression(entry) {
10902
- return stringField(entry, "expression").replace(/^toolExecutionResult\./, "result.");
12535
+ return stringField(entry, "expression").replace(
12536
+ /^toolExecutionResult\./,
12537
+ "result."
12538
+ );
10903
12539
  }
10904
12540
  function toolMetadataJsonForDescribe(tool, requestedToolId) {
10905
12541
  const toolId = String(tool.toolId || requestedToolId);
@@ -10990,12 +12626,13 @@ function formatListedToolCost(tool) {
10990
12626
  return displayText ? `Cost: ${displayText}` : "";
10991
12627
  }
10992
12628
  function toolInputFieldsForDisplay(inputSchema) {
10993
- if (Array.isArray(inputSchema.fields)) return inputSchema.fields.filter(isRecord4);
10994
- const jsonSchema = isRecord4(inputSchema.jsonSchema) ? inputSchema.jsonSchema : inputSchema;
10995
- const properties = isRecord4(jsonSchema.properties) ? jsonSchema.properties : {};
12629
+ if (Array.isArray(inputSchema.fields))
12630
+ return inputSchema.fields.filter(isRecord5);
12631
+ const jsonSchema = isRecord5(inputSchema.jsonSchema) ? inputSchema.jsonSchema : inputSchema;
12632
+ const properties = isRecord5(jsonSchema.properties) ? jsonSchema.properties : {};
10996
12633
  const required = Array.isArray(jsonSchema.required) ? new Set(jsonSchema.required.map(String)) : /* @__PURE__ */ new Set();
10997
12634
  return Object.entries(properties).map(([name, value]) => {
10998
- const property = isRecord4(value) ? value : {};
12635
+ const property = isRecord5(value) ? value : {};
10999
12636
  return {
11000
12637
  name,
11001
12638
  type: typeof property.type === "string" ? property.type : "unknown",
@@ -11010,8 +12647,10 @@ function printSamples(samples) {
11010
12647
  const responsePayload = samplePayload(samples, "response");
11011
12648
  if (requestPayload === void 0 && responsePayload === void 0) return;
11012
12649
  console.log(" Samples:");
11013
- if (requestPayload !== void 0) printJsonPreview("Example payload", requestPayload);
11014
- if (responsePayload !== void 0) printJsonPreview("Example response", responsePayload);
12650
+ if (requestPayload !== void 0)
12651
+ printJsonPreview("Example payload", requestPayload);
12652
+ if (responsePayload !== void 0)
12653
+ printJsonPreview("Example response", responsePayload);
11015
12654
  }
11016
12655
  function printJsonPreview(label, payload) {
11017
12656
  console.log(` ${label}:`);
@@ -11022,15 +12661,15 @@ function printJsonPreview(label, payload) {
11022
12661
  }
11023
12662
  function samplePayload(samples, key) {
11024
12663
  const entry = samples[key];
11025
- if (!isRecord4(entry)) return void 0;
12664
+ if (!isRecord5(entry)) return void 0;
11026
12665
  return Object.prototype.hasOwnProperty.call(entry, "payload") ? entry.payload : entry;
11027
12666
  }
11028
12667
  function commandEnvelopeFromRawResponse(rawResponse) {
11029
- return isRecord4(rawResponse) ? { ...rawResponse } : { status: "completed", result: rawResponse };
12668
+ return isRecord5(rawResponse) ? { ...rawResponse } : { status: "completed", result: rawResponse };
11030
12669
  }
11031
12670
  function listExtractorPathsFromUsageGuidance(tool) {
11032
12671
  const toolExecutionResult = tool.usageGuidance?.toolExecutionResult;
11033
- const extractedLists = Array.isArray(toolExecutionResult?.extractedLists) ? toolExecutionResult.extractedLists : isRecord4(toolExecutionResult?.extractedLists) ? Object.values(toolExecutionResult.extractedLists) : [];
12672
+ const extractedLists = Array.isArray(toolExecutionResult?.extractedLists) ? toolExecutionResult.extractedLists : isRecord5(toolExecutionResult?.extractedLists) ? Object.values(toolExecutionResult.extractedLists) : [];
11034
12673
  return extractedLists.flatMap((entry) => {
11035
12674
  const paths = entry.details?.candidatePaths ?? entry.details?.rawToolOutputPaths;
11036
12675
  if (!Array.isArray(paths)) return [];
@@ -11046,7 +12685,7 @@ function formatDecimal(value) {
11046
12685
  function formatUsd(value) {
11047
12686
  return `$${formatDecimal(value)}`;
11048
12687
  }
11049
- function isRecord4(value) {
12688
+ function isRecord5(value) {
11050
12689
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
11051
12690
  }
11052
12691
  function stringField(source, ...keys) {
@@ -11073,7 +12712,7 @@ function arrayField(source, ...keys) {
11073
12712
  function recordField(source, ...keys) {
11074
12713
  for (const key of keys) {
11075
12714
  const value = source[key];
11076
- if (isRecord4(value)) return value;
12715
+ if (isRecord5(value)) return value;
11077
12716
  }
11078
12717
  return {};
11079
12718
  }
@@ -11096,7 +12735,9 @@ function normalizeOutputFormat(raw) {
11096
12735
  function parseExecuteOptions(args) {
11097
12736
  const toolId = args[0];
11098
12737
  if (!toolId) {
11099
- throw new Error(`Usage: deepline tools execute <toolId> [--param key=value ...] [--input '{"k":"v"}'] [--output-format auto|csv|csv_file|json|json_file] [--no-preview]`);
12738
+ throw new Error(
12739
+ `Usage: deepline tools execute <toolId> [--param key=value ...] [--input '{"k":"v"}'] [--output-format auto|csv|csv_file|json|json_file] [--no-preview]`
12740
+ );
11100
12741
  }
11101
12742
  const params = {};
11102
12743
  let outputFormat = "auto";
@@ -11206,7 +12847,7 @@ function buildToolExecuteBaseEnvelope(input) {
11206
12847
  kind: summaryEntries.length > 0 ? "object" : "raw",
11207
12848
  summary: input.summary
11208
12849
  };
11209
- const envelopeHasCanonicalOutput = isRecord4(envelope.toolResponse) && Object.prototype.hasOwnProperty.call(envelope.toolResponse, "raw");
12850
+ const envelopeHasCanonicalOutput = isRecord5(envelope.toolResponse) && Object.prototype.hasOwnProperty.call(envelope.toolResponse, "raw");
11210
12851
  const inspectCommand = `deepline tools execute ${input.toolId} --input ${shellQuote(JSON.stringify(input.params))} --json`;
11211
12852
  const actions = input.listConversion ? [
11212
12853
  {
@@ -11240,7 +12881,9 @@ function buildToolExecuteBaseEnvelope(input) {
11240
12881
  ] : [
11241
12882
  {
11242
12883
  title: "result",
11243
- lines: summaryEntries.length > 0 ? summaryEntries.map(([key, value]) => `${key}=${String(value)}`) : [JSON.stringify(input.rawResponse, null, 2)]
12884
+ lines: summaryEntries.length > 0 ? summaryEntries.map(
12885
+ ([key, value]) => `${key}=${String(value)}`
12886
+ ) : [JSON.stringify(input.rawResponse, null, 2)]
11244
12887
  }
11245
12888
  ],
11246
12889
  actions
@@ -11267,7 +12910,9 @@ async function executeTool(args) {
11267
12910
  const play = await findPlayForToolId(client, parsed.toolId);
11268
12911
  if (play) {
11269
12912
  if (argsWantJson(args)) {
11270
- printJsonError(new Error(playAliasToolErrorMessage(parsed.toolId, play)));
12913
+ printJsonError(
12914
+ new Error(playAliasToolErrorMessage(parsed.toolId, play))
12915
+ );
11271
12916
  } else {
11272
12917
  printPlayAliasToolError(parsed.toolId, play);
11273
12918
  }
@@ -11303,12 +12948,15 @@ async function executeTool(args) {
11303
12948
  return 0;
11304
12949
  }
11305
12950
  if (parsed.outputFormat === "json_file") {
11306
- const jsonPath = writeJsonOutputFile(rawResponse, `payload_${parsed.toolId}`);
12951
+ const jsonPath = writeJsonOutputFile(
12952
+ rawResponse,
12953
+ `payload_${parsed.toolId}`
12954
+ );
11307
12955
  printCommandEnvelope(
11308
12956
  {
11309
12957
  ...baseEnvelope,
11310
12958
  local: {
11311
- ...isRecord4(baseEnvelope.local) ? baseEnvelope.local : {},
12959
+ ...isRecord5(baseEnvelope.local) ? baseEnvelope.local : {},
11312
12960
  payload_file: jsonPath
11313
12961
  }
11314
12962
  },
@@ -11318,7 +12966,10 @@ async function executeTool(args) {
11318
12966
  }
11319
12967
  if (!listConversion) {
11320
12968
  if (parsed.outputFormat === "csv" || parsed.outputFormat === "csv_file") {
11321
- const jsonPath = writeJsonOutputFile(rawResponse, `payload_${parsed.toolId}`);
12969
+ const jsonPath = writeJsonOutputFile(
12970
+ rawResponse,
12971
+ `payload_${parsed.toolId}`
12972
+ );
11322
12973
  printCommandEnvelope(
11323
12974
  {
11324
12975
  ...baseEnvelope,
@@ -11333,7 +12984,10 @@ async function executeTool(args) {
11333
12984
  printCommandEnvelope(baseEnvelope, { json: false });
11334
12985
  return 0;
11335
12986
  }
11336
- const csv = writeCsvOutputFile(listConversion.rows, `${parsed.toolId}_output`);
12987
+ const csv = writeCsvOutputFile(
12988
+ listConversion.rows,
12989
+ `${parsed.toolId}_output`
12990
+ );
11337
12991
  const seededScript = seedToolListScript({
11338
12992
  toolId: parsed.toolId,
11339
12993
  payload: parsed.params,
@@ -11359,7 +13013,9 @@ async function executeTool(args) {
11359
13013
  title: `${csv.path} (${csv.rowCount} rows)`,
11360
13014
  lines: [
11361
13015
  ...csv.columns.length > 0 ? [`columns: ${JSON.stringify(csv.columns)}`] : [],
11362
- ...Object.keys(summary).length > 0 ? [`summary: ${Object.entries(summary).map(([key, value]) => `${key}=${String(value)}`).join(", ")}`] : [],
13016
+ ...Object.keys(summary).length > 0 ? [
13017
+ `summary: ${Object.entries(summary).map(([key, value]) => `${key}=${String(value)}`).join(", ")}`
13018
+ ] : [],
11363
13019
  `preview: ${JSON.stringify(csv.preview)}`,
11364
13020
  `starter script: ${seededScript.path}`
11365
13021
  ]
@@ -11382,22 +13038,25 @@ async function executeTool(args) {
11382
13038
  }
11383
13039
  };
11384
13040
  if (parsed.outputFormat === "csv_file") {
11385
- printCommandEnvelope({
11386
- ...materializedEnvelope,
11387
- extracted_csv: csv.path,
11388
- extracted_csv_rows: csv.rowCount,
11389
- extracted_csv_columns: csv.columns,
11390
- preview: csv.preview,
11391
- list_strategy: listConversion.strategy,
11392
- list_source_path: listConversion.sourcePath,
11393
- starter_script: seededScript.path,
11394
- project_dir: seededScript.projectDir,
11395
- copy_to_project: {
11396
- macos_linux: seededScript.macCopyCommand,
11397
- windows_powershell: seededScript.windowsCopyCommand
13041
+ printCommandEnvelope(
13042
+ {
13043
+ ...materializedEnvelope,
13044
+ extracted_csv: csv.path,
13045
+ extracted_csv_rows: csv.rowCount,
13046
+ extracted_csv_columns: csv.columns,
13047
+ preview: csv.preview,
13048
+ list_strategy: listConversion.strategy,
13049
+ list_source_path: listConversion.sourcePath,
13050
+ starter_script: seededScript.path,
13051
+ project_dir: seededScript.projectDir,
13052
+ copy_to_project: {
13053
+ macos_linux: seededScript.macCopyCommand,
13054
+ windows_powershell: seededScript.windowsCopyCommand
13055
+ },
13056
+ summary
11398
13057
  },
11399
- summary
11400
- }, { json: true });
13058
+ { json: true }
13059
+ );
11401
13060
  return 0;
11402
13061
  }
11403
13062
  if (parsed.noPreview) {
@@ -11421,7 +13080,7 @@ async function executeTool(args) {
11421
13080
  // src/cli/commands/update.ts
11422
13081
  import { spawn } from "child_process";
11423
13082
  import { existsSync as existsSync7 } from "fs";
11424
- import { dirname as dirname9, join as join9, resolve as resolve10 } from "path";
13083
+ import { dirname as dirname9, join as join9, resolve as resolve11 } from "path";
11425
13084
  function posixShellQuote(value) {
11426
13085
  return `'${value.replace(/'/g, `'\\''`)}'`;
11427
13086
  }
@@ -11440,7 +13099,7 @@ function buildSourceUpdateCommand(sourceRoot) {
11440
13099
  return `${cdCommand} && git fetch origin main --tags && git merge --ff-only origin/main`;
11441
13100
  }
11442
13101
  function findRepoBackedSdkRoot(startPath) {
11443
- let current = resolve10(startPath);
13102
+ let current = resolve11(startPath);
11444
13103
  while (true) {
11445
13104
  if (existsSync7(join9(current, "sdk", "package.json")) && existsSync7(join9(current, "sdk", "bin", "deepline-dev.ts"))) {
11446
13105
  return current;
@@ -11451,7 +13110,7 @@ function findRepoBackedSdkRoot(startPath) {
11451
13110
  }
11452
13111
  }
11453
13112
  function resolveUpdatePlan() {
11454
- const entrypoint = process.argv[1] ? resolve10(process.argv[1]) : "";
13113
+ const entrypoint = process.argv[1] ? resolve11(process.argv[1]) : "";
11455
13114
  const sourceRoot = entrypoint ? findRepoBackedSdkRoot(dirname9(entrypoint)) : null;
11456
13115
  if (sourceRoot) {
11457
13116
  return {
@@ -11545,7 +13204,7 @@ Examples:
11545
13204
 
11546
13205
  // src/cli/skills-sync.ts
11547
13206
  import { spawn as spawn2, spawnSync } from "child_process";
11548
- import { existsSync as existsSync8, mkdirSync as mkdirSync5, readdirSync as readdirSync2, readFileSync as readFileSync6, statSync, writeFileSync as writeFileSync9 } from "fs";
13207
+ import { existsSync as existsSync8, mkdirSync as mkdirSync5, readdirSync as readdirSync2, readFileSync as readFileSync6, statSync as statSync2, writeFileSync as writeFileSync9 } from "fs";
11549
13208
  import { homedir as homedir4 } from "os";
11550
13209
  import { dirname as dirname10, join as join10 } from "path";
11551
13210
  var CHECK_TIMEOUT_MS2 = 3e3;
@@ -11591,7 +13250,7 @@ function installedSdkSkillHasStalePositionalExecuteExamples() {
11591
13250
  const scan = (dir) => {
11592
13251
  for (const entry of readdirSync2(dir)) {
11593
13252
  const path = join10(dir, entry);
11594
- const stat3 = statSync(path);
13253
+ const stat3 = statSync2(path);
11595
13254
  if (stat3.isDirectory()) {
11596
13255
  if (scan(path)) return true;
11597
13256
  continue;
@@ -11702,7 +13361,7 @@ function resolveSkillsInstallCommands(baseUrl) {
11702
13361
  return [npxInstall];
11703
13362
  }
11704
13363
  function runOneSkillsInstall(install) {
11705
- return new Promise((resolve11) => {
13364
+ return new Promise((resolve12) => {
11706
13365
  const child = spawn2(install.command, install.args, {
11707
13366
  stdio: ["ignore", "ignore", "pipe"],
11708
13367
  env: process.env
@@ -11712,7 +13371,7 @@ function runOneSkillsInstall(install) {
11712
13371
  stderr += chunk.toString("utf-8");
11713
13372
  });
11714
13373
  child.on("error", (error) => {
11715
- resolve11({
13374
+ resolve12({
11716
13375
  ok: false,
11717
13376
  detail: `failed to start ${install.command}: ${error.message}`,
11718
13377
  manualCommand: install.manualCommand
@@ -11720,11 +13379,11 @@ function runOneSkillsInstall(install) {
11720
13379
  });
11721
13380
  child.on("close", (code) => {
11722
13381
  if (code === 0) {
11723
- resolve11({ ok: true, detail: "", manualCommand: install.manualCommand });
13382
+ resolve12({ ok: true, detail: "", manualCommand: install.manualCommand });
11724
13383
  return;
11725
13384
  }
11726
13385
  const detail = stderr.trim();
11727
- resolve11({
13386
+ resolve12({
11728
13387
  ok: false,
11729
13388
  detail: detail ? `${install.command}: ${detail}` : `${install.command} exited ${code}`,
11730
13389
  manualCommand: install.manualCommand