deepline 0.1.57 → 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.
package/dist/cli/index.js CHANGED
@@ -25,7 +25,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
25
25
 
26
26
  // src/cli/index.ts
27
27
  var import_promises5 = require("fs/promises");
28
- var import_node_path15 = require("path");
28
+ var import_node_path16 = require("path");
29
29
  var import_node_os9 = require("os");
30
30
  var import_commander3 = require("commander");
31
31
 
@@ -220,10 +220,10 @@ function resolveConfig(options) {
220
220
 
221
221
  // src/release.ts
222
222
  var SDK_RELEASE = {
223
- version: "0.1.57",
223
+ version: "0.1.58",
224
224
  apiContract: "2026-05-play-tool-describe-starters",
225
225
  supportPolicy: {
226
- latest: "0.1.57",
226
+ latest: "0.1.58",
227
227
  minimumSupported: "0.1.53",
228
228
  deprecatedBelow: "0.1.53"
229
229
  }
@@ -361,8 +361,8 @@ var HttpClient = class {
361
361
  if (lastError instanceof DeeplineError) {
362
362
  throw lastError;
363
363
  }
364
- const errorMessage = lastError?.message ? `Unable to connect to ${baseUrl}. ${lastError.message}` : `Unable to connect to ${baseUrl}. Is the computer able to access the url?`;
365
- throw new DeeplineError(errorMessage);
364
+ const errorMessage2 = lastError?.message ? `Unable to connect to ${baseUrl}. ${lastError.message}` : `Unable to connect to ${baseUrl}. Is the computer able to access the url?`;
365
+ throw new DeeplineError(errorMessage2);
366
366
  }
367
367
  /**
368
368
  * Send a GET request.
@@ -535,7 +535,7 @@ function decodeSseFrame(frame) {
535
535
  return parsed;
536
536
  }
537
537
  function sleep(ms) {
538
- return new Promise((resolve11) => setTimeout(resolve11, ms));
538
+ return new Promise((resolve12) => setTimeout(resolve12, ms));
539
539
  }
540
540
 
541
541
  // src/client.ts
@@ -545,7 +545,7 @@ var EXECUTE_RESPONSE_CONTRACT_HEADER = "x-deepline-execute-response-contract";
545
545
  var V2_EXECUTE_RESPONSE_CONTRACT = "v2-tool-response";
546
546
  var COMPILE_MANIFEST_RETRY_DELAYS_MS = [250, 1e3];
547
547
  function sleep2(ms) {
548
- return new Promise((resolve11) => setTimeout(resolve11, ms));
548
+ return new Promise((resolve12) => setTimeout(resolve12, ms));
549
549
  }
550
550
  function isTransientCompileManifestError(error) {
551
551
  if (error instanceof DeeplineError && typeof error.statusCode === "number") {
@@ -2276,7 +2276,7 @@ function buildCandidateUrls2(url) {
2276
2276
  }
2277
2277
  }
2278
2278
  function sleep3(ms) {
2279
- return new Promise((resolve11) => setTimeout(resolve11, ms));
2279
+ return new Promise((resolve12) => setTimeout(resolve12, ms));
2280
2280
  }
2281
2281
  function printDeeplineLogo() {
2282
2282
  if (process.stdout.isTTY && (process.stdout.columns ?? 80) >= 70) {
@@ -4025,8 +4025,8 @@ Examples:
4025
4025
 
4026
4026
  // src/cli/commands/play.ts
4027
4027
  var import_node_crypto3 = require("crypto");
4028
- var import_node_fs8 = require("fs");
4029
- var import_node_path10 = require("path");
4028
+ var import_node_fs9 = require("fs");
4029
+ var import_node_path11 = require("path");
4030
4030
 
4031
4031
  // src/plays/bundle-play-file.ts
4032
4032
  var import_node_os5 = require("os");
@@ -4379,6 +4379,9 @@ function localSdkAliasPlugin(adapter, options) {
4379
4379
  buildContext.onResolve({ filter: /^deepline$/ }, () => ({
4380
4380
  path: entryFile
4381
4381
  }));
4382
+ buildContext.onResolve({ filter: /^deepline\/helpers$/ }, () => ({
4383
+ path: (0, import_node_path7.join)(adapter.sdkSourceRoot, "helpers.ts")
4384
+ }));
4382
4385
  }
4383
4386
  };
4384
4387
  }
@@ -5552,41 +5555,1478 @@ function warnAboutNonDevelopmentBundling(filePath) {
5552
5555
  if (!nodeEnv || nodeEnv === "development" || nodeEnv === "test") {
5553
5556
  return;
5554
5557
  }
5555
- hasWarnedAboutNonDevelopmentBundling = true;
5556
- console.warn(
5557
- `[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.`
5558
- );
5559
- console.warn(
5560
- '[deepline] Preferred production call pattern: client.play("person-to-email").run(...) or run a previously registered/published org play.'
5561
- );
5558
+ hasWarnedAboutNonDevelopmentBundling = true;
5559
+ console.warn(
5560
+ `[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.`
5561
+ );
5562
+ console.warn(
5563
+ '[deepline] Preferred production call pattern: client.play("person-to-email").run(...) or run a previously registered/published org play.'
5564
+ );
5565
+ }
5566
+ function defaultPlayBundleTarget() {
5567
+ return resolveExecutionProfile(null).artifactKind;
5568
+ }
5569
+ function createSdkPlayBundlingAdapter() {
5570
+ return {
5571
+ projectRoot: PROJECT_ROOT,
5572
+ nodeModulesDir: (0, import_node_path9.resolve)(PROJECT_ROOT, "node_modules"),
5573
+ cacheDir: (0, import_node_path9.join)(
5574
+ (0, import_node_os5.tmpdir)(),
5575
+ `deepline-play-artifacts-v${PLAY_BUNDLE_CACHE_VERSION2}`
5576
+ ),
5577
+ sdkSourceRoot: SDK_SOURCE_ROOT,
5578
+ sdkPackageJson: SDK_PACKAGE_JSON,
5579
+ sdkEntryFile: SDK_ENTRY_FILE,
5580
+ sdkTypesEntryFile: HAS_SOURCE_BUNDLING_SOURCES || !(0, import_node_fs7.existsSync)(SDK_TYPES_ENTRY_FILE) ? SDK_ENTRY_FILE : SDK_TYPES_ENTRY_FILE,
5581
+ sdkWorkersEntryFile: SDK_WORKERS_ENTRY_FILE,
5582
+ workersHarnessEntryFile: WORKERS_HARNESS_ENTRY_FILE,
5583
+ workersHarnessFilesDir: WORKERS_HARNESS_FILES_DIR,
5584
+ discoverPackagedLocalFiles,
5585
+ warnAboutNonDevelopmentBundling
5586
+ };
5587
+ }
5588
+ async function bundlePlayFile2(filePath, options = {}) {
5589
+ return bundlePlayFile(filePath, {
5590
+ target: options.target ?? defaultPlayBundleTarget(),
5591
+ exportName: options.exportName,
5592
+ adapter: createSdkPlayBundlingAdapter()
5593
+ });
5594
+ }
5595
+
5596
+ // src/cli/commands/plays/bootstrap.ts
5597
+ var import_node_fs8 = require("fs");
5598
+ var import_node_path10 = require("path");
5599
+ var import_sync4 = require("csv-parse/sync");
5600
+
5601
+ // ../shared_libs/plays/bootstrap-routes.ts
5602
+ var PLAY_BOOTSTRAP_TEMPLATES = [
5603
+ "people-list",
5604
+ "company-list",
5605
+ "people-email",
5606
+ "people-phone",
5607
+ "company-people",
5608
+ "company-people-email",
5609
+ "company-people-phone"
5610
+ ];
5611
+ var PLAY_BOOTSTRAP_COMPANY_PROVIDER_CATEGORY = "company_search";
5612
+ var PLAY_BOOTSTRAP_PEOPLE_PROVIDER_CATEGORY = "people_search";
5613
+ var PLAY_BOOTSTRAP_PROVIDER_CATEGORY_BY_FINDER = {
5614
+ email_finder: "email_finder",
5615
+ phone_finder: "phone_finder"
5616
+ };
5617
+ var PLAY_BOOTSTRAP_OUTPUT_FIELD_BY_FINDER = {
5618
+ email_finder: "email",
5619
+ phone_finder: "phone"
5620
+ };
5621
+ function isPlayBootstrapTemplate(value) {
5622
+ return PLAY_BOOTSTRAP_TEMPLATES.includes(value);
5623
+ }
5624
+ function formatPlayBootstrapTemplates() {
5625
+ return PLAY_BOOTSTRAP_TEMPLATES.join("|");
5626
+ }
5627
+
5628
+ // src/cli/commands/plays/bootstrap.ts
5629
+ function parseReferencedPlayTarget(target) {
5630
+ const trimmed = target.trim();
5631
+ const slashIndex = trimmed.indexOf("/");
5632
+ if (slashIndex <= 0 || slashIndex === trimmed.length - 1) {
5633
+ return { ownerSlug: null, playName: trimmed, unqualifiedPlayName: trimmed };
5634
+ }
5635
+ return {
5636
+ ownerSlug: trimmed.slice(0, slashIndex),
5637
+ playName: trimmed,
5638
+ unqualifiedPlayName: trimmed.slice(slashIndex + 1)
5639
+ };
5640
+ }
5641
+ function parsePositiveInteger2(value, flagName) {
5642
+ const parsed = Number.parseInt(value, 10);
5643
+ if (!Number.isFinite(parsed) || parsed <= 0) {
5644
+ throw new PlayBootstrapUsageError(
5645
+ `${flagName} must be a positive integer.`
5646
+ );
5647
+ }
5648
+ return parsed;
5649
+ }
5650
+ function isRecord3(value) {
5651
+ return Boolean(value && typeof value === "object" && !Array.isArray(value));
5652
+ }
5653
+ function stringValue(value) {
5654
+ return typeof value === "string" ? value.trim() : "";
5655
+ }
5656
+ function extractionEntries(value) {
5657
+ if (Array.isArray(value)) return value.filter(isRecord3);
5658
+ if (!isRecord3(value)) return [];
5659
+ return Object.entries(value).map(
5660
+ ([name, entry]) => isRecord3(entry) ? { name, ...entry } : { name }
5661
+ );
5662
+ }
5663
+ var PlayBootstrapError = class extends Error {
5664
+ constructor(message, exitCode) {
5665
+ super(message);
5666
+ this.exitCode = exitCode;
5667
+ }
5668
+ exitCode;
5669
+ };
5670
+ var PlayBootstrapUsageError = class extends PlayBootstrapError {
5671
+ constructor(message) {
5672
+ super(message, 2);
5673
+ }
5674
+ };
5675
+ var PlayBootstrapValidationError = class extends PlayBootstrapError {
5676
+ constructor(message) {
5677
+ super(message, 7);
5678
+ }
5679
+ };
5680
+ var CSV_HEADER_SAMPLE_BYTES = 64 * 1024;
5681
+ function parseCsvList(value) {
5682
+ return value.split(",").map((item) => item.trim()).filter(Boolean);
5683
+ }
5684
+ function parseProviderList(value, flag) {
5685
+ const providers = parseCsvList(value);
5686
+ if (providers.length === 0) {
5687
+ throw new PlayBootstrapUsageError(`${flag} provider list cannot be empty.`);
5688
+ }
5689
+ return providers;
5690
+ }
5691
+ function parseBootstrapPrefixedRef(value, flag) {
5692
+ const separatorIndex = value.indexOf(":");
5693
+ if (separatorIndex <= 0 || separatorIndex === value.length - 1) {
5694
+ throw new PlayBootstrapUsageError(
5695
+ `${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.`
5696
+ );
5697
+ }
5698
+ return {
5699
+ prefix: value.slice(0, separatorIndex).trim(),
5700
+ body: value.slice(separatorIndex + 1).trim()
5701
+ };
5702
+ }
5703
+ function parseBootstrapSourceRef(value, flag = "--from") {
5704
+ const { prefix, body } = parseBootstrapPrefixedRef(value, flag);
5705
+ switch (prefix) {
5706
+ case "csv":
5707
+ return { kind: "csv", value: body };
5708
+ case "play":
5709
+ return { kind: "play", value: parseReferencedPlayTarget(body).playName };
5710
+ case "provider":
5711
+ case "providers":
5712
+ return { kind: "providers", values: parseProviderList(body, flag) };
5713
+ }
5714
+ throw new PlayBootstrapUsageError(
5715
+ `${flag} does not support ${prefix}:. Use csv:, play:, provider:, or providers:.`
5716
+ );
5717
+ }
5718
+ function parseBootstrapStageRef(value, flag) {
5719
+ const { prefix, body } = parseBootstrapPrefixedRef(value, flag);
5720
+ switch (prefix) {
5721
+ case "play":
5722
+ return { kind: "play", value: parseReferencedPlayTarget(body).playName };
5723
+ case "provider":
5724
+ case "providers":
5725
+ return { kind: "providers", values: parseProviderList(body, flag) };
5726
+ }
5727
+ throw new PlayBootstrapUsageError(
5728
+ `${flag} does not support ${prefix}:. Use play:, provider:, or providers:.`
5729
+ );
5730
+ }
5731
+ function playBootstrapTemplateConfig(template) {
5732
+ switch (template) {
5733
+ case "company-list":
5734
+ return { sourceEntity: "company", usingStage: null, requiredStages: [] };
5735
+ case "people-list":
5736
+ return { sourceEntity: "people", usingStage: null, requiredStages: [] };
5737
+ case "people-email":
5738
+ return {
5739
+ sourceEntity: "people",
5740
+ usingStage: "email",
5741
+ requiredStages: []
5742
+ };
5743
+ case "people-phone":
5744
+ return {
5745
+ sourceEntity: "people",
5746
+ usingStage: "phone",
5747
+ requiredStages: []
5748
+ };
5749
+ case "company-people":
5750
+ return {
5751
+ sourceEntity: "company",
5752
+ usingStage: "people",
5753
+ requiredStages: []
5754
+ };
5755
+ case "company-people-email":
5756
+ return {
5757
+ sourceEntity: "company",
5758
+ usingStage: null,
5759
+ requiredStages: ["people", "email"]
5760
+ };
5761
+ case "company-people-phone":
5762
+ return {
5763
+ sourceEntity: "company",
5764
+ usingStage: null,
5765
+ requiredStages: ["people", "phone"]
5766
+ };
5767
+ }
5768
+ }
5769
+ function templateExample(template) {
5770
+ switch (template) {
5771
+ case "people-list":
5772
+ return "deepline plays bootstrap people-list --from provider:dropleads_search_people > people.play.ts";
5773
+ case "company-list":
5774
+ return "deepline plays bootstrap company-list --from provider:apollo_company_search > companies.play.ts";
5775
+ case "people-email":
5776
+ return "deepline plays bootstrap people-email --from csv:data/leads.csv --using play:prebuilt/name-and-domain-to-email-waterfall > email-flow.play.ts";
5777
+ case "people-phone":
5778
+ return "deepline plays bootstrap people-phone --from csv:data/vp_contacts.csv --using play:prebuilt/person-to-phone > phone-flow.play.ts";
5779
+ case "company-people":
5780
+ return "deepline plays bootstrap company-people --from provider:apollo_company_search --using play:prebuilt/company-to-contact > company-people.play.ts";
5781
+ case "company-people-email":
5782
+ 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";
5783
+ case "company-people-phone":
5784
+ 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";
5785
+ }
5786
+ }
5787
+ var PLAY_BOOTSTRAP_STAGE_NAMES = [
5788
+ "people",
5789
+ "email",
5790
+ "phone"
5791
+ ];
5792
+ function playBootstrapUsageLine() {
5793
+ 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`;
5794
+ }
5795
+ function requireBootstrapTemplate(rawTemplate) {
5796
+ if (!rawTemplate) {
5797
+ throw new PlayBootstrapUsageError(
5798
+ `plays bootstrap needs a route template: ${formatPlayBootstrapTemplates()}.
5799
+ Example: deepline plays bootstrap people-email --from csv:data/leads.csv --using play:prebuilt/name-and-domain-to-email-waterfall > email-flow.play.ts`
5800
+ );
5801
+ }
5802
+ if (!isPlayBootstrapTemplate(rawTemplate)) {
5803
+ throw new PlayBootstrapUsageError(
5804
+ `Unknown plays bootstrap template: ${rawTemplate}
5805
+ Supported templates: ${formatPlayBootstrapTemplates()}`
5806
+ );
5807
+ }
5808
+ return rawTemplate;
5809
+ }
5810
+ function nextFlagValue(args, index, flag) {
5811
+ const value = args[index + 1];
5812
+ if (!value || value.startsWith("--")) {
5813
+ throw new PlayBootstrapUsageError(`${flag} needs a value.`);
5814
+ }
5815
+ return value;
5816
+ }
5817
+ function stageFlag(stage) {
5818
+ return `--${stage}`;
5819
+ }
5820
+ function stageRefHelp(stage) {
5821
+ switch (stage) {
5822
+ case "people":
5823
+ return "play:<people-play>";
5824
+ case "email":
5825
+ case "phone":
5826
+ return "<play:REF|provider:ID|providers:ID,ID>";
5827
+ }
5828
+ }
5829
+ function getStageRef(options, stage) {
5830
+ switch (stage) {
5831
+ case "people":
5832
+ return options.people;
5833
+ case "email":
5834
+ return options.email;
5835
+ case "phone":
5836
+ return options.phone;
5837
+ }
5838
+ }
5839
+ function setStageRef(options, stage, ref) {
5840
+ switch (stage) {
5841
+ case "people":
5842
+ options.people = ref;
5843
+ return;
5844
+ case "email":
5845
+ options.email = ref;
5846
+ return;
5847
+ case "phone":
5848
+ options.phone = ref;
5849
+ return;
5850
+ }
5851
+ }
5852
+ function unsupportedStageMessage(template, stage) {
5853
+ switch (stage) {
5854
+ case "people":
5855
+ return `${template} does not accept --people. Use company-people, company-people-email, or company-people-phone.`;
5856
+ case "email":
5857
+ return `${template} does not accept --email. Use people-email or company-people-email.`;
5858
+ case "phone":
5859
+ return `${template} does not accept --phone. Use people-phone or company-people-phone.`;
5860
+ }
5861
+ }
5862
+ function requireSource(options) {
5863
+ if (!options.from) {
5864
+ throw new PlayBootstrapUsageError(
5865
+ `${options.template} needs --from.
5866
+ Example: ${templateExample(options.template)}`
5867
+ );
5868
+ }
5869
+ return options.from;
5870
+ }
5871
+ function assertAllowedStageFlags(options, allowedStages) {
5872
+ const allowed = new Set(allowedStages);
5873
+ for (const stage of PLAY_BOOTSTRAP_STAGE_NAMES) {
5874
+ if (!allowed.has(stage) && getStageRef(options, stage)) {
5875
+ throw new PlayBootstrapUsageError(
5876
+ unsupportedStageMessage(options.template, stage)
5877
+ );
5878
+ }
5879
+ }
5880
+ }
5881
+ function assertRequiredStages(options, stages) {
5882
+ for (const stage of stages) {
5883
+ if (!getStageRef(options, stage)) {
5884
+ throw new PlayBootstrapUsageError(
5885
+ `${options.template} needs ${stageFlag(stage)} ${stageRefHelp(stage)}.
5886
+ Example: ${templateExample(options.template)}`
5887
+ );
5888
+ }
5889
+ }
5890
+ }
5891
+ function normalizeSingleStageRoute(options, stage) {
5892
+ const explicitStage = getStageRef(options, stage);
5893
+ if (options.using && explicitStage) {
5894
+ throw new PlayBootstrapUsageError(
5895
+ `${options.template} received both --using and ${stageFlag(stage)}. Choose one stage binding.`
5896
+ );
5897
+ }
5898
+ const selectedStage = options.using ?? explicitStage;
5899
+ if (!selectedStage) {
5900
+ throw new PlayBootstrapUsageError(
5901
+ `${options.template} needs --using ${stageRefHelp(stage)} or ${stageFlag(stage)} ${stageRefHelp(stage)}.
5902
+ Example: ${templateExample(options.template)}`
5903
+ );
5904
+ }
5905
+ setStageRef(options, stage, selectedStage);
5906
+ options.using = selectedStage;
5907
+ assertAllowedStageFlags(options, [stage]);
5908
+ }
5909
+ function normalizeMultiStageRoute(options, stages) {
5910
+ if (options.using) {
5911
+ throw new PlayBootstrapUsageError(
5912
+ `${options.template} does not accept --using. Use the explicit stage flags shown in: ${templateExample(options.template)}`
5913
+ );
5914
+ }
5915
+ assertRequiredStages(options, stages);
5916
+ assertAllowedStageFlags(options, stages);
5917
+ }
5918
+ function normalizeTemplateStages(options) {
5919
+ const config = playBootstrapTemplateConfig(options.template);
5920
+ const from = requireSource(options);
5921
+ switch (config.usingStage) {
5922
+ case "people":
5923
+ case "email":
5924
+ case "phone":
5925
+ normalizeSingleStageRoute(options, config.usingStage);
5926
+ break;
5927
+ case null:
5928
+ normalizeMultiStageRoute(options, config.requiredStages);
5929
+ break;
5930
+ }
5931
+ return {
5932
+ ...options,
5933
+ from
5934
+ };
5935
+ }
5936
+ function parsePlayBootstrapOptions(args) {
5937
+ const [rawTemplate, ...rest] = args;
5938
+ const template = requireBootstrapTemplate(rawTemplate);
5939
+ const options = {
5940
+ template,
5941
+ name: `gtm-${template}`,
5942
+ from: null,
5943
+ using: null,
5944
+ people: null,
5945
+ email: null,
5946
+ phone: null,
5947
+ limit: 5
5948
+ };
5949
+ for (let index = 0; index < rest.length; index += 1) {
5950
+ const arg = rest[index];
5951
+ const value = () => nextFlagValue(rest, index, arg);
5952
+ switch (arg) {
5953
+ case "--name":
5954
+ options.name = value();
5955
+ index += 1;
5956
+ break;
5957
+ case "--from":
5958
+ options.from = parseBootstrapSourceRef(value(), "--from");
5959
+ index += 1;
5960
+ break;
5961
+ case "--using":
5962
+ options.using = parseBootstrapStageRef(value(), "--using");
5963
+ index += 1;
5964
+ break;
5965
+ case "--people":
5966
+ options.people = parseBootstrapStageRef(value(), "--people");
5967
+ index += 1;
5968
+ break;
5969
+ case "--email":
5970
+ options.email = parseBootstrapStageRef(value(), "--email");
5971
+ index += 1;
5972
+ break;
5973
+ case "--phone":
5974
+ options.phone = parseBootstrapStageRef(value(), "--phone");
5975
+ index += 1;
5976
+ break;
5977
+ case "--limit":
5978
+ options.limit = parsePositiveInteger2(value(), "--limit");
5979
+ index += 1;
5980
+ break;
5981
+ default:
5982
+ throw new PlayBootstrapUsageError(
5983
+ `Unknown plays bootstrap option: ${arg}
5984
+ ${playBootstrapUsageLine()}`
5985
+ );
5986
+ }
5987
+ }
5988
+ return normalizeTemplateStages(options);
5989
+ }
5990
+ function jsString(value) {
5991
+ return JSON.stringify(value);
5992
+ }
5993
+ function inferCsvCellTypeExpression(values) {
5994
+ const nonEmptyValues = values.map((value) => value.trim()).filter((value) => value.length > 0);
5995
+ const hasEmptyValue = values.some((value) => value.trim().length === 0);
5996
+ if (nonEmptyValues.length === 0) return "string";
5997
+ const numericPattern = /^[+-]?(?:(?:\d+\.?\d*)|(?:\.\d+))(?:[eE][+-]?\d+)?$/;
5998
+ const booleanPattern = /^(?:true|false)$/i;
5999
+ let inferred = "string";
6000
+ if (nonEmptyValues.every((value) => numericPattern.test(value))) {
6001
+ inferred = "`${number}`";
6002
+ } else if (nonEmptyValues.every((value) => booleanPattern.test(value))) {
6003
+ const canonicalBooleanValues = nonEmptyValues.every(
6004
+ (value) => value === "true" || value === "false"
6005
+ );
6006
+ inferred = canonicalBooleanValues ? '"false" | "true"' : [...new Set(nonEmptyValues)].sort().map(jsString).join(" | ");
6007
+ }
6008
+ return hasEmptyValue && inferred !== "string" ? `${inferred} | ""` : inferred;
6009
+ }
6010
+ function inferCsvColumnSpecs(headers, rows) {
6011
+ return headers.map((header) => ({
6012
+ name: header,
6013
+ typeExpression: inferCsvCellTypeExpression(
6014
+ rows.map((row) => String(row[header] ?? ""))
6015
+ )
6016
+ }));
6017
+ }
6018
+ function readCsvSample(csvPath) {
6019
+ const resolvedPath = (0, import_node_path10.resolve)(csvPath);
6020
+ const size = (0, import_node_fs8.statSync)(resolvedPath).size;
6021
+ const fd = (0, import_node_fs8.openSync)(resolvedPath, "r");
6022
+ const byteLength = Math.min(size, CSV_HEADER_SAMPLE_BYTES);
6023
+ const buffer = Buffer.alloc(byteLength);
6024
+ const bytesRead = (0, import_node_fs8.readSync)(fd, buffer, 0, byteLength, 0);
6025
+ (0, import_node_fs8.closeSync)(fd);
6026
+ if (bytesRead === 0) {
6027
+ throw new PlayBootstrapUsageError(`--from csv:${csvPath} is empty.`);
6028
+ }
6029
+ return {
6030
+ content: buffer.subarray(0, bytesRead).toString("utf8"),
6031
+ truncated: size > bytesRead
6032
+ };
6033
+ }
6034
+ function completeCsvSample(csvPath, sample) {
6035
+ if (!sample.truncated) return sample.content;
6036
+ const lastLineBreak = Math.max(
6037
+ sample.content.lastIndexOf("\n"),
6038
+ sample.content.lastIndexOf("\r")
6039
+ );
6040
+ if (lastLineBreak < 0) {
6041
+ throw new PlayBootstrapUsageError(
6042
+ `CSV header in ${csvPath} is longer than ${CSV_HEADER_SAMPLE_BYTES} bytes; shorten the header row before bootstrapping.`
6043
+ );
6044
+ }
6045
+ return sample.content.slice(0, lastLineBreak + 1);
6046
+ }
6047
+ function readCsvHeaderFields(csvPath, sample) {
6048
+ const records = (0, import_sync4.parse)(sample, {
6049
+ bom: true,
6050
+ to_line: 1,
6051
+ relax_column_count: true,
6052
+ skip_empty_lines: false
6053
+ });
6054
+ const firstRecord = Array.isArray(records) ? records[0] : null;
6055
+ const fields = Array.isArray(firstRecord) ? firstRecord.map((field) => String(field ?? "").trim()).filter(Boolean) : [];
6056
+ const uniqueFields = [...new Set(fields)];
6057
+ if (uniqueFields.length === 0) {
6058
+ throw new PlayBootstrapUsageError(
6059
+ `Could not read a header row from --from csv:${csvPath}.`
6060
+ );
6061
+ }
6062
+ return uniqueFields;
6063
+ }
6064
+ function readCsvSampleRows(sample) {
6065
+ const parsedRows = (0, import_sync4.parse)(sample, {
6066
+ bom: true,
6067
+ columns: true,
6068
+ skip_empty_lines: true,
6069
+ relax_column_count: true,
6070
+ trim: true
6071
+ });
6072
+ return Array.isArray(parsedRows) ? parsedRows.filter(isRecord3) : [];
6073
+ }
6074
+ function readSourceCsvColumnSpecs(csvPath) {
6075
+ const sample = readCsvSample(csvPath);
6076
+ const completeSample = completeCsvSample(csvPath, sample);
6077
+ return inferCsvColumnSpecs(
6078
+ readCsvHeaderFields(csvPath, sample.content),
6079
+ readCsvSampleRows(completeSample)
6080
+ );
6081
+ }
6082
+ function renderSourceCsvRowType(columns) {
6083
+ if (columns.length === 0) return "";
6084
+ const properties = columns.map((column) => ` ${jsString(column.name)}: ${column.typeExpression};`).join("\n");
6085
+ return `// CSV cells are strings at runtime. \`${"${number}"}\` means a numeric-looking CSV string; cast before math.
6086
+ type SourceCsvRow = {
6087
+ ${properties}
6088
+ };
6089
+
6090
+ `;
6091
+ }
6092
+ function packagedCsvPathForPlay(csvPath) {
6093
+ const playDir = process.cwd();
6094
+ const absoluteCsvPath = (0, import_node_path10.resolve)(csvPath);
6095
+ const relativePath = (0, import_node_path10.relative)(playDir, absoluteCsvPath);
6096
+ if (relativePath === "" || relativePath.startsWith("..") || (0, import_node_path10.isAbsolute)(relativePath)) {
6097
+ throw new PlayBootstrapUsageError(
6098
+ `--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.`
6099
+ );
6100
+ }
6101
+ const portablePath = relativePath.split("\\").join("/");
6102
+ return portablePath.startsWith(".") ? portablePath : `./${portablePath}`;
6103
+ }
6104
+ function getterNamesFromTool(tool, kind) {
6105
+ const usageGuidance = isRecord3(tool?.usageGuidance) ? tool.usageGuidance : {};
6106
+ const resultGuidance = isRecord3(usageGuidance.toolExecutionResult) ? usageGuidance.toolExecutionResult : isRecord3(usageGuidance.tool_execution_result) ? usageGuidance.tool_execution_result : {};
6107
+ const key = kind === "list" ? "extractedLists" : "extractedValues";
6108
+ const snakeKey = kind === "list" ? "extracted_lists" : "extracted_values";
6109
+ return extractionEntries(resultGuidance[key] ?? resultGuidance[snakeKey]).map((entry) => stringValue(entry.name)).filter(Boolean);
6110
+ }
6111
+ function targetGettersFromTool(tool) {
6112
+ const record = isRecord3(tool) ? tool : {};
6113
+ const raw = record.targetGetters ?? record.target_getters;
6114
+ if (!isRecord3(raw)) return {};
6115
+ const entries = [];
6116
+ for (const [target, value] of Object.entries(raw)) {
6117
+ const paths = Array.isArray(value) ? value.map((path) => typeof path === "string" ? path.trim() : "").filter(Boolean) : [];
6118
+ if (target.trim() && paths.length > 0) {
6119
+ entries.push([target.trim(), paths]);
6120
+ }
6121
+ }
6122
+ return Object.fromEntries(entries);
6123
+ }
6124
+ function listRowCandidateKeysFromTool(tool) {
6125
+ const keys = /* @__PURE__ */ new Set();
6126
+ for (const paths of Object.values(targetGettersFromTool(tool))) {
6127
+ for (const path of paths) {
6128
+ const key = path.replace(/\[(?:\*|\d+)\]/g, "").split(/[.[\]]/, 1)[0]?.trim();
6129
+ if (key) keys.add(key);
6130
+ }
6131
+ }
6132
+ return [...keys].sort();
6133
+ }
6134
+ function inputPropertyNames(schema) {
6135
+ if (!isRecord3(schema)) return [];
6136
+ if (isRecord3(schema.properties)) return Object.keys(schema.properties);
6137
+ if (Array.isArray(schema.fields)) {
6138
+ return schema.fields.filter(isRecord3).map((field) => stringValue(field.name)).filter(Boolean);
6139
+ }
6140
+ return [];
6141
+ }
6142
+ function schemaFieldDetails(schema) {
6143
+ const required = requiredPlayInputFields({
6144
+ inputSchema: schema
6145
+ });
6146
+ const optional = inputPropertyNames(schema).filter(
6147
+ (field) => !required.includes(field)
6148
+ );
6149
+ return { required, optional };
6150
+ }
6151
+ function jsonSchemaTypeExpression(schema) {
6152
+ if (!isRecord3(schema)) return "unknown";
6153
+ const type = schema.type;
6154
+ if (Array.isArray(type)) {
6155
+ return type.map((entry) => jsonSchemaTypeExpression({ ...schema, type: entry })).join(" | ");
6156
+ }
6157
+ if (Array.isArray(schema.anyOf)) {
6158
+ return schema.anyOf.map(jsonSchemaTypeExpression).join(" | ");
6159
+ }
6160
+ if (Array.isArray(schema.oneOf)) {
6161
+ return schema.oneOf.map(jsonSchemaTypeExpression).join(" | ");
6162
+ }
6163
+ switch (type) {
6164
+ case "string":
6165
+ return "string";
6166
+ case "number":
6167
+ case "integer":
6168
+ return "number";
6169
+ case "boolean":
6170
+ return "boolean";
6171
+ case "null":
6172
+ return "null";
6173
+ case "array":
6174
+ return `Array<${jsonSchemaTypeExpression(schema.items)}>`;
6175
+ case "object":
6176
+ return "Record<string, unknown>";
6177
+ default:
6178
+ return "unknown";
6179
+ }
6180
+ }
6181
+ function objectPropertySchema(schema, property) {
6182
+ return isRecord3(schema) && isRecord3(schema.properties) ? schema.properties[property] : null;
6183
+ }
6184
+ function finderResultTypeName(finder) {
6185
+ return finder === "email_finder" ? "EmailFinderPlayResult" : "PhoneFinderPlayResult";
6186
+ }
6187
+ function renderFinderPlayResultType(input) {
6188
+ if (!input.play) return null;
6189
+ const outputField = PLAY_BOOTSTRAP_OUTPUT_FIELD_BY_FINDER[input.finder];
6190
+ const fieldSchema = objectPropertySchema(
6191
+ input.play.outputSchema,
6192
+ outputField
6193
+ );
6194
+ const fieldType = fieldSchema ? jsonSchemaTypeExpression(fieldSchema) : "string | null";
6195
+ return `type ${finderResultTypeName(input.finder)} =
6196
+ | string
6197
+ | null
6198
+ | {
6199
+ ${outputField}?: ${fieldType};
6200
+ };`;
6201
+ }
6202
+ function generatedFinderPlayResultTypes(input) {
6203
+ return ["email_finder", "phone_finder"].flatMap((finder) => {
6204
+ const stage = finderStage(input.options, finder);
6205
+ if (stage?.kind !== "play") return [];
6206
+ const typeDefinition = renderFinderPlayResultType({
6207
+ finder,
6208
+ play: input.finderPlays[finder]
6209
+ });
6210
+ return typeDefinition ? [typeDefinition] : [];
6211
+ }).join("\n\n");
6212
+ }
6213
+ function exampleValueComment(field) {
6214
+ if (field === "limit" || field === "numResults" || field === "num_results" || field === "page_size") {
6215
+ return "limit";
6216
+ }
6217
+ if (field === "roles" || field.endsWith("s")) return '["..."]';
6218
+ return '"..."';
6219
+ }
6220
+ function generateContactInputObjectFromSchema(schema, indent, label, fallbackFields = ["first_name", "last_name", "domain"]) {
6221
+ const details = schemaFieldDetails(schema);
6222
+ const required = details.required.length ? details.required : fallbackFields;
6223
+ const optional = details.optional;
6224
+ const lines = [
6225
+ `${indent}// TODO: map row fields into ${label}.`,
6226
+ ...playInspectionComments(label, indent),
6227
+ `${indent}// Required: ${required.join(", ") || "none declared"}.`
6228
+ ];
6229
+ for (const field of required) {
6230
+ lines.push(`${indent}// ${field}: row["TODO_SOURCE_FIELD"],`);
6231
+ }
6232
+ if (optional.length > 0) {
6233
+ lines.push("");
6234
+ lines.push(`${indent}// optional (delete unused):`);
6235
+ for (const field of optional) {
6236
+ lines.push(`${indent}// ${field}: row["TODO_SOURCE_FIELD"],`);
6237
+ }
6238
+ }
6239
+ return `{
6240
+ ${lines.join("\n")}
6241
+ ${indent.slice(2)}}`;
6242
+ }
6243
+ function generateCompanyInputObjectFromSchema(schema, indent, label, fallbackFields = ["domain", "company_name"]) {
6244
+ const details = schemaFieldDetails(schema);
6245
+ const required = details.required.length ? details.required : fallbackFields;
6246
+ const optional = details.optional;
6247
+ const lines = [
6248
+ `${indent}// TODO: map company fields into ${label}.`,
6249
+ ...playInspectionComments(label, indent),
6250
+ `${indent}// Required: ${required.join(", ") || "none declared"}.`
6251
+ ];
6252
+ for (const field of required) {
6253
+ lines.push(`${indent}// ${field}: company["TODO_SOURCE_FIELD"],`);
6254
+ }
6255
+ if (optional.length > 0) {
6256
+ lines.push("");
6257
+ lines.push(`${indent}// optional (delete unused):`);
6258
+ for (const field of optional) {
6259
+ lines.push(`${indent}// ${field}: company["TODO_SOURCE_FIELD"],`);
6260
+ }
6261
+ }
6262
+ return `{
6263
+ ${lines.join("\n")}
6264
+ ${indent.slice(2)}}`;
6265
+ }
6266
+ function generateSourceProviderInputObject(input) {
6267
+ const { tool, indent, label, entity } = input;
6268
+ const properties = inputPropertyNames(tool?.inputSchema);
6269
+ const details = schemaFieldDetails(tool?.inputSchema);
6270
+ const required = details.required;
6271
+ const includeOptional = properties.length === 0 ? ["query", "title", "domain", "limit"] : properties.filter(
6272
+ (field) => [
6273
+ "query",
6274
+ "q",
6275
+ "search",
6276
+ "title",
6277
+ "role",
6278
+ "persona",
6279
+ "domain",
6280
+ "company_domain",
6281
+ "limit",
6282
+ "numResults",
6283
+ "num_results",
6284
+ "page_size"
6285
+ ].includes(field)
6286
+ );
6287
+ const lines = [
6288
+ `${indent}// TODO: fill ${entity} source inputs for ${label}.`,
6289
+ `${indent}// Inspect: deepline tools describe ${label} --json`
6290
+ ];
6291
+ for (const field of required) {
6292
+ lines.push(`${indent}// ${field}: ${exampleValueComment(field)},`);
6293
+ }
6294
+ const activeTodoField = required.length === 0 ? ["query", "q", "search", "title", "role", "persona"].find(
6295
+ (field) => includeOptional.includes(field)
6296
+ ) ?? "query" : null;
6297
+ if (activeTodoField) {
6298
+ lines.push(
6299
+ `${indent}// ${activeTodoField}: ${exampleValueComment(activeTodoField)},`
6300
+ );
6301
+ }
6302
+ const optionalExamples = includeOptional.filter(
6303
+ (field) => !required.includes(field) && field !== activeTodoField
6304
+ );
6305
+ if (optionalExamples.length > 0) {
6306
+ lines.push("");
6307
+ lines.push(`${indent}// optional - uncomment what this provider supports:`);
6308
+ for (const field of optionalExamples) {
6309
+ if (field === "limit" || field === "numResults" || field === "num_results" || field === "page_size") {
6310
+ lines.push(`${indent}// ${field}: limit,`);
6311
+ } else {
6312
+ lines.push(`${indent}// ${field}: ${exampleValueComment(field)},`);
6313
+ }
6314
+ }
6315
+ }
6316
+ if (!required.some(
6317
+ (field) => ["limit", "numResults", "num_results", "page_size"].includes(field)
6318
+ )) {
6319
+ lines.push(`${indent}limit,`);
6320
+ }
6321
+ return `{
6322
+ ${lines.join("\n")}
6323
+ ${indent.slice(2)}}`;
6324
+ }
6325
+ function generatePlayInputObject(input) {
6326
+ const { schema, indent, label, entity } = input;
6327
+ const details = schemaFieldDetails(schema);
6328
+ const fallback = entity === "company" ? ["domain", "company_name"] : ["first_name", "last_name", "domain"];
6329
+ const required = details.required.length ? details.required : fallback;
6330
+ const lines = [
6331
+ `${indent}// TODO: fill source play inputs for ${label}.`,
6332
+ ...playInspectionComments(label, indent)
6333
+ ];
6334
+ for (const field of required) {
6335
+ lines.push(`${indent}// ${field}: ${exampleValueComment(field)},`);
6336
+ }
6337
+ if (!required.includes("limit")) lines.push(`${indent}limit,`);
6338
+ return `{
6339
+ ${lines.join("\n")}
6340
+ ${indent.slice(2)}}`;
6341
+ }
6342
+ function requiredPlayInputFields(play) {
6343
+ const schema = play?.inputSchema;
6344
+ if (!isRecord3(schema)) return [];
6345
+ if (Array.isArray(schema.required)) {
6346
+ return schema.required.filter(
6347
+ (value) => typeof value === "string"
6348
+ );
6349
+ }
6350
+ if (Array.isArray(schema.fields)) {
6351
+ return schema.fields.filter(isRecord3).filter(
6352
+ (field) => field.required === true && typeof field.name === "string"
6353
+ ).map((field) => String(field.name));
6354
+ }
6355
+ return [];
6356
+ }
6357
+ function sourceProviders(options) {
6358
+ return options.from.kind === "providers" ? options.from.values : [];
6359
+ }
6360
+ function sourcePlayRef(options) {
6361
+ return options.from.kind === "play" ? options.from.value : null;
6362
+ }
6363
+ function stagePlayRef(stage) {
6364
+ return stage?.kind === "play" ? stage.value : null;
6365
+ }
6366
+ function stageProviders(stage) {
6367
+ return stage?.kind === "providers" ? stage.values : [];
6368
+ }
6369
+ function finderStage(options, finder) {
6370
+ return finder === "email_finder" ? options.email : options.phone;
6371
+ }
6372
+ function stepFieldName(finder) {
6373
+ return PLAY_BOOTSTRAP_OUTPUT_FIELD_BY_FINDER[finder];
6374
+ }
6375
+ function finderProviderStepPrefix(finder) {
6376
+ return finder === "email_finder" ? "emailFinder" : "phoneFinder";
6377
+ }
6378
+ function safeIdentifier(value) {
6379
+ return value.replace(/[^A-Za-z0-9_]+/g, "_");
6380
+ }
6381
+ function playInspectionComments(playRef, indent) {
6382
+ return [`${indent}// Inspect: deepline plays describe ${playRef} --json`];
6383
+ }
6384
+ function accessorExpression(base, field) {
6385
+ return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(field) ? `${base}.${field}` : `${base}[${jsString(field)}]`;
6386
+ }
6387
+ function needsWhenImport(options) {
6388
+ return stageProviders(options.email).length > 1 || stageProviders(options.phone).length > 1;
6389
+ }
6390
+ function sourceCollectionTypeName(entity) {
6391
+ return entity === "company" ? "CompanySourceRow" : "ContactSourceRow";
6392
+ }
6393
+ function renderPartialRowType(input) {
6394
+ if (input.fields.length === 0) {
6395
+ return `type ${input.typeName} = Record<string, unknown>;`;
6396
+ }
6397
+ const properties = input.fields.map((field) => ` ${jsString(field)}?: unknown;`).join("\n");
6398
+ return `type ${input.typeName} = Record<string, unknown> & Partial<{
6399
+ // ${input.comment}
6400
+ ${properties}
6401
+ }>;`;
6402
+ }
6403
+ function fieldsFromSchemaDetails(input) {
6404
+ return [
6405
+ ...input.details.required.length ? input.details.required : input.fallbackFields,
6406
+ ...input.details.optional
6407
+ ];
6408
+ }
6409
+ function schemaFieldsForStage(stage, input) {
6410
+ switch (stage?.kind) {
6411
+ case void 0:
6412
+ return [];
6413
+ case "play":
6414
+ return fieldsFromSchemaDetails({
6415
+ details: schemaFieldDetails(input.play?.inputSchema),
6416
+ fallbackFields: input.fallbackFields
6417
+ });
6418
+ case "providers":
6419
+ return input.tools.flatMap(
6420
+ (tool) => fieldsFromSchemaDetails({
6421
+ details: schemaFieldDetails(tool.inputSchema),
6422
+ fallbackFields: input.fallbackFields
6423
+ })
6424
+ );
6425
+ }
6426
+ }
6427
+ function sourceRowTypeDefinition(input) {
6428
+ switch (input.options.from.kind) {
6429
+ case "csv":
6430
+ return `type ${input.sourceTypeName} = SourceCsvRow;`;
6431
+ case "providers":
6432
+ return renderPartialRowType({
6433
+ typeName: input.sourceTypeName,
6434
+ fields: [
6435
+ ...new Set(input.sourceTools.flatMap(listRowCandidateKeysFromTool))
6436
+ ].sort(),
6437
+ comment: "Candidate source row keys from described list getters; confirm the actual provider keys with source_*.extractedLists.*.keys before mapping."
6438
+ });
6439
+ case "play": {
6440
+ const details = schemaFieldDetails(input.sourcePlay?.outputSchema);
6441
+ return renderPartialRowType({
6442
+ typeName: input.sourceTypeName,
6443
+ fields: [...details.required, ...details.optional].sort(),
6444
+ comment: "Candidate source play output fields; confirm the selected rows field before mapping."
6445
+ });
6446
+ }
6447
+ }
6448
+ }
6449
+ function contactBridgeRowTypeDefinition(input) {
6450
+ const config = playBootstrapTemplateConfig(input.options.template);
6451
+ if (config.sourceEntity !== "company" || !input.options.people) return null;
6452
+ const emailFields = schemaFieldsForStage(input.options.email, {
6453
+ tools: input.finderTools.email_finder ?? [],
6454
+ play: input.finderPlays.email_finder,
6455
+ fallbackFields: ["first_name", "last_name", "domain"]
6456
+ });
6457
+ const phoneFields = schemaFieldsForStage(input.options.phone, {
6458
+ tools: input.finderTools.phone_finder ?? [],
6459
+ play: input.finderPlays.phone_finder,
6460
+ fallbackFields: ["first_name", "last_name", "domain"]
6461
+ });
6462
+ return renderPartialRowType({
6463
+ typeName: "ContactSourceRow",
6464
+ fields: [
6465
+ .../* @__PURE__ */ new Set([
6466
+ ...inputPropertyNames(input.peoplePlay?.outputSchema),
6467
+ ...emailFields,
6468
+ ...phoneFields
6469
+ ])
6470
+ ].sort(),
6471
+ comment: "Fields the people play or later finder stages may need; the generated code still requires explicit mapping."
6472
+ });
6473
+ }
6474
+ function generateRowTypeDefinitions(input) {
6475
+ const config = playBootstrapTemplateConfig(input.options.template);
6476
+ const sourceTypeName = sourceCollectionTypeName(config.sourceEntity);
6477
+ const definitions = [
6478
+ sourceRowTypeDefinition({
6479
+ options: input.options,
6480
+ sourceTypeName,
6481
+ sourceTools: input.sourceTools,
6482
+ sourcePlay: input.sourcePlay
6483
+ }),
6484
+ contactBridgeRowTypeDefinition(input)
6485
+ ];
6486
+ return definitions.filter(Boolean).join("\n\n");
6487
+ }
6488
+ function validateBootstrapRoutes(input) {
6489
+ const config = playBootstrapTemplateConfig(input.options.template);
6490
+ const sourceCategory = config.sourceEntity === "company" ? PLAY_BOOTSTRAP_COMPANY_PROVIDER_CATEGORY : PLAY_BOOTSTRAP_PEOPLE_PROVIDER_CATEGORY;
6491
+ for (const tool of input.sourceTools) {
6492
+ if (!tool.categories.includes(sourceCategory)) {
6493
+ throw new PlayBootstrapValidationError(
6494
+ `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`
6495
+ );
6496
+ }
6497
+ if (getterNamesFromTool(tool, "list").length === 0) {
6498
+ throw new PlayBootstrapValidationError(
6499
+ `Cannot use ${tool.toolId} as a ${config.sourceEntity} source: it exposes no extracted list getters. Run: deepline tools describe ${tool.toolId} --json`
6500
+ );
6501
+ }
6502
+ }
6503
+ if (input.options.people?.kind === "providers") {
6504
+ throw new PlayBootstrapValidationError(
6505
+ "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."
6506
+ );
6507
+ }
6508
+ for (const finder of ["email_finder", "phone_finder"]) {
6509
+ const requiredCategory = PLAY_BOOTSTRAP_PROVIDER_CATEGORY_BY_FINDER[finder];
6510
+ for (const tool of input.finderTools[finder] ?? []) {
6511
+ if (!tool.categories.includes(requiredCategory)) {
6512
+ throw new PlayBootstrapValidationError(
6513
+ `Cannot use ${tool.toolId} for ${finder}: expected category ${requiredCategory}, got ${tool.categories.join(", ") || "none"}. Run: deepline tools grep ${requiredCategory} --categories ${requiredCategory} --json`
6514
+ );
6515
+ }
6516
+ if (getterNamesFromTool(tool, "value").length === 0) {
6517
+ throw new PlayBootstrapValidationError(
6518
+ `Cannot use ${tool.toolId} as a ${finder}: it exposes no extracted value getters. Run: deepline tools describe ${tool.toolId} --json`
6519
+ );
6520
+ }
6521
+ }
6522
+ }
6523
+ }
6524
+ function sourceCollectionName(entity) {
6525
+ switch (entity) {
6526
+ case "company":
6527
+ return "companies";
6528
+ case "people":
6529
+ return "contacts";
6530
+ }
6531
+ }
6532
+ function requiredGetterName(input) {
6533
+ const getter = getterNamesFromTool(input.tool, input.kind)[0];
6534
+ if (!getter) {
6535
+ switch (input.kind) {
6536
+ case "list":
6537
+ throw new PlayBootstrapValidationError(
6538
+ `Cannot use ${input.label} as a source: it exposes no extracted list getters.`
6539
+ );
6540
+ case "value":
6541
+ throw new PlayBootstrapValidationError(
6542
+ `Cannot use ${input.label} as a finder: it exposes no extracted value getters.`
6543
+ );
6544
+ }
6545
+ }
6546
+ return getter;
6547
+ }
6548
+ function generateCsvSourceRowsBlock(input) {
6549
+ return `const sourceDataset = await ctx.csv<SourceCsvRow>(${jsString(input.packagedSourceCsvPath ?? input.source.value)});
6550
+ const ${input.collection}: ${input.collectionType}[] = await sourceDataset.peek(limit);`;
6551
+ }
6552
+ function generatePlaySourceRowsBlock(input) {
6553
+ const playInput = generatePlayInputObject({
6554
+ schema: input.sourcePlay?.inputSchema,
6555
+ indent: " ",
6556
+ label: input.source.value,
6557
+ entity: input.entity
6558
+ });
6559
+ return `const sourceInput = ${playInput};
6560
+ throw new Error(${jsString(`TODO: map sourceInput for ${input.source.value}, choose the play output rows field, then delete this throw.`)});
6561
+ const sourceResult = await ctx.runPlay('source_play', ${jsString(input.source.value)}, sourceInput, {
6562
+ description: ${jsString(`Seed ${input.entity} rows from the selected play.`)},
6563
+ });
6564
+ // TODO: Replace sourceResult.rows with the selected play's actual row output field.
6565
+ const ${input.collection}: ${input.collectionType}[] = (sourceResult.rows ?? []) as ${input.collectionType}[];`;
6566
+ }
6567
+ function generateProviderSourceBlock(input) {
6568
+ const getter = requiredGetterName({
6569
+ tool: input.tool,
6570
+ kind: "list",
6571
+ label: input.provider
6572
+ });
6573
+ const inputName = `${input.entity}Input_${input.index}`;
6574
+ return `// ${input.entity === "company" ? "Company" : "People"} source provider: ${input.provider}
6575
+ const ${inputName}: Record<string, unknown> = ${generateSourceProviderInputObject(
6576
+ {
6577
+ tool: input.tool,
6578
+ indent: " ",
6579
+ label: input.provider,
6580
+ entity: input.entity
6581
+ }
6582
+ )};
6583
+ throw new Error(${jsString(`TODO: fill ${inputName} for ${input.provider}, then delete this throw.`)});
6584
+ const source_${input.index} = await ctx.tools.execute({
6585
+ id: ${jsString(`${input.entity}_source_${input.index}`)},
6586
+ tool: ${jsString(input.provider)},
6587
+ input: ${inputName},
6588
+ description: ${jsString(`Seed ${input.entity} rows from ${input.provider}.`)},
6589
+ });
6590
+ // extractedLists.${getter}.get() returns provider-shaped rows. Do not assume canonical fields;
6591
+ // inspect source_${input.index}.extractedLists.${getter}.keys or the provider output schema, then map explicitly below.
6592
+ const sourceRows_${input.index} = ${accessorExpression(`source_${input.index}.extractedLists`, getter)}.get() as ${input.collectionType}[];`;
6593
+ }
6594
+ function generateProviderSourceRowsBlock(input) {
6595
+ const blocks = input.source.values.map(
6596
+ (provider, index) => generateProviderSourceBlock({
6597
+ provider,
6598
+ index,
6599
+ tool: input.sourceTools[index] ?? null,
6600
+ entity: input.entity,
6601
+ collectionType: input.collectionType
6602
+ })
6603
+ );
6604
+ return `${blocks.join("\n\n ")}
6605
+ const ${input.collection}: ${input.collectionType}[] = [${input.source.values.map((_, index) => `...sourceRows_${index}`).join(", ")}];`;
6606
+ }
6607
+ function generateSourceRowsBlock(input) {
6608
+ const config = playBootstrapTemplateConfig(input.options.template);
6609
+ const entity = config.sourceEntity;
6610
+ const collection = sourceCollectionName(entity);
6611
+ const collectionType = sourceCollectionTypeName(entity);
6612
+ switch (input.options.from.kind) {
6613
+ case "csv":
6614
+ return generateCsvSourceRowsBlock({
6615
+ source: input.options.from,
6616
+ collection,
6617
+ collectionType,
6618
+ packagedSourceCsvPath: input.packagedSourceCsvPath
6619
+ });
6620
+ case "play":
6621
+ return generatePlaySourceRowsBlock({
6622
+ source: input.options.from,
6623
+ sourcePlay: input.sourcePlay,
6624
+ entity,
6625
+ collection,
6626
+ collectionType
6627
+ });
6628
+ case "providers":
6629
+ return generateProviderSourceRowsBlock({
6630
+ source: input.options.from,
6631
+ sourceTools: input.sourceTools,
6632
+ entity,
6633
+ collection,
6634
+ collectionType
6635
+ });
6636
+ }
6637
+ }
6638
+ function generateSourceSeedBlock(input) {
6639
+ const sourceRows = generateSourceRowsBlock(input);
6640
+ const peoplePlayRef = stagePlayRef(input.options.people);
6641
+ if (!peoplePlayRef) return sourceRows;
6642
+ const peopleInput = generateCompanyInputObjectFromSchema(
6643
+ input.peoplePlay?.inputSchema,
6644
+ " ",
6645
+ peoplePlayRef,
6646
+ ["domain", "company_name"]
6647
+ );
6648
+ return `${sourceRows}
6649
+ const contacts: ContactSourceRow[] = [];
6650
+ for (const [index, company] of companies.slice(0, limit).entries()) {
6651
+ const peopleInput = ${peopleInput};
6652
+ throw new Error(${jsString(`TODO: map company fields into peopleInput for ${peoplePlayRef}, choose the play output rows field, then delete this throw.`)});
6653
+ const peopleResult = await ctx.runPlay(
6654
+ \`people_play_\${index}\`,
6655
+ ${jsString(peoplePlayRef)},
6656
+ peopleInput,
6657
+ {
6658
+ description: 'Map one company row into people/contact rows with the selected play.',
6659
+ },
6660
+ );
6661
+ // TODO: Replace peopleResult.rows with the selected play's actual contact rows field.
6662
+ contacts.push(...((peopleResult.rows ?? []) as ContactSourceRow[]));
6663
+ }`;
6664
+ }
6665
+ function finderProviderStepName(input) {
6666
+ return `${input.aggregateStepName}${input.index}_${safeIdentifier(input.provider)}`;
6667
+ }
6668
+ function finderValueGetter(input) {
6669
+ const getters = getterNamesFromTool(input.tool, "value");
6670
+ const getter = getters.find((name) => name === input.outputField) ?? requiredGetterName({
6671
+ tool: input.tool,
6672
+ kind: "value",
6673
+ label: input.provider
6674
+ });
6675
+ return getter;
6676
+ }
6677
+ function optionalFinderValueExpression(candidateExpression, outputField) {
6678
+ const valueExpression = /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(outputField) ? `${candidateExpression}?.${outputField}` : `${candidateExpression}?.[${jsString(outputField)}]`;
6679
+ return `${valueExpression}?.trim()`;
6680
+ }
6681
+ function generateFinderPlayStep(input) {
6682
+ const outputField = PLAY_BOOTSTRAP_OUTPUT_FIELD_BY_FINDER[input.finder];
6683
+ const resultTypeName = finderResultTypeName(input.finder);
6684
+ const payload = generateContactInputObjectFromSchema(
6685
+ input.play?.inputSchema,
6686
+ " ",
6687
+ input.stage.value
6688
+ );
6689
+ return `.step(${jsString(outputField)}, async (row, rowCtx) => {
6690
+ const ${input.aggregateStepName}Input = ${payload};
6691
+ throw new Error(${jsString(`TODO: map ${input.aggregateStepName}Input for ${input.stage.value}, then delete this throw.`)});
6692
+ const ${input.aggregateStepName}Result = await rowCtx.runPlay<${resultTypeName}>(
6693
+ ${jsString(`${input.aggregateStepName}Play`)},
6694
+ ${jsString(input.stage.value)},
6695
+ ${input.aggregateStepName}Input,
6696
+ {
6697
+ description: ${jsString(`Run ${input.finder} play.`)},
6698
+ },
6699
+ );
6700
+ return typeof ${input.aggregateStepName}Result === 'string'
6701
+ ? ${input.aggregateStepName}Result.trim() || null
6702
+ : ${input.aggregateStepName}Result?.${outputField} ?? null;
6703
+ })`;
6704
+ }
6705
+ function generateFinderProviderResolver(input) {
6706
+ const payload = generateContactInputObjectFromSchema(
6707
+ input.tool?.inputSchema,
6708
+ " ",
6709
+ input.provider
6710
+ );
6711
+ const getter = finderValueGetter({
6712
+ tool: input.tool,
6713
+ provider: input.provider,
6714
+ outputField: input.outputField
6715
+ });
6716
+ return `async (row, rowCtx) => {
6717
+ const providerInput = ${payload};
6718
+ throw new Error(${jsString(`TODO: map providerInput for ${input.provider}, then delete this throw.`)});
6719
+ const result = await rowCtx.tools.execute({
6720
+ id: ${jsString(`${input.aggregateStepName}_${input.providerIndex}`)},
6721
+ tool: ${jsString(input.provider)},
6722
+ input: providerInput,
6723
+ description: ${jsString(`Try ${input.provider} as a ${input.finder}.`)},
6724
+ });
6725
+ return {
6726
+ ${input.outputField}: (${accessorExpression("result.extractedValues", getter)}.get() as string | null) ?? null,
6727
+ result,
6728
+ };
6729
+ }`;
6730
+ }
6731
+ function generateFinderProviderStep(input) {
6732
+ const stepName = input.stepNames[input.index];
6733
+ switch (input.index) {
6734
+ case 0:
6735
+ return `.step(${jsString(stepName)}, ${input.resolver})`;
6736
+ default: {
6737
+ const priorCandidates = input.stepNames.slice(0, input.index).map((name) => `row.${name}`).join(", ");
6738
+ return `.step(
6739
+ ${jsString(stepName)},
6740
+ when(
6741
+ (row) => ![${priorCandidates}].some((candidate) => ${optionalFinderValueExpression("candidate", input.outputField)}),
6742
+ ${input.resolver},
6743
+ ),
6744
+ )`;
6745
+ }
6746
+ }
6747
+ }
6748
+ function generateFinderProviderWaterfall(input) {
6749
+ const legPrefix = finderProviderStepPrefix(input.finder);
6750
+ const stepNames = input.stage.values.map(
6751
+ (provider, index) => finderProviderStepName({
6752
+ aggregateStepName: legPrefix,
6753
+ provider,
6754
+ index
6755
+ })
6756
+ );
6757
+ const providerSteps = input.stage.values.map(
6758
+ (provider, index) => generateFinderProviderStep({
6759
+ index,
6760
+ stepNames,
6761
+ outputField: input.outputField,
6762
+ resolver: generateFinderProviderResolver({
6763
+ finder: input.finder,
6764
+ provider,
6765
+ providerIndex: index,
6766
+ tool: input.tools[index] ?? null,
6767
+ aggregateStepName: input.aggregateStepName,
6768
+ outputField: input.outputField
6769
+ })
6770
+ })
6771
+ );
6772
+ const candidateNames = stepNames.map((name) => `row.${name}`).join(", ");
6773
+ return `// ${input.aggregateStepName} provider waterfall. Each provider leg is active once its TODO throw is removed;
6774
+ // delete or comment out legs you do not want before running. Later legs are gated with when(...).
6775
+ ${providerSteps.join("\n ")}
6776
+ .step(${jsString(input.aggregateStepName)}, (row) => {
6777
+ const candidates = [${candidateNames}];
6778
+ const match = candidates.find((candidate) => ${optionalFinderValueExpression("candidate", input.outputField)});
6779
+ return ${optionalFinderValueExpression("match", input.outputField)} ?? null;
6780
+ })`;
6781
+ }
6782
+ function generateFinderStageSteps(input) {
6783
+ const outputField = PLAY_BOOTSTRAP_OUTPUT_FIELD_BY_FINDER[input.finder];
6784
+ const aggregateStepName = stepFieldName(input.finder);
6785
+ switch (input.stage.kind) {
6786
+ case "play":
6787
+ return generateFinderPlayStep({
6788
+ finder: input.finder,
6789
+ stage: input.stage,
6790
+ play: input.finderPlays[input.finder],
6791
+ aggregateStepName
6792
+ });
6793
+ case "providers":
6794
+ return generateFinderProviderWaterfall({
6795
+ finder: input.finder,
6796
+ stage: input.stage,
6797
+ tools: input.finderTools[input.finder] ?? [],
6798
+ aggregateStepName,
6799
+ outputField
6800
+ });
6801
+ }
6802
+ }
6803
+ function generateFinderSteps(input) {
6804
+ return ["email_finder", "phone_finder"].flatMap((finder) => {
6805
+ const stage = finderStage(input.options, finder);
6806
+ return stage ? [
6807
+ generateFinderStageSteps({
6808
+ ...input,
6809
+ finder,
6810
+ stage
6811
+ })
6812
+ ] : [];
6813
+ }).join("\n ");
6814
+ }
6815
+ function generateBootstrapPlaySource(input) {
6816
+ const config = playBootstrapTemplateConfig(input.options.template);
6817
+ const sourceSeedBlock = generateSourceSeedBlock(input);
6818
+ const finderSteps = generateFinderSteps(input);
6819
+ const hasPeople = config.sourceEntity === "people" || Boolean(input.options.people);
6820
+ const sourceCollection = hasPeople ? "contacts" : "companies";
6821
+ const mapSteps = finderSteps ? `
6822
+ ${finderSteps}` : "";
6823
+ const sourceCsvRowType = input.options.from.kind === "csv" ? renderSourceCsvRowType(input.sourceCsvColumns) : "";
6824
+ const rowTypeDefinitions = generateRowTypeDefinitions(input);
6825
+ const finderPlayResultTypes = generatedFinderPlayResultTypes(input);
6826
+ const typeDefinitions = [
6827
+ sourceCsvRowType.trimEnd(),
6828
+ rowTypeDefinitions,
6829
+ finderPlayResultTypes
6830
+ ].filter((definition) => definition.trim().length > 0).join("\n\n");
6831
+ const importNames = needsWhenImport(input.options) ? "definePlay, when" : "definePlay";
6832
+ return `import { ${importNames} } from 'deepline';
6833
+
6834
+ ${typeDefinitions}
6835
+
6836
+ type Input = {
6837
+ limit?: number;
6838
+ };
6839
+
6840
+ export default definePlay(${jsString(input.options.name)}, async (ctx, input: Input = {}) => {
6841
+ const limit = Math.max(1, Math.min(Number(input.limit ?? ${input.options.limit}), ${input.options.limit}));
6842
+ ${sourceSeedBlock}
6843
+
6844
+ const rowsToProcess = ${sourceCollection}.slice(0, limit);
6845
+ if (rowsToProcess.length === 0) {
6846
+ throw new Error('plays bootstrap found 0 source rows. Check the source provider/play/CSV output.');
6847
+ }
6848
+
6849
+ const rows = await ctx
6850
+ .map('bootstrap_rows', rowsToProcess)${mapSteps}
6851
+ .run({
6852
+ key: (_row, index) => index,
6853
+ description: ${jsString(`Bootstrap ${input.options.template}: seed source rows, run requested stages, then return the mapped rows.`)},
6854
+ });
6855
+
6856
+ return {
6857
+ count: await rows.count(),
6858
+ rows,
6859
+ };
6860
+ });
6861
+
6862
+ `;
6863
+ }
6864
+ async function describePlayMaybe(client, playRef) {
6865
+ return playRef ? client.describePlay(playRef, { compact: true }) : null;
6866
+ }
6867
+ function loadTools(client, providers) {
6868
+ return Promise.all(providers.map((provider) => client.getTool(provider)));
6869
+ }
6870
+ async function loadBootstrapContracts(client, options) {
6871
+ const [
6872
+ sourceTools,
6873
+ sourcePlay,
6874
+ peoplePlay,
6875
+ emailPlay,
6876
+ phonePlay,
6877
+ emailTools,
6878
+ phoneTools
6879
+ ] = await Promise.all([
6880
+ loadTools(client, sourceProviders(options)),
6881
+ describePlayMaybe(client, sourcePlayRef(options)),
6882
+ describePlayMaybe(client, stagePlayRef(options.people)),
6883
+ describePlayMaybe(client, stagePlayRef(options.email)),
6884
+ describePlayMaybe(client, stagePlayRef(options.phone)),
6885
+ loadTools(client, stageProviders(options.email)),
6886
+ loadTools(client, stageProviders(options.phone))
6887
+ ]);
6888
+ const contracts = {
6889
+ sourceTools,
6890
+ sourcePlay,
6891
+ peoplePlay,
6892
+ finderTools: {
6893
+ email_finder: emailTools,
6894
+ phone_finder: phoneTools
6895
+ },
6896
+ finderPlays: {
6897
+ email_finder: emailPlay,
6898
+ phone_finder: phonePlay
6899
+ }
6900
+ };
6901
+ validateBootstrapRoutes({
6902
+ options,
6903
+ sourceTools: contracts.sourceTools,
6904
+ peoplePlay: contracts.peoplePlay,
6905
+ finderTools: contracts.finderTools,
6906
+ finderPlays: contracts.finderPlays
6907
+ });
6908
+ return contracts;
6909
+ }
6910
+ function loadCsvContext(source) {
6911
+ switch (source.kind) {
6912
+ case "csv":
6913
+ return {
6914
+ packagedSourceCsvPath: packagedCsvPathForPlay(source.value),
6915
+ sourceCsvColumns: readSourceCsvColumnSpecs(source.value)
6916
+ };
6917
+ case "play":
6918
+ case "providers":
6919
+ return {
6920
+ packagedSourceCsvPath: null,
6921
+ sourceCsvColumns: []
6922
+ };
6923
+ }
5562
6924
  }
5563
- function defaultPlayBundleTarget() {
5564
- return resolveExecutionProfile(null).artifactKind;
6925
+ function errorMessage(error) {
6926
+ return error instanceof Error ? error.message : String(error);
5565
6927
  }
5566
- function createSdkPlayBundlingAdapter() {
5567
- return {
5568
- projectRoot: PROJECT_ROOT,
5569
- nodeModulesDir: (0, import_node_path9.resolve)(PROJECT_ROOT, "node_modules"),
5570
- cacheDir: (0, import_node_path9.join)(
5571
- (0, import_node_os5.tmpdir)(),
5572
- `deepline-play-artifacts-v${PLAY_BUNDLE_CACHE_VERSION2}`
5573
- ),
5574
- sdkSourceRoot: SDK_SOURCE_ROOT,
5575
- sdkPackageJson: SDK_PACKAGE_JSON,
5576
- sdkEntryFile: SDK_ENTRY_FILE,
5577
- sdkTypesEntryFile: HAS_SOURCE_BUNDLING_SOURCES || !(0, import_node_fs7.existsSync)(SDK_TYPES_ENTRY_FILE) ? SDK_ENTRY_FILE : SDK_TYPES_ENTRY_FILE,
5578
- sdkWorkersEntryFile: SDK_WORKERS_ENTRY_FILE,
5579
- workersHarnessEntryFile: WORKERS_HARNESS_ENTRY_FILE,
5580
- workersHarnessFilesDir: WORKERS_HARNESS_FILES_DIR,
5581
- discoverPackagedLocalFiles,
5582
- warnAboutNonDevelopmentBundling
5583
- };
6928
+ function renderPlayBootstrapError(error) {
6929
+ console.error(errorMessage(error));
6930
+ return error instanceof PlayBootstrapError ? error.exitCode : 1;
5584
6931
  }
5585
- async function bundlePlayFile2(filePath, options = {}) {
5586
- return bundlePlayFile(filePath, {
5587
- target: options.target ?? defaultPlayBundleTarget(),
5588
- exportName: options.exportName,
5589
- adapter: createSdkPlayBundlingAdapter()
6932
+ async function runPlayBootstrap(args) {
6933
+ const options = parsePlayBootstrapOptions(args);
6934
+ const client = new DeeplineClient();
6935
+ const contracts = await loadBootstrapContracts(client, options);
6936
+ const csvContext = loadCsvContext(options.from);
6937
+ const source = generateBootstrapPlaySource({
6938
+ options,
6939
+ ...contracts,
6940
+ ...csvContext
6941
+ });
6942
+ process.stdout.write(source);
6943
+ return 0;
6944
+ }
6945
+ async function handlePlayBootstrap(args) {
6946
+ return runPlayBootstrap(args).catch(renderPlayBootstrapError);
6947
+ }
6948
+ function registerPlayBootstrapCommand(play) {
6949
+ play.command("bootstrap <template>").description("Print a scratchpad play for a GTM route template.").addHelpText(
6950
+ "after",
6951
+ `
6952
+ Notes:
6953
+ Cloud-validated play generator for agents. Pick the JTBD as the positional
6954
+ template, bind resources with typed refs, redirect stdout to a .play.ts file,
6955
+ then edit the generated TODO mapping comments. Multiple finder providers are
6956
+ generated as a waterfall in the order you pass them.
6957
+
6958
+ This command requires auth because provider/play contracts are fetched from
6959
+ Deepline. It prints TypeScript source only and does not run paid tools; the
6960
+ generated play may spend credits later when you run it.
6961
+
6962
+ stdout is the generated .play.ts source. Errors and diagnostics go to stderr.
6963
+ There is no JSON mode and no --out; use shell redirection:
6964
+ deepline plays bootstrap ... > scratchpad.play.ts
6965
+
6966
+ Templates:
6967
+ people-list start from people/contact rows
6968
+ company-list start from company/account rows
6969
+ people-email people/contact rows -> email finder
6970
+ people-phone people/contact rows -> phone finder
6971
+ company-people company/account rows -> people play
6972
+ company-people-email company/account rows -> people play -> email finder
6973
+ company-people-phone company/account rows -> people play -> phone finder
6974
+
6975
+ Resource refs:
6976
+ csv:./contacts.csv
6977
+ play:prebuilt/name-and-domain-to-email-waterfall
6978
+ provider:dropleads_search_people
6979
+ providers:hunter_email_finder,leadmagic_email_finder
6980
+
6981
+ Validation:
6982
+ source providers must match the route entity: company_search or people_search
6983
+ source providers must expose list getters
6984
+ company -> people uses a play only; provider bridge is generated later when a play exists
6985
+ email/phone finder providers must match their category and expose value getters
6986
+ finder plays/providers must match the route; generated code leaves input mapping explicit
6987
+ business-specific provider inputs and company -> people persona fields are TODOs in code
6988
+ csv: paths are resolved from the directory where you run bootstrap; redirect the play file there too
6989
+
6990
+ Exit codes:
6991
+ 0 success
6992
+ 2 usage/local input error
6993
+ 7 route validation failed
6994
+
6995
+ Examples:
6996
+ 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
6997
+ deepline plays check email-flow.play.ts
6998
+ deepline plays run email-flow.play.ts --input '{"limit":5}' --watch
6999
+
7000
+ deepline plays bootstrap people-email --from provider:dropleads_search_people --using providers:hunter_email_finder,leadmagic_email_finder --limit 5 > prospecting.play.ts
7001
+ 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
7002
+ deepline plays bootstrap company-list --from provider:apollo_company_search --limit 5 > companies.play.ts
7003
+ `
7004
+ ).option("--name <name>", "Generated play name").option(
7005
+ "--from <ref>",
7006
+ "Route source: csv:PATH, play:REF, provider:ID, or providers:ID,ID"
7007
+ ).option(
7008
+ "--using <ref>",
7009
+ "Single-stage route shorthand for people-email, people-phone, or company-people"
7010
+ ).option(
7011
+ "--people <ref>",
7012
+ "Company-to-people stage for company-people-email/phone; use play:REF"
7013
+ ).option(
7014
+ "--email <ref>",
7015
+ "Email finder stage: play:REF, provider:ID, or providers:ID,ID"
7016
+ ).option(
7017
+ "--phone <ref>",
7018
+ "Phone finder stage: play:REF, provider:ID, or providers:ID,ID"
7019
+ ).option("--limit <n>", "Maximum rows to fan out in the generated play").action(async (template, options) => {
7020
+ process.exitCode = await handlePlayBootstrap([
7021
+ template,
7022
+ ...options.name ? ["--name", options.name] : [],
7023
+ ...options.from ? ["--from", options.from] : [],
7024
+ ...options.using ? ["--using", options.using] : [],
7025
+ ...options.people ? ["--people", options.people] : [],
7026
+ ...options.email ? ["--email", options.email] : [],
7027
+ ...options.phone ? ["--phone", options.phone] : [],
7028
+ ...options.limit ? ["--limit", options.limit] : []
7029
+ ]);
5590
7030
  });
5591
7031
  }
5592
7032
 
@@ -6041,9 +7481,9 @@ function traceCliSync(phase, fields, run) {
6041
7481
  }
6042
7482
  }
6043
7483
  function sleep4(ms) {
6044
- return new Promise((resolve11) => setTimeout(resolve11, ms));
7484
+ return new Promise((resolve12) => setTimeout(resolve12, ms));
6045
7485
  }
6046
- function parseReferencedPlayTarget(target) {
7486
+ function parseReferencedPlayTarget2(target) {
6047
7487
  const trimmed = target.trim();
6048
7488
  const slashIndex = trimmed.indexOf("/");
6049
7489
  if (slashIndex <= 0 || slashIndex === trimmed.length - 1) {
@@ -6064,7 +7504,7 @@ function buildBarePrebuiltReferenceError(input) {
6064
7504
  );
6065
7505
  }
6066
7506
  async function assertCanonicalNamedPlayReference(client, target) {
6067
- const parsed = parseReferencedPlayTarget(target);
7507
+ const parsed = parseReferencedPlayTarget2(target);
6068
7508
  const detail = await client.getPlay(parsed.playName);
6069
7509
  if (detail.play.ownerType === "deepline" && !isPrebuiltReferenceTarget(target)) {
6070
7510
  throw buildBarePrebuiltReferenceError({
@@ -6085,10 +7525,10 @@ function formatPlayListReference(play) {
6085
7525
  return play.reference || play.name;
6086
7526
  }
6087
7527
  function defaultMaterializedPlayPath(reference) {
6088
- return (0, import_node_path10.resolve)(defaultStarterPlayPath(reference));
7528
+ return (0, import_node_path11.resolve)(defaultStarterPlayPath(reference));
6089
7529
  }
6090
7530
  function defaultStarterPlayPath(reference) {
6091
- const playName = parseReferencedPlayTarget(reference).unqualifiedPlayName;
7531
+ const playName = parseReferencedPlayTarget2(reference).unqualifiedPlayName;
6092
7532
  const safeName = playName.trim().toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
6093
7533
  return `./${safeName || "play"}.play.ts`;
6094
7534
  }
@@ -6111,15 +7551,15 @@ function materializeRemotePlaySource(input) {
6111
7551
  return null;
6112
7552
  }
6113
7553
  const outputPath = input.outPath ?? defaultMaterializedPlayPath(input.playName);
6114
- if ((0, import_node_fs8.existsSync)(outputPath)) {
6115
- const existingSource = (0, import_node_fs8.readFileSync)(outputPath, "utf-8");
7554
+ if ((0, import_node_fs9.existsSync)(outputPath)) {
7555
+ const existingSource = (0, import_node_fs9.readFileSync)(outputPath, "utf-8");
6116
7556
  if (existingSource === input.sourceCode) {
6117
7557
  return { path: outputPath, status: "unchanged", created: false };
6118
7558
  }
6119
- (0, import_node_fs8.writeFileSync)(outputPath, input.sourceCode, "utf-8");
7559
+ (0, import_node_fs9.writeFileSync)(outputPath, input.sourceCode, "utf-8");
6120
7560
  return { path: outputPath, status: "updated", created: false };
6121
7561
  }
6122
- (0, import_node_fs8.writeFileSync)(outputPath, input.sourceCode, "utf-8");
7562
+ (0, import_node_fs9.writeFileSync)(outputPath, input.sourceCode, "utf-8");
6123
7563
  return { path: outputPath, status: "created", created: true };
6124
7564
  }
6125
7565
  function formatLoadedPlayMessage(materializedFile) {
@@ -6144,7 +7584,7 @@ To make your own version:
6144
7584
  );
6145
7585
  }
6146
7586
  async function ensureEditableRemotePlay(client, target) {
6147
- const parsed = parseReferencedPlayTarget(target);
7587
+ const parsed = parseReferencedPlayTarget2(target);
6148
7588
  const detail = await client.getPlay(parsed.playName);
6149
7589
  if (detail.play.ownerType === "deepline") {
6150
7590
  throw buildReadonlyPrebuiltPlayError(formatPlayReference(detail.play));
@@ -6164,7 +7604,7 @@ function extractPlayName(code, filePath) {
6164
7604
  throw buildMissingDefinePlayError(filePath);
6165
7605
  }
6166
7606
  function isFileTarget(target) {
6167
- return (0, import_node_fs8.existsSync)((0, import_node_path10.resolve)(target));
7607
+ return (0, import_node_fs9.existsSync)((0, import_node_path11.resolve)(target));
6168
7608
  }
6169
7609
  function looksLikeRunId(target) {
6170
7610
  return /^play\/[^/]+\/run\/[^/]+/.test(target.trim());
@@ -6185,7 +7625,7 @@ function looksLikeFilePath(target) {
6185
7625
  }
6186
7626
  return target.includes("\\") || /\.(ts|js|mjs|play\.ts)$/.test(target);
6187
7627
  }
6188
- function parsePositiveInteger2(value, flagName) {
7628
+ function parsePositiveInteger3(value, flagName) {
6189
7629
  const parsed = Number.parseInt(value, 10);
6190
7630
  if (!Number.isFinite(parsed) || parsed <= 0) {
6191
7631
  throw new Error(`${flagName} must be a positive integer.`);
@@ -6193,7 +7633,7 @@ function parsePositiveInteger2(value, flagName) {
6193
7633
  return parsed;
6194
7634
  }
6195
7635
  function parseJsonInput(raw) {
6196
- const source = raw.startsWith("@") ? (0, import_node_fs8.readFileSync)((0, import_node_path10.resolve)(raw.slice(1)), "utf-8") : raw;
7636
+ const source = raw.startsWith("@") ? (0, import_node_fs9.readFileSync)((0, import_node_path11.resolve)(raw.slice(1)), "utf-8") : raw;
6197
7637
  const parsed = JSON.parse(source);
6198
7638
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
6199
7639
  throw new Error("--input must be a JSON object.");
@@ -6260,7 +7700,8 @@ function setDottedInputValue(input, path, value) {
6260
7700
  cursor[parts[parts.length - 1]] = value;
6261
7701
  }
6262
7702
  function schemaMetadata(schema, key) {
6263
- if (!schema || typeof schema !== "object" || Array.isArray(schema)) return null;
7703
+ if (!schema || typeof schema !== "object" || Array.isArray(schema))
7704
+ return null;
6264
7705
  const value = schema[key];
6265
7706
  return value && typeof value === "object" && !Array.isArray(value) ? value : null;
6266
7707
  }
@@ -6294,7 +7735,7 @@ function fileInputBindingsFromStaticPipeline(staticPipeline) {
6294
7735
  function isLocalFilePathValue(value) {
6295
7736
  if (typeof value !== "string" || !value.trim()) return false;
6296
7737
  if (/^[a-z][a-z0-9+.-]*:\/\//i.test(value.trim())) return false;
6297
- return (0, import_node_fs8.existsSync)((0, import_node_path10.resolve)(value));
7738
+ return (0, import_node_fs9.existsSync)((0, import_node_path11.resolve)(value));
6298
7739
  }
6299
7740
  function inputContainsLocalFilePath(value) {
6300
7741
  if (isLocalFilePathValue(value)) {
@@ -6315,13 +7756,15 @@ function namedRunNeedsPlayDefinition(input) {
6315
7756
  }
6316
7757
  async function stageFileInputArgs(input) {
6317
7758
  const uniqueBindings = [
6318
- ...new Map(input.bindings.map((binding) => [binding.inputPath, binding])).values()
7759
+ ...new Map(
7760
+ input.bindings.map((binding) => [binding.inputPath, binding])
7761
+ ).values()
6319
7762
  ];
6320
7763
  const localFiles = uniqueBindings.flatMap((binding) => {
6321
7764
  const value = getDottedInputValue(input.runtimeInput, binding.inputPath);
6322
7765
  if (!isLocalFilePathValue(value)) return [];
6323
- const absolutePath = (0, import_node_path10.resolve)(value);
6324
- return [{ binding, absolutePath, logicalPath: (0, import_node_path10.basename)(absolutePath) }];
7766
+ const absolutePath = (0, import_node_path11.resolve)(value);
7767
+ return [{ binding, absolutePath, logicalPath: (0, import_node_path11.basename)(absolutePath) }];
6325
7768
  });
6326
7769
  if (localFiles.length === 0) {
6327
7770
  return { inputFile: null, packagedFiles: [] };
@@ -6333,10 +7776,18 @@ async function stageFileInputArgs(input) {
6333
7776
  localFiles.map((file) => stageFile(file.logicalPath, file.absolutePath))
6334
7777
  );
6335
7778
  for (const [index, file] of localFiles.entries()) {
6336
- setDottedInputValue(input.runtimeInput, file.binding.inputPath, file.logicalPath);
7779
+ setDottedInputValue(
7780
+ input.runtimeInput,
7781
+ file.binding.inputPath,
7782
+ file.logicalPath
7783
+ );
6337
7784
  const stagedFile = staged[index];
6338
7785
  if (stagedFile && stagedFile.logicalPath !== file.logicalPath) {
6339
- setDottedInputValue(input.runtimeInput, file.binding.inputPath, stagedFile.logicalPath);
7786
+ setDottedInputValue(
7787
+ input.runtimeInput,
7788
+ file.binding.inputPath,
7789
+ stagedFile.logicalPath
7790
+ );
6340
7791
  }
6341
7792
  }
6342
7793
  return {
@@ -6345,7 +7796,7 @@ async function stageFileInputArgs(input) {
6345
7796
  };
6346
7797
  }
6347
7798
  function stageFile(logicalPath, absolutePath) {
6348
- const buffer = (0, import_node_fs8.readFileSync)(absolutePath);
7799
+ const buffer = (0, import_node_fs9.readFileSync)(absolutePath);
6349
7800
  return {
6350
7801
  logicalPath,
6351
7802
  contentBase64: buffer.toString("base64"),
@@ -6356,9 +7807,9 @@ function stageFile(logicalPath, absolutePath) {
6356
7807
  }
6357
7808
  function normalizePlayPath(filePath) {
6358
7809
  try {
6359
- return import_node_fs8.realpathSync.native((0, import_node_path10.resolve)(filePath));
7810
+ return import_node_fs9.realpathSync.native((0, import_node_path11.resolve)(filePath));
6360
7811
  } catch {
6361
- return (0, import_node_path10.resolve)(filePath);
7812
+ return (0, import_node_path11.resolve)(filePath);
6362
7813
  }
6363
7814
  }
6364
7815
  function formatBundlingErrors(filePath, errors) {
@@ -6716,7 +8167,10 @@ function formatProgressCounts(input) {
6716
8167
  if (completed === null || total === null || total <= 0) {
6717
8168
  return null;
6718
8169
  }
6719
- const percent = Math.max(0, Math.min(100, Math.round(completed / total * 100)));
8170
+ const percent = Math.max(
8171
+ 0,
8172
+ Math.min(100, Math.round(completed / total * 100))
8173
+ );
6720
8174
  const failed = typeof input.failed === "number" && Number.isFinite(input.failed) && input.failed > 0 ? `, failed ${formatInteger(input.failed)}` : "";
6721
8175
  return `${formatInteger(completed)}/${formatInteger(total)} (${percent}%)${failed}`;
6722
8176
  }
@@ -7430,7 +8884,9 @@ function buildInsufficientCreditsSummaryLines(input) {
7430
8884
  const runId = input.status.runId?.trim();
7431
8885
  if (runId) {
7432
8886
  lines.push(` inspect: deepline runs get ${runId} --json`);
7433
- lines.push(` export partial: deepline runs export ${runId} --out output.csv`);
8887
+ lines.push(
8888
+ ` export partial: deepline runs export ${runId} --out output.csv`
8889
+ );
7434
8890
  }
7435
8891
  return lines;
7436
8892
  }
@@ -7502,7 +8958,10 @@ function normalizeErrorsForEnvelope(status, error) {
7502
8958
  }
7503
8959
  return {
7504
8960
  ...entry,
7505
- message: formatInsufficientCreditsMessage({ billing: billing2, error: message2 }),
8961
+ message: formatInsufficientCreditsMessage({
8962
+ billing: billing2,
8963
+ error: message2
8964
+ }),
7506
8965
  billing: stripProviderSpendFromBilling(billing2)
7507
8966
  };
7508
8967
  });
@@ -7657,7 +9116,9 @@ function buildRunPackageTextLines(packaged) {
7657
9116
  const runId = typeof run.id === "string" ? run.id : "unknown";
7658
9117
  const status = typeof run.status === "string" ? run.status : "unknown";
7659
9118
  const playName = typeof run.playName === "string" ? run.playName : null;
7660
- const lines = [`${status === "completed" ? "\u2713" : status === "failed" ? "\u2717" : "\u2022"} ${status} ${runId}`];
9119
+ const lines = [
9120
+ `${status === "completed" ? "\u2713" : status === "failed" ? "\u2717" : "\u2022"} ${status} ${runId}`
9121
+ ];
7661
9122
  if (playName) {
7662
9123
  lines.push(` play: ${playName}`);
7663
9124
  }
@@ -7728,13 +9189,16 @@ function writePlayResult(status, jsonOutput, options) {
7728
9189
  }
7729
9190
  lines.push(...renderedServerView.actions);
7730
9191
  const payload = options?.fullJson ? enrichPlayStatusWithDatasetStats(status) : compactPlayStatus(status);
7731
- printCommandEnvelope({
7732
- ...payload,
7733
- render: {
7734
- sections: [{ title: "run result", lines }]
7735
- }
7736
- }, { json: jsonOutput, text: `${lines.join("\n")}
7737
- ` });
9192
+ printCommandEnvelope(
9193
+ {
9194
+ ...payload,
9195
+ render: {
9196
+ sections: [{ title: "run result", lines }]
9197
+ }
9198
+ },
9199
+ { json: jsonOutput, text: `${lines.join("\n")}
9200
+ ` }
9201
+ );
7738
9202
  }
7739
9203
  async function resolvePlayRunOutputStatus(input) {
7740
9204
  if (!input.fullJson || !getPlayRunPackage(input.status)) {
@@ -7759,7 +9223,7 @@ function sqlStringLiteral(value) {
7759
9223
  return `'${value.replace(/'/g, "''")}'`;
7760
9224
  }
7761
9225
  function runExportRetryCommand(runId, outPath, datasetPath) {
7762
- return `deepline runs export ${runId}${datasetPath ? ` --dataset ${shellSingleQuote(datasetPath)}` : ""} --out ${shellSingleQuote((0, import_node_path10.resolve)(outPath))}`;
9226
+ return `deepline runs export ${runId}${datasetPath ? ` --dataset ${shellSingleQuote(datasetPath)}` : ""} --out ${shellSingleQuote((0, import_node_path11.resolve)(outPath))}`;
7763
9227
  }
7764
9228
  function extractRunPlayName(status) {
7765
9229
  const run = status.run;
@@ -7793,7 +9257,7 @@ function buildCustomerDbQueryPlan(input) {
7793
9257
  return {
7794
9258
  sql,
7795
9259
  json: `${base} --json`,
7796
- csv: `${base} --format csv --out ${shellSingleQuote((0, import_node_path10.resolve)(input.outPath))}`
9260
+ csv: `${base} --format csv --out ${shellSingleQuote((0, import_node_path11.resolve)(input.outPath))}`
7797
9261
  };
7798
9262
  }
7799
9263
  function exportableSheetRow(row) {
@@ -8093,7 +9557,9 @@ function renderServerResultView(value) {
8093
9557
  (field) => typeof field === "string"
8094
9558
  ) : [];
8095
9559
  if (rawResultFields.length > 0) {
8096
- lines.push(` tool-result columns: ${rawResultFields.join(", ")}`);
9560
+ lines.push(
9561
+ ` tool-result columns: ${rawResultFields.join(", ")}`
9562
+ );
8097
9563
  }
8098
9564
  }
8099
9565
  if (typeof table.slowExportAsCsvCommand === "string") {
@@ -8146,10 +9612,13 @@ function writeStartedPlayRun(input) {
8146
9612
  ` stop run: deepline runs stop ${input.runId} --reason "stale lock" --json`
8147
9613
  ];
8148
9614
  if (input.jsonOutput) {
8149
- printCommandEnvelope({
8150
- ...payload,
8151
- render: { sections: [{ title: "play run", lines }] }
8152
- }, { json: true });
9615
+ printCommandEnvelope(
9616
+ {
9617
+ ...payload,
9618
+ render: { sections: [{ title: "play run", lines }] }
9619
+ },
9620
+ { json: true }
9621
+ );
8153
9622
  return;
8154
9623
  }
8155
9624
  if (input.dashboardUrl) {
@@ -8160,11 +9629,14 @@ function writeStartedPlayRun(input) {
8160
9629
  input.progress.writeLine(output, process.stdout);
8161
9630
  return;
8162
9631
  }
8163
- printCommandEnvelope({
8164
- ...payload,
8165
- render: { sections: [{ title: "play run", lines }] }
8166
- }, { json: false, text: `${output}
8167
- ` });
9632
+ printCommandEnvelope(
9633
+ {
9634
+ ...payload,
9635
+ render: { sections: [{ title: "play run", lines }] }
9636
+ },
9637
+ { json: false, text: `${output}
9638
+ ` }
9639
+ );
8168
9640
  }
8169
9641
  function parsePlayRunOptions(args) {
8170
9642
  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.";
@@ -8187,7 +9659,7 @@ function parsePlayRunOptions(args) {
8187
9659
  continue;
8188
9660
  }
8189
9661
  if (arg === "--name" && args[index + 1]) {
8190
- playName = parseReferencedPlayTarget(args[++index]).playName;
9662
+ playName = parseReferencedPlayTarget2(args[++index]).playName;
8191
9663
  continue;
8192
9664
  }
8193
9665
  if ((arg === "--input" || arg === "-i") && args[index + 1]) {
@@ -8217,7 +9689,7 @@ function parsePlayRunOptions(args) {
8217
9689
  );
8218
9690
  }
8219
9691
  if ((arg === "--tail-timeout-ms" || arg === "--timeout-ms") && args[index + 1]) {
8220
- waitTimeoutMs = parsePositiveInteger2(args[++index], arg);
9692
+ waitTimeoutMs = parsePositiveInteger3(args[++index], arg);
8221
9693
  continue;
8222
9694
  }
8223
9695
  if (PLAY_RUN_RESERVED_BOOLEAN_FLAGS.has(arg)) {
@@ -8251,7 +9723,7 @@ function parsePlayRunOptions(args) {
8251
9723
  if (isFileTarget(arg) || looksLikeFilePath(arg)) {
8252
9724
  filePath = arg;
8253
9725
  } else {
8254
- playName = parseReferencedPlayTarget(arg).playName;
9726
+ playName = parseReferencedPlayTarget2(arg).playName;
8255
9727
  }
8256
9728
  continue;
8257
9729
  }
@@ -8300,34 +9772,34 @@ function shouldUseLocalOnlyPlayCheck() {
8300
9772
  const value = process.env.DEEPLINE_PLAY_CHECK_LOCAL_ONLY?.trim().toLowerCase();
8301
9773
  return value === "1" || value === "true" || value === "yes" || value === "on";
8302
9774
  }
8303
- function isRecord3(value) {
9775
+ function isRecord4(value) {
8304
9776
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
8305
9777
  }
8306
- function stringValue(value) {
9778
+ function stringValue2(value) {
8307
9779
  return typeof value === "string" ? value.trim() : "";
8308
9780
  }
8309
9781
  function asArray(value) {
8310
9782
  return Array.isArray(value) ? value : [];
8311
9783
  }
8312
- function extractionEntries(value) {
8313
- if (Array.isArray(value)) return value.filter(isRecord3);
8314
- if (!isRecord3(value)) return [];
9784
+ function extractionEntries2(value) {
9785
+ if (Array.isArray(value)) return value.filter(isRecord4);
9786
+ if (!isRecord4(value)) return [];
8315
9787
  return Object.entries(value).map(
8316
- ([name, entry]) => isRecord3(entry) ? { name, ...entry } : { name }
9788
+ ([name, entry]) => isRecord4(entry) ? { name, ...entry } : { name }
8317
9789
  );
8318
9790
  }
8319
9791
  function firstRawPath(entry) {
8320
- const details = isRecord3(entry.details) ? entry.details : {};
9792
+ const details = isRecord4(entry.details) ? entry.details : {};
8321
9793
  const paths = [
8322
9794
  ...asArray(details.rawToolOutputPaths),
8323
9795
  ...asArray(details.raw_tool_output_paths),
8324
9796
  ...asArray(details.candidatePaths),
8325
9797
  ...asArray(details.candidate_paths)
8326
- ].map(stringValue).filter(Boolean);
9798
+ ].map(stringValue2).filter(Boolean);
8327
9799
  return paths[0];
8328
9800
  }
8329
9801
  function checkHintExpression(value) {
8330
- return stringValue(value).replace(/^toolExecutionResult\./, "result.");
9802
+ return stringValue2(value).replace(/^toolExecutionResult\./, "result.");
8331
9803
  }
8332
9804
  function checkHintRawPath(value) {
8333
9805
  return value?.replace(/^toolResponse\./, "result.toolResponse.");
@@ -8335,14 +9807,14 @@ function checkHintRawPath(value) {
8335
9807
  function collectStaticPipelineToolIds(staticPipeline) {
8336
9808
  const seen = /* @__PURE__ */ new Set();
8337
9809
  const visitPipeline = (pipeline) => {
8338
- if (!isRecord3(pipeline)) return;
9810
+ if (!isRecord4(pipeline)) return;
8339
9811
  for (const step of [
8340
9812
  ...asArray(pipeline.stages),
8341
9813
  ...asArray(pipeline.substeps)
8342
9814
  ]) {
8343
- if (!isRecord3(step)) continue;
9815
+ if (!isRecord4(step)) continue;
8344
9816
  if (step.type === "tool") {
8345
- const toolId = stringValue(step.toolId) || stringValue(step.tool);
9817
+ const toolId = stringValue2(step.toolId) || stringValue2(step.tool);
8346
9818
  if (toolId) seen.add(toolId);
8347
9819
  }
8348
9820
  if (step.type === "play_call") {
@@ -8354,20 +9826,20 @@ function collectStaticPipelineToolIds(staticPipeline) {
8354
9826
  return [...seen].sort();
8355
9827
  }
8356
9828
  function toolGetterHintFromMetadata(toolId, tool) {
8357
- const usageGuidance = isRecord3(tool.usageGuidance) ? tool.usageGuidance : {};
8358
- const resultGuidance = isRecord3(usageGuidance.toolExecutionResult) ? usageGuidance.toolExecutionResult : isRecord3(usageGuidance.tool_execution_result) ? usageGuidance.tool_execution_result : {};
8359
- const toolResponse = isRecord3(resultGuidance.toolResponse) ? resultGuidance.toolResponse : isRecord3(resultGuidance.tool_response) ? resultGuidance.tool_response : {};
8360
- const lists = extractionEntries(
9829
+ const usageGuidance = isRecord4(tool.usageGuidance) ? tool.usageGuidance : {};
9830
+ const resultGuidance = isRecord4(usageGuidance.toolExecutionResult) ? usageGuidance.toolExecutionResult : isRecord4(usageGuidance.tool_execution_result) ? usageGuidance.tool_execution_result : {};
9831
+ const toolResponse = isRecord4(resultGuidance.toolResponse) ? resultGuidance.toolResponse : isRecord4(resultGuidance.tool_response) ? resultGuidance.tool_response : {};
9832
+ const lists = extractionEntries2(
8361
9833
  resultGuidance.extractedLists ?? resultGuidance.extracted_lists
8362
9834
  ).map((entry) => ({
8363
- name: stringValue(entry.name),
9835
+ name: stringValue2(entry.name),
8364
9836
  expression: checkHintExpression(entry.expression),
8365
9837
  raw: checkHintRawPath(firstRawPath(entry))
8366
9838
  })).filter((entry) => entry.name && entry.expression);
8367
- const values = extractionEntries(
9839
+ const values = extractionEntries2(
8368
9840
  resultGuidance.extractedValues ?? resultGuidance.extracted_values
8369
9841
  ).map((entry) => ({
8370
- name: stringValue(entry.name),
9842
+ name: stringValue2(entry.name),
8371
9843
  expression: checkHintExpression(entry.expression),
8372
9844
  raw: checkHintRawPath(firstRawPath(entry))
8373
9845
  })).filter((entry) => entry.name && entry.expression);
@@ -8423,12 +9895,12 @@ function printToolGetterHints(hints) {
8423
9895
  async function handlePlayCheck(args) {
8424
9896
  const options = parsePlayCheckOptions(args);
8425
9897
  if (!isFileTarget(options.target)) {
8426
- const resolved = (0, import_node_path10.resolve)(options.target);
9898
+ const resolved = (0, import_node_path11.resolve)(options.target);
8427
9899
  console.error(`File not found: ${resolved}`);
8428
9900
  return 1;
8429
9901
  }
8430
- const absolutePlayPath = (0, import_node_path10.resolve)(options.target);
8431
- const sourceCode = (0, import_node_fs8.readFileSync)(absolutePlayPath, "utf-8");
9902
+ const absolutePlayPath = (0, import_node_path11.resolve)(options.target);
9903
+ const sourceCode = (0, import_node_fs9.readFileSync)(absolutePlayPath, "utf-8");
8432
9904
  let graph;
8433
9905
  try {
8434
9906
  graph = await collectBundledPlayGraph(absolutePlayPath);
@@ -8455,8 +9927,10 @@ async function handlePlayCheck(args) {
8455
9927
  graphHash: graph.root.artifact.graphHash
8456
9928
  };
8457
9929
  if (options.jsonOutput) {
8458
- process.stdout.write(`${JSON.stringify({ name: playName, ...result2 })}
8459
- `);
9930
+ process.stdout.write(
9931
+ `${JSON.stringify({ name: playName, ...result2 })}
9932
+ `
9933
+ );
8460
9934
  } else {
8461
9935
  console.log(`\u2713 ${playName} passed local play check`);
8462
9936
  console.log(` artifact: ${result2.artifactHash.slice(0, 12)}`);
@@ -8480,8 +9954,10 @@ async function handlePlayCheck(args) {
8480
9954
  toolGetterHints: result.toolGetterHints ?? await buildToolGetterHints(client, result.staticPipeline)
8481
9955
  };
8482
9956
  if (options.jsonOutput) {
8483
- process.stdout.write(`${JSON.stringify({ name: playName, ...enrichedResult })}
8484
- `);
9957
+ process.stdout.write(
9958
+ `${JSON.stringify({ name: playName, ...enrichedResult })}
9959
+ `
9960
+ );
8485
9961
  } else if (enrichedResult.valid) {
8486
9962
  console.log(`\u2713 ${playName} passed cloud play check`);
8487
9963
  if (enrichedResult.artifactHash) {
@@ -8503,12 +9979,12 @@ async function handleFileBackedRun(options) {
8503
9979
  }
8504
9980
  const client = new DeeplineClient();
8505
9981
  const progress = getActiveCliProgress() ?? createCliProgress(!options.jsonOutput);
8506
- const absolutePlayPath = (0, import_node_path10.resolve)(options.target.path);
9982
+ const absolutePlayPath = (0, import_node_path11.resolve)(options.target.path);
8507
9983
  progress.phase("compiling play");
8508
9984
  const sourceCode = traceCliSync(
8509
9985
  "cli.play_file_read_source",
8510
9986
  { targetKind: "file" },
8511
- () => (0, import_node_fs8.readFileSync)(absolutePlayPath, "utf-8")
9987
+ () => (0, import_node_fs9.readFileSync)(absolutePlayPath, "utf-8")
8512
9988
  );
8513
9989
  const runtimeInput = options.input ? { ...options.input } : {};
8514
9990
  let graph;
@@ -8792,19 +10268,19 @@ async function handlePlayRun(args) {
8792
10268
  if (isFileTarget(options.target.path)) {
8793
10269
  return handleFileBackedRun(options);
8794
10270
  }
8795
- const resolved = (0, import_node_path10.resolve)(options.target.path);
10271
+ const resolved = (0, import_node_path11.resolve)(options.target.path);
8796
10272
  console.error(`File not found: ${resolved}`);
8797
- const dir = (0, import_node_path10.dirname)(resolved);
8798
- if ((0, import_node_fs8.existsSync)(dir)) {
8799
- const base = (0, import_node_path10.basename)(resolved);
10273
+ const dir = (0, import_node_path11.dirname)(resolved);
10274
+ if ((0, import_node_fs9.existsSync)(dir)) {
10275
+ const base = (0, import_node_path11.basename)(resolved);
8800
10276
  try {
8801
- const siblings = (0, import_node_fs8.readdirSync)(dir).filter(
10277
+ const siblings = (0, import_node_fs9.readdirSync)(dir).filter(
8802
10278
  (f) => f.includes(base.replace(/\.(play\.)?ts$/, "")) || f.endsWith(".play.ts")
8803
10279
  );
8804
10280
  if (siblings.length > 0) {
8805
10281
  console.error(`Did you mean one of these?`);
8806
10282
  for (const s of siblings.slice(0, 5)) {
8807
- console.error(` ${(0, import_node_path10.join)(dir, s)}`);
10283
+ console.error(` ${(0, import_node_path11.join)(dir, s)}`);
8808
10284
  }
8809
10285
  }
8810
10286
  } catch {
@@ -8858,7 +10334,7 @@ async function handleRunsList(args) {
8858
10334
  for (let index = 0; index < args.length; index += 1) {
8859
10335
  const arg = args[index];
8860
10336
  if ((arg === "--play" || arg === "--name") && args[index + 1]) {
8861
- playName = parseReferencedPlayTarget(args[++index]).playName;
10337
+ playName = parseReferencedPlayTarget2(args[++index]).playName;
8862
10338
  continue;
8863
10339
  }
8864
10340
  if (arg === "--status" && args[index + 1]) {
@@ -8887,15 +10363,20 @@ async function handleRunsList(args) {
8887
10363
  executionTime: run.executionTime,
8888
10364
  playName: run.memo?.playName ?? playName
8889
10365
  }));
8890
- const lines = runs.length === 0 ? [`No runs found for ${playName}.`] : runs.map((run) => `${run.runId} ${run.status} ${formatTimestamp(run.startedAt)}`);
8891
- printCommandEnvelope({
8892
- runs,
8893
- count: runs.length,
8894
- next: {
8895
- get: runs[0]?.runId ? `deepline runs get ${runs[0].runId} --json` : null
10366
+ const lines = runs.length === 0 ? [`No runs found for ${playName}.`] : runs.map(
10367
+ (run) => `${run.runId} ${run.status} ${formatTimestamp(run.startedAt)}`
10368
+ );
10369
+ printCommandEnvelope(
10370
+ {
10371
+ runs,
10372
+ count: runs.length,
10373
+ next: {
10374
+ get: runs[0]?.runId ? `deepline runs get ${runs[0].runId} --json` : null
10375
+ },
10376
+ render: { sections: [{ title: "runs", lines }] }
8896
10377
  },
8897
- render: { sections: [{ title: "runs", lines }] }
8898
- }, { json: argsWantJson(args) });
10378
+ { json: argsWantJson(args) }
10379
+ );
8899
10380
  return 0;
8900
10381
  }
8901
10382
  async function handleRunTail(args) {
@@ -8910,7 +10391,9 @@ async function handleRunTail(args) {
8910
10391
  for (let index = 0; index < args.length; index += 1) {
8911
10392
  const arg = args[index];
8912
10393
  if (arg === "--cursor") {
8913
- console.error("--cursor was removed. deepline runs tail reads the canonical run stream.");
10394
+ console.error(
10395
+ "--cursor was removed. deepline runs tail reads the canonical run stream."
10396
+ );
8914
10397
  return 1;
8915
10398
  }
8916
10399
  if (arg.startsWith("--") && arg !== "--json" && arg !== "--compact") {
@@ -8937,42 +10420,58 @@ async function handleRunLogs(args) {
8937
10420
  for (let index = 0; index < args.length; index += 1) {
8938
10421
  const arg = args[index];
8939
10422
  if (arg === "--limit" && args[index + 1]) {
8940
- limit = parsePositiveInteger2(args[++index], "--limit");
10423
+ limit = parsePositiveInteger3(args[++index], "--limit");
8941
10424
  continue;
8942
10425
  }
8943
10426
  if (arg === "--out" && args[index + 1]) {
8944
- outPath = (0, import_node_path10.resolve)(args[++index]);
10427
+ outPath = (0, import_node_path11.resolve)(args[++index]);
8945
10428
  }
8946
10429
  }
8947
10430
  const client = new DeeplineClient();
8948
10431
  const status = await client.runs.get(runId);
8949
10432
  const logs = status.progress?.logs ?? [];
8950
10433
  if (outPath) {
8951
- (0, import_node_fs8.writeFileSync)(outPath, `${logs.join("\n")}${logs.length > 0 ? "\n" : ""}`);
8952
- printCommandEnvelope({
8953
- runId: status.runId,
8954
- log_path: outPath,
8955
- lineCount: logs.length,
8956
- local: { log_path: outPath },
8957
- render: { sections: [{ title: "run logs", lines: [`Wrote ${logs.length} log lines to ${outPath}`] }] }
8958
- }, { json: argsWantJson(args) });
10434
+ (0, import_node_fs9.writeFileSync)(outPath, `${logs.join("\n")}${logs.length > 0 ? "\n" : ""}`);
10435
+ printCommandEnvelope(
10436
+ {
10437
+ runId: status.runId,
10438
+ log_path: outPath,
10439
+ lineCount: logs.length,
10440
+ local: { log_path: outPath },
10441
+ render: {
10442
+ sections: [
10443
+ {
10444
+ title: "run logs",
10445
+ lines: [`Wrote ${logs.length} log lines to ${outPath}`]
10446
+ }
10447
+ ]
10448
+ }
10449
+ },
10450
+ { json: argsWantJson(args) }
10451
+ );
8959
10452
  return 0;
8960
10453
  }
8961
10454
  const entries = logs.slice(Math.max(0, logs.length - limit));
8962
- printCommandEnvelope({
8963
- runId: status.runId,
8964
- totalCount: logs.length,
8965
- returnedCount: entries.length,
8966
- firstSequence: logs.length === 0 ? null : logs.length - entries.length + 1,
8967
- lastSequence: logs.length === 0 ? null : logs.length,
8968
- truncated: logs.length > entries.length,
8969
- hasMore: logs.length > entries.length,
8970
- entries,
8971
- next: {
8972
- export: `deepline runs logs ${status.runId} --out run.log --json`
10455
+ printCommandEnvelope(
10456
+ {
10457
+ runId: status.runId,
10458
+ totalCount: logs.length,
10459
+ returnedCount: entries.length,
10460
+ firstSequence: logs.length === 0 ? null : logs.length - entries.length + 1,
10461
+ lastSequence: logs.length === 0 ? null : logs.length,
10462
+ truncated: logs.length > entries.length,
10463
+ hasMore: logs.length > entries.length,
10464
+ entries,
10465
+ next: {
10466
+ export: `deepline runs logs ${status.runId} --out run.log --json`
10467
+ },
10468
+ render: { sections: [{ title: "run logs", lines: entries }] }
8973
10469
  },
8974
- render: { sections: [{ title: "run logs", lines: entries }] }
8975
- }, { json: argsWantJson(args), text: `${entries.join("\n")}${entries.length > 0 ? "\n" : ""}` });
10470
+ {
10471
+ json: argsWantJson(args),
10472
+ text: `${entries.join("\n")}${entries.length > 0 ? "\n" : ""}`
10473
+ }
10474
+ );
8976
10475
  return 0;
8977
10476
  }
8978
10477
  async function handleRunStop(args) {
@@ -8997,10 +10496,13 @@ async function handleRunStop(args) {
8997
10496
  `Stopped ${result.runId}`,
8998
10497
  ...result.hitlCancelledCount > 0 ? [`cancelled HITL waits: ${result.hitlCancelledCount}`] : []
8999
10498
  ];
9000
- printCommandEnvelope({
9001
- ...result,
9002
- render: { sections: [{ title: "run stop", lines }] }
9003
- }, { json: argsWantJson(args) });
10499
+ printCommandEnvelope(
10500
+ {
10501
+ ...result,
10502
+ render: { sections: [{ title: "run stop", lines }] }
10503
+ },
10504
+ { json: argsWantJson(args) }
10505
+ );
9004
10506
  return 0;
9005
10507
  }
9006
10508
  async function handleRunExport(args) {
@@ -9018,7 +10520,7 @@ async function handleRunExport(args) {
9018
10520
  for (let index = 0; index < args.length; index += 1) {
9019
10521
  const arg = args[index];
9020
10522
  if (arg === "--out" && args[index + 1]) {
9021
- outPath = (0, import_node_path10.resolve)(args[++index]);
10523
+ outPath = (0, import_node_path11.resolve)(args[++index]);
9022
10524
  continue;
9023
10525
  }
9024
10526
  if (arg === "--dataset" && args[index + 1]) {
@@ -9026,7 +10528,7 @@ async function handleRunExport(args) {
9026
10528
  continue;
9027
10529
  }
9028
10530
  if (arg === "--metadata-out" && args[index + 1]) {
9029
- metadataOutPath = (0, import_node_path10.resolve)(args[++index]);
10531
+ metadataOutPath = (0, import_node_path11.resolve)(args[++index]);
9030
10532
  }
9031
10533
  }
9032
10534
  if (!outPath) {
@@ -9083,7 +10585,7 @@ async function handleRunExport(args) {
9083
10585
  }
9084
10586
  };
9085
10587
  if (metadataOutPath) {
9086
- (0, import_node_fs8.writeFileSync)(
10588
+ (0, import_node_fs9.writeFileSync)(
9087
10589
  metadataOutPath,
9088
10590
  `${JSON.stringify(payload, null, 2)}
9089
10591
  `,
@@ -9113,10 +10615,10 @@ async function handlePlayGet(args) {
9113
10615
  for (let index = 1; index < args.length; index += 1) {
9114
10616
  const arg = args[index];
9115
10617
  if (arg === "--out" && args[index + 1]) {
9116
- outPath = (0, import_node_path10.resolve)(args[++index]);
10618
+ outPath = (0, import_node_path11.resolve)(args[++index]);
9117
10619
  }
9118
10620
  }
9119
- const playName = isFileTarget(target) ? extractPlayName((0, import_node_fs8.readFileSync)((0, import_node_path10.resolve)(target), "utf-8"), (0, import_node_path10.resolve)(target)) : parseReferencedPlayTarget(target).playName;
10621
+ const playName = isFileTarget(target) ? extractPlayName((0, import_node_fs9.readFileSync)((0, import_node_path11.resolve)(target), "utf-8"), (0, import_node_path11.resolve)(target)) : parseReferencedPlayTarget2(target).playName;
9120
10622
  const detail = isFileTarget(target) ? await client.getPlay(playName) : await assertCanonicalNamedPlayReference(client, target);
9121
10623
  const resolvedSource = detail.play.workingRevision?.sourceCode ?? detail.play.liveRevision?.sourceCode ?? detail.play.currentRevision?.sourceCode ?? detail.play.sourceCode ?? "";
9122
10624
  const materializedFile = outPath ? materializeRemotePlaySource({
@@ -9201,7 +10703,7 @@ async function handlePlayVersions(args) {
9201
10703
  const jsonOutput = argsWantJson(args);
9202
10704
  await assertCanonicalNamedPlayReference(client, playName);
9203
10705
  const versions = await client.listPlayVersions(
9204
- parseReferencedPlayTarget(playName).playName
10706
+ parseReferencedPlayTarget2(playName).playName
9205
10707
  );
9206
10708
  if (jsonOutput) {
9207
10709
  process.stdout.write(`${JSON.stringify({ versions })}
@@ -9335,7 +10837,8 @@ function compactPlaySchema(schema) {
9335
10837
  return fields.length > 0 ? { fields } : schema;
9336
10838
  }
9337
10839
  function playSchemaMetadata(schema, key) {
9338
- if (!schema || typeof schema !== "object" || Array.isArray(schema)) return null;
10840
+ if (!schema || typeof schema !== "object" || Array.isArray(schema))
10841
+ return null;
9339
10842
  const value = schema[key];
9340
10843
  return value && typeof value === "object" && !Array.isArray(value) ? value : null;
9341
10844
  }
@@ -9350,7 +10853,10 @@ function playRunCommand(play, options) {
9350
10853
  function summarizePlayListItemForCli(play, options) {
9351
10854
  const aliases = play.aliases?.length ? play.aliases : [play.name];
9352
10855
  const csvInput = playSchemaMetadata(play.inputSchema, "csvInput");
9353
- const rowOutputSchema = playSchemaMetadata(play.outputSchema, "rowOutputSchema");
10856
+ const rowOutputSchema = playSchemaMetadata(
10857
+ play.outputSchema,
10858
+ "rowOutputSchema"
10859
+ );
9354
10860
  const runCommand2 = playRunCommand(play, { csvInput });
9355
10861
  const cloneEditStarter = buildCloneEditStarter(play);
9356
10862
  return {
@@ -9500,7 +11006,7 @@ async function handlePlayDescribe(args) {
9500
11006
  const client = new DeeplineClient();
9501
11007
  await assertCanonicalNamedPlayReference(client, playName);
9502
11008
  const play = await client.describePlay(
9503
- parseReferencedPlayTarget(playName).playName,
11009
+ parseReferencedPlayTarget2(playName).playName,
9504
11010
  {
9505
11011
  compact: args.includes("--compact")
9506
11012
  }
@@ -9546,7 +11052,7 @@ async function handlePlayPublish(args) {
9546
11052
  }
9547
11053
  let graph;
9548
11054
  try {
9549
- graph = await collectBundledPlayGraph((0, import_node_path10.resolve)(playName));
11055
+ graph = await collectBundledPlayGraph((0, import_node_path11.resolve)(playName));
9550
11056
  await compileBundledPlayGraphManifests(client, graph);
9551
11057
  await publishImportedPlayDependencies(client, graph);
9552
11058
  } catch (error) {
@@ -9575,7 +11081,7 @@ async function handlePlayPublish(args) {
9575
11081
  );
9576
11082
  return 0;
9577
11083
  }
9578
- const resolvedName = parseReferencedPlayTarget(playName).playName;
11084
+ const resolvedName = parseReferencedPlayTarget2(playName).playName;
9579
11085
  if (useLatest) {
9580
11086
  const versions = await client.listPlayVersions(resolvedName);
9581
11087
  const latest = versions[0];
@@ -9615,17 +11121,19 @@ async function handlePlayDelete(args) {
9615
11121
  const client = new DeeplineClient();
9616
11122
  let detail;
9617
11123
  try {
9618
- detail = await client.getPlay(parseReferencedPlayTarget(playName).playName);
11124
+ detail = await client.getPlay(parseReferencedPlayTarget2(playName).playName);
9619
11125
  } catch (error) {
9620
11126
  console.error(error instanceof Error ? error.message : String(error));
9621
11127
  return 1;
9622
11128
  }
9623
11129
  if (detail.play.ownerType === "deepline" || detail.play.origin === "prebuilt") {
9624
- console.error(`Cannot delete prebuilt play: ${formatPlayReference(detail.play)}`);
11130
+ console.error(
11131
+ `Cannot delete prebuilt play: ${formatPlayReference(detail.play)}`
11132
+ );
9625
11133
  return 1;
9626
11134
  }
9627
11135
  const result = await client.deletePlay(
9628
- parseReferencedPlayTarget(formatPlayReference(detail.play)).playName
11136
+ parseReferencedPlayTarget2(formatPlayReference(detail.play)).playName
9629
11137
  );
9630
11138
  if (argsWantJson(args)) {
9631
11139
  process.stdout.write(`${JSON.stringify(result)}
@@ -9770,6 +11278,7 @@ Pass-through input flags:
9770
11278
  ...passthroughArgs
9771
11279
  ]);
9772
11280
  });
11281
+ registerPlayBootstrapCommand(play);
9773
11282
  play.command("get <target>").description("Fetch full play details.").addHelpText(
9774
11283
  "after",
9775
11284
  `
@@ -9784,7 +11293,10 @@ Examples:
9784
11293
  deepline plays get prebuilt/name-and-domain-to-email-waterfall-batch --source > email-waterfall.play.ts
9785
11294
  deepline plays get prebuilt/name-and-domain-to-email-waterfall-batch --source --out ./email-waterfall.play.ts
9786
11295
  `
9787
- ).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) => {
11296
+ ).option("--json", "Emit JSON output. Also automatic when stdout is piped").option(
11297
+ "--source",
11298
+ "Print raw source code; combine with --out to write a file"
11299
+ ).option("--out <path>", "Write source to a specific path").action(async (target, options) => {
9788
11300
  process.exitCode = await handlePlayGet([
9789
11301
  target,
9790
11302
  ...options.json ? ["--json"] : [],
@@ -9831,7 +11343,9 @@ Examples:
9831
11343
  ]);
9832
11344
  });
9833
11345
  addPlaySearchCommand(play.command("search <query>"));
9834
- play.command("grep <query>").description("Literal grep over play names, aliases, schemas, and descriptions.").addHelpText(
11346
+ play.command("grep <query>").description(
11347
+ "Literal grep over play names, aliases, schemas, and descriptions."
11348
+ ).addHelpText(
9835
11349
  "after",
9836
11350
  `
9837
11351
  Notes:
@@ -9917,7 +11431,9 @@ Examples:
9917
11431
  ]);
9918
11432
  });
9919
11433
  addPublishHelp(
9920
- play.command("set-live <target>").description("Promote a local file or saved revision as the live play revision.")
11434
+ play.command("set-live <target>").description(
11435
+ "Promote a local file or saved revision as the live play revision."
11436
+ )
9921
11437
  ).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) => {
9922
11438
  process.exitCode = await handlePlayPublish([
9923
11439
  target,
@@ -9962,7 +11478,9 @@ Examples:
9962
11478
  deepline runs export play/my-play/run/20260501t000000-000 --out output.csv
9963
11479
  `
9964
11480
  );
9965
- runs.command("get <runId>").description("Get status, progress, result, errors, and recovery metadata for a play run.").addHelpText(
11481
+ runs.command("get <runId>").description(
11482
+ "Get status, progress, result, errors, and recovery metadata for a play run."
11483
+ ).addHelpText(
9966
11484
  "after",
9967
11485
  `
9968
11486
  Notes:
@@ -10030,7 +11548,11 @@ Examples:
10030
11548
  deepline runs logs play/my-play/run/20260501t000000-000 --limit 500
10031
11549
  deepline runs logs play/my-play/run/20260501t000000-000 --out run.log --json
10032
11550
  `
10033
- ).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) => {
11551
+ ).option(
11552
+ "--limit <count>",
11553
+ "Maximum recent log lines to print without --out",
11554
+ "200"
11555
+ ).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) => {
10034
11556
  process.exitCode = await handleRunLogs([
10035
11557
  runId,
10036
11558
  ...options.limit ? ["--limit", options.limit] : [],
@@ -10071,7 +11593,10 @@ Examples:
10071
11593
  deepline runs export play/my-play/run/20260501t000000-000 --out output.csv --metadata-out output.meta.json
10072
11594
  deepline runs export play/my-play/run/20260501t000000-000 --out output.csv --json
10073
11595
  `
10074
- ).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) => {
11596
+ ).requiredOption("--out <path>", "Output CSV path").option(
11597
+ "--dataset <path>",
11598
+ "Returned dataset handle path, such as result.rows"
11599
+ ).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) => {
10075
11600
  process.exitCode = await handleRunExport([
10076
11601
  runId,
10077
11602
  ...options.dataset ? ["--dataset", options.dataset] : [],
@@ -10085,14 +11610,14 @@ Examples:
10085
11610
 
10086
11611
  // src/cli/commands/tools.ts
10087
11612
  var import_commander2 = require("commander");
10088
- var import_node_fs10 = require("fs");
11613
+ var import_node_fs11 = require("fs");
10089
11614
  var import_node_os7 = require("os");
10090
- var import_node_path12 = require("path");
11615
+ var import_node_path13 = require("path");
10091
11616
 
10092
11617
  // src/tool-output.ts
10093
- var import_node_fs9 = require("fs");
11618
+ var import_node_fs10 = require("fs");
10094
11619
  var import_node_os6 = require("os");
10095
- var import_node_path11 = require("path");
11620
+ var import_node_path12 = require("path");
10096
11621
  function isPlainObject(value) {
10097
11622
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
10098
11623
  }
@@ -10182,19 +11707,19 @@ function tryConvertToList(payload, options) {
10182
11707
  return null;
10183
11708
  }
10184
11709
  function ensureOutputDir() {
10185
- const outputDir = (0, import_node_path11.join)((0, import_node_os6.homedir)(), ".local", "share", "deepline", "data");
10186
- (0, import_node_fs9.mkdirSync)(outputDir, { recursive: true });
11710
+ const outputDir = (0, import_node_path12.join)((0, import_node_os6.homedir)(), ".local", "share", "deepline", "data");
11711
+ (0, import_node_fs10.mkdirSync)(outputDir, { recursive: true });
10187
11712
  return outputDir;
10188
11713
  }
10189
11714
  function writeJsonOutputFile(payload, stem) {
10190
11715
  const outputDir = ensureOutputDir();
10191
- const outputPath = (0, import_node_path11.join)(outputDir, `${stem}_${Date.now()}.json`);
10192
- (0, import_node_fs9.writeFileSync)(outputPath, JSON.stringify(payload, null, 2), "utf-8");
11716
+ const outputPath = (0, import_node_path12.join)(outputDir, `${stem}_${Date.now()}.json`);
11717
+ (0, import_node_fs10.writeFileSync)(outputPath, JSON.stringify(payload, null, 2), "utf-8");
10193
11718
  return outputPath;
10194
11719
  }
10195
11720
  function writeCsvOutputFile(rows, stem) {
10196
11721
  const outputDir = ensureOutputDir();
10197
- const outputPath = (0, import_node_path11.join)(outputDir, `${stem}_${Date.now()}.csv`);
11722
+ const outputPath = (0, import_node_path12.join)(outputDir, `${stem}_${Date.now()}.csv`);
10198
11723
  const seen = /* @__PURE__ */ new Set();
10199
11724
  const columns = [];
10200
11725
  for (const row of rows) {
@@ -10217,7 +11742,7 @@ function writeCsvOutputFile(rows, stem) {
10217
11742
  for (const row of rows) {
10218
11743
  lines.push(columns.map((column) => escapeCell(row[column])).join(","));
10219
11744
  }
10220
- (0, import_node_fs9.writeFileSync)(outputPath, `${lines.join("\n")}
11745
+ (0, import_node_fs10.writeFileSync)(outputPath, `${lines.join("\n")}
10221
11746
  `, "utf-8");
10222
11747
  const previewRows = rows.slice(0, 5);
10223
11748
  const previewColumns = columns.slice(0, 5);
@@ -10299,11 +11824,14 @@ async function listTools(args) {
10299
11824
  const client = new DeeplineClient();
10300
11825
  const categoryArgIndex = args.findIndex((arg) => arg === "--categories");
10301
11826
  const categoryFilter = categoryArgIndex >= 0 ? args[categoryArgIndex + 1] : "";
11827
+ const compact = args.includes("--compact");
10302
11828
  const requestedCategories = categoryFilter ? categoryFilter.split(",").map((item) => item.trim()).filter(Boolean) : [];
10303
11829
  const items = (await client.listTools({
10304
11830
  ...categoryFilter ? { categories: categoryFilter } : {}
10305
11831
  })).map(toListedTool).filter(
10306
- (item) => requestedCategories.length === 0 || requestedCategories.some((category) => item.categories.includes(category))
11832
+ (item) => requestedCategories.length === 0 || requestedCategories.some(
11833
+ (category) => item.categories.includes(category)
11834
+ )
10307
11835
  );
10308
11836
  const render = {
10309
11837
  sections: [
@@ -10323,10 +11851,11 @@ async function listTools(args) {
10323
11851
  }
10324
11852
  ]
10325
11853
  };
11854
+ const outputItems = compact ? items.map(compactTool) : items;
10326
11855
  printCommandEnvelope(
10327
11856
  {
10328
- tools: items,
10329
- count: items.length,
11857
+ tools: outputItems,
11858
+ count: outputItems.length,
10330
11859
  filters: {
10331
11860
  categories: requestedCategories
10332
11861
  },
@@ -10351,7 +11880,11 @@ async function searchTools(queryInput, options = {}) {
10351
11880
  searchMode: options.searchMode,
10352
11881
  includeSearchDebug: options.includeSearchDebug
10353
11882
  });
10354
- printCommandEnvelope(result, {
11883
+ const payload = options.compact && Array.isArray(result.tools) ? {
11884
+ ...result,
11885
+ tools: result.tools.map(compactTool)
11886
+ } : result;
11887
+ printCommandEnvelope(payload, {
10355
11888
  json: options.json || shouldEmitJson()
10356
11889
  });
10357
11890
  return 0;
@@ -10370,7 +11903,9 @@ async function grepTools(queryInput, options = {}) {
10370
11903
  grepMode: mode,
10371
11904
  ...options.categories ? { categories: options.categories } : {}
10372
11905
  })).map(toListedTool).filter(
10373
- (item) => requestedCategories.length === 0 || requestedCategories.some((category) => item.categories.includes(category))
11906
+ (item) => requestedCategories.length === 0 || requestedCategories.some(
11907
+ (category) => item.categories.includes(category)
11908
+ )
10374
11909
  ).filter(
10375
11910
  (item) => matchesGrepQuery(
10376
11911
  {
@@ -10388,10 +11923,11 @@ async function grepTools(queryInput, options = {}) {
10388
11923
  mode
10389
11924
  )
10390
11925
  );
11926
+ const outputTools = options.compact ? tools.map(compactTool) : tools;
10391
11927
  printCommandEnvelope(
10392
11928
  {
10393
- tools,
10394
- count: tools.length,
11929
+ tools: outputTools,
11930
+ count: outputTools.length,
10395
11931
  query,
10396
11932
  grep: {
10397
11933
  mode,
@@ -10406,6 +11942,19 @@ async function grepTools(queryInput, options = {}) {
10406
11942
  );
10407
11943
  return 0;
10408
11944
  }
11945
+ function compactTool(tool) {
11946
+ const listed = toListedTool(tool);
11947
+ return {
11948
+ id: listed.id,
11949
+ toolId: listed.toolId,
11950
+ provider: listed.provider,
11951
+ displayName: listed.displayName,
11952
+ description: listed.description,
11953
+ categories: listed.categories,
11954
+ type: listed.type,
11955
+ executeCommand: listed.executeCommand
11956
+ };
11957
+ }
10409
11958
  function playIdentifiers(play) {
10410
11959
  return [play.name, play.reference, ...play.aliases ?? []].filter((value) => Boolean(value?.trim())).map((value) => value.trim());
10411
11960
  }
@@ -10478,9 +12027,13 @@ Examples:
10478
12027
  deepline tools list --categories email_finder --json
10479
12028
  deepline tools search email --json
10480
12029
  `
10481
- ).option("--categories <categories>", "Comma-separated categories to filter inventory").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (options) => {
12030
+ ).option(
12031
+ "--categories <categories>",
12032
+ "Comma-separated categories to filter inventory"
12033
+ ).option("--compact", "Drop verbose fields from JSON output").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (options) => {
10482
12034
  process.exitCode = await listTools([
10483
12035
  ...options.categories ? ["--categories", options.categories] : [],
12036
+ ...options.compact ? ["--compact"] : [],
10484
12037
  ...options.json ? ["--json"] : []
10485
12038
  ]);
10486
12039
  });
@@ -10498,9 +12051,19 @@ Examples:
10498
12051
  deepline tools grep "company enrichment" --categories enrichment --json
10499
12052
  deepline tools search verifier --search-mode v2 --json
10500
12053
  `
10501
- ).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) => {
12054
+ ).option(
12055
+ "--categories <categories>",
12056
+ "Comma-separated categories to filter ranked search"
12057
+ ).option(
12058
+ "--search_terms <terms>",
12059
+ "Structured search terms for ranked search"
12060
+ ).option(
12061
+ "--search-terms <terms>",
12062
+ "Structured search terms for ranked search"
12063
+ ).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) => {
10502
12064
  process.exitCode = await searchTools(query, {
10503
12065
  json: options.json,
12066
+ compact: options.compact,
10504
12067
  categories: options.categories,
10505
12068
  searchTerms: options.searchTerms ?? options.search_terms,
10506
12069
  searchMode: options.searchMode === "v1" || options.searchMode === "v2" ? options.searchMode : void 0,
@@ -10508,7 +12071,9 @@ Examples:
10508
12071
  });
10509
12072
  });
10510
12073
  addToolSearchCommand(tools.command("search <query>"));
10511
- tools.command("grep <query>").description("Literal grep over tool ids, descriptions, categories, and input fields.").addHelpText(
12074
+ tools.command("grep <query>").description(
12075
+ "Literal grep over tool ids, descriptions, categories, and input fields."
12076
+ ).addHelpText(
10512
12077
  "after",
10513
12078
  `
10514
12079
  Notes:
@@ -10522,10 +12087,14 @@ Examples:
10522
12087
  deepline tools grep "phone validate" --mode all --json
10523
12088
  deepline tools grep hunter --mode phrase --json
10524
12089
  `
10525
- ).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) => {
12090
+ ).option(
12091
+ "--categories <categories>",
12092
+ "Comma-separated categories to filter inventory"
12093
+ ).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) => {
10526
12094
  const mode = options.mode === "any" || options.mode === "phrase" ? options.mode : "all";
10527
12095
  process.exitCode = await grepTools(query, {
10528
12096
  json: options.json,
12097
+ compact: options.compact,
10529
12098
  categories: options.categories,
10530
12099
  mode
10531
12100
  });
@@ -10546,7 +12115,20 @@ Examples:
10546
12115
  deepline tools describe hunter_email_verifier --json
10547
12116
  deepline tools execute hunter_email_verifier --input '{"email":"a@b.com"}'
10548
12117
  `
10549
- ).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 import_commander2.Option("--compact", "Compatibility alias for the default compact view").hideHelp()).addOption(new import_commander2.Option("--contract-json", "Compatibility alias for compact contract JSON").hideHelp()).action(async (toolId, options) => {
12118
+ ).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(
12119
+ "--examples-only",
12120
+ "Only print runnable examples and sample payloads"
12121
+ ).option("--getters-only", "Only print extracted list/value getters").addOption(
12122
+ new import_commander2.Option(
12123
+ "--compact",
12124
+ "Compatibility alias for the default compact view"
12125
+ ).hideHelp()
12126
+ ).addOption(
12127
+ new import_commander2.Option(
12128
+ "--contract-json",
12129
+ "Compatibility alias for compact contract JSON"
12130
+ ).hideHelp()
12131
+ ).action(async (toolId, options) => {
10550
12132
  process.exitCode = await getTool(toolId, {
10551
12133
  json: Boolean(options.json),
10552
12134
  compact: Boolean(options.compact),
@@ -10588,13 +12170,24 @@ Examples:
10588
12170
  deepline tools execute hunter_email_verifier -p email=a@b.com
10589
12171
  deepline tools execute test_rate_limit --input '{"key":"smoke"}' --json | jq '.status'
10590
12172
  `
10591
- ).option("-p, --param <key=value>", "Pass one parameter. Repeat for multiple values.", (value, acc) => {
10592
- acc.push(value);
10593
- return acc;
10594
- }, []).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(
12173
+ ).option(
12174
+ "-p, --param <key=value>",
12175
+ "Pass one parameter. Repeat for multiple values.",
12176
+ (value, acc) => {
12177
+ acc.push(value);
12178
+ return acc;
12179
+ },
12180
+ []
12181
+ ).option(
12182
+ "--json [payload]",
12183
+ "Emit JSON output. Use `--input` or `--payload` for passing JSON params."
12184
+ ).option("--input <payload>", "Merge a JSON object into the tool params").option("--payload <payload>", "Merge a JSON object into the tool params").option(
10595
12185
  "--output-format <format>",
10596
12186
  "Output format: auto, csv, csv_file, json, or json_file"
10597
- ).option("--no-preview", "Only print the extracted output path when applicable").action(async (toolId, options) => {
12187
+ ).option(
12188
+ "--no-preview",
12189
+ "Only print the extracted output path when applicable"
12190
+ ).action(async (toolId, options) => {
10598
12191
  const args = [
10599
12192
  toolId,
10600
12193
  ...options.param.flatMap((value) => ["--param", value]),
@@ -10626,14 +12219,18 @@ async function getTool(toolId, options = {}) {
10626
12219
  throw error;
10627
12220
  }
10628
12221
  if (options.contractJson) {
10629
- process.stdout.write(`${JSON.stringify(toolContractJsonForDescribe(tool, toolId))}
10630
- `);
12222
+ process.stdout.write(
12223
+ `${JSON.stringify(toolContractJsonForDescribe(tool, toolId))}
12224
+ `
12225
+ );
10631
12226
  return 0;
10632
12227
  }
10633
12228
  const emitJson = options.json === true;
10634
12229
  if (emitJson) {
10635
- process.stdout.write(`${JSON.stringify(toolMetadataJsonForDescribe(tool, toolId))}
10636
- `);
12230
+ process.stdout.write(
12231
+ `${JSON.stringify(toolMetadataJsonForDescribe(tool, toolId))}
12232
+ `
12233
+ );
10637
12234
  return 0;
10638
12235
  }
10639
12236
  const onlyModes = [
@@ -10643,7 +12240,9 @@ async function getTool(toolId, options = {}) {
10643
12240
  options.gettersOnly
10644
12241
  ].filter(Boolean).length;
10645
12242
  if (onlyModes > 1) {
10646
- console.error("Use only one of --pricing-only, --schema-only, --examples-only, or --getters-only.");
12243
+ console.error(
12244
+ "Use only one of --pricing-only, --schema-only, --examples-only, or --getters-only."
12245
+ );
10647
12246
  return 2;
10648
12247
  }
10649
12248
  if (options.pricingOnly) {
@@ -10667,8 +12266,10 @@ async function getTool(toolId, options = {}) {
10667
12266
  return 0;
10668
12267
  }
10669
12268
  if (shouldEmitJson()) {
10670
- process.stdout.write(`${JSON.stringify(toolMetadataJsonForDescribe(tool, toolId))}
10671
- `);
12269
+ process.stdout.write(
12270
+ `${JSON.stringify(toolMetadataJsonForDescribe(tool, toolId))}
12271
+ `
12272
+ );
10672
12273
  return 0;
10673
12274
  }
10674
12275
  printCompactToolContract(tool, toolId);
@@ -10676,9 +12277,15 @@ async function getTool(toolId, options = {}) {
10676
12277
  }
10677
12278
  function toolContractJsonForDescribe(tool, requestedToolId) {
10678
12279
  const toolId = String(tool.toolId || requestedToolId);
10679
- const inputFields = toolInputFieldsForDisplay(recordField(tool, "inputSchema", "input_schema"));
12280
+ const inputFields = toolInputFieldsForDisplay(
12281
+ recordField(tool, "inputSchema", "input_schema")
12282
+ );
10680
12283
  const usageGuidance = recordField(tool, "usageGuidance", "usage_guidance");
10681
- const toolExecutionResult = recordField(usageGuidance, "toolExecutionResult", "tool_execution_result");
12284
+ const toolExecutionResult = recordField(
12285
+ usageGuidance,
12286
+ "toolExecutionResult",
12287
+ "tool_execution_result"
12288
+ );
10682
12289
  const extractedLists = extractionContractEntries(
10683
12290
  arrayField(toolExecutionResult, "extractedLists", "extracted_lists")
10684
12291
  );
@@ -10731,7 +12338,7 @@ function toolContractJsonForDescribe(tool, requestedToolId) {
10731
12338
  }
10732
12339
  function extractionContractEntries(entries) {
10733
12340
  return entries.flatMap((entry) => {
10734
- if (!isRecord4(entry)) return [];
12341
+ if (!isRecord5(entry)) return [];
10735
12342
  const name = stringField(entry, "name");
10736
12343
  const expression = stringField(entry, "expression");
10737
12344
  return name && expression ? [{ name, expression }] : [];
@@ -10739,8 +12346,8 @@ function extractionContractEntries(entries) {
10739
12346
  }
10740
12347
  function printCompactToolContract(tool, requestedToolId) {
10741
12348
  const contract = toolContractJsonForDescribe(tool, requestedToolId);
10742
- const cost = isRecord4(contract.cost) ? contract.cost : {};
10743
- const getters = isRecord4(contract.getters) ? contract.getters : {};
12349
+ const cost = isRecord5(contract.cost) ? contract.cost : {};
12350
+ const getters = isRecord5(contract.getters) ? contract.getters : {};
10744
12351
  const listGetters = Array.isArray(getters.extractedLists) ? getters.extractedLists : [];
10745
12352
  const valueGetters = Array.isArray(getters.extractedValues) ? getters.extractedValues : [];
10746
12353
  const inputFields = Array.isArray(contract.inputFields) ? contract.inputFields : [];
@@ -10757,18 +12364,20 @@ function printCompactToolContract(tool, requestedToolId) {
10757
12364
  console.log("");
10758
12365
  console.log("Inputs:");
10759
12366
  for (const field of inputFields) {
10760
- if (!isRecord4(field)) continue;
12367
+ if (!isRecord5(field)) continue;
10761
12368
  const name = stringField(field, "name");
10762
12369
  if (!name) continue;
10763
12370
  const required = field.required ? "*" : "";
10764
12371
  const type = stringField(field, "type") || "unknown";
10765
12372
  const description = stringField(field, "description");
10766
- console.log(`- ${name}${required}: ${type}${description ? ` - ${description}` : ""}`);
12373
+ console.log(
12374
+ `- ${name}${required}: ${type}${description ? ` - ${description}` : ""}`
12375
+ );
10767
12376
  }
10768
12377
  }
10769
12378
  console.log("");
10770
12379
  printToolExamplesOnly(tool, requestedToolId, { includeSamples: false });
10771
- const starterScript = isRecord4(contract.starterScript) ? contract.starterScript : {};
12380
+ const starterScript = isRecord5(contract.starterScript) ? contract.starterScript : {};
10772
12381
  const starterPath = stringField(starterScript, "path");
10773
12382
  if (starterPath) {
10774
12383
  console.log("");
@@ -10780,19 +12389,27 @@ function printCompactToolContract(tool, requestedToolId) {
10780
12389
  console.log("Getters:");
10781
12390
  if (listGetters.length) console.log("Lists:");
10782
12391
  for (const entry of listGetters) {
10783
- if (isRecord4(entry)) console.log(`- ${stringField(entry, "name")}: ${playResultExpression(entry)}`);
12392
+ if (isRecord5(entry))
12393
+ console.log(
12394
+ `- ${stringField(entry, "name")}: ${playResultExpression(entry)}`
12395
+ );
10784
12396
  }
10785
12397
  if (valueGetters.length) console.log("Values:");
10786
12398
  for (const entry of valueGetters) {
10787
- if (isRecord4(entry)) console.log(`- ${stringField(entry, "name")}: ${playResultExpression(entry)}`);
12399
+ if (isRecord5(entry))
12400
+ console.log(
12401
+ `- ${stringField(entry, "name")}: ${playResultExpression(entry)}`
12402
+ );
10788
12403
  }
10789
12404
  }
10790
12405
  console.log("");
10791
- console.log(`More: deepline tools describe ${contract.toolId} --pricing-only | --schema-only | --examples-only | --getters-only | --json`);
12406
+ console.log(
12407
+ `More: deepline tools describe ${contract.toolId} --pricing-only | --schema-only | --examples-only | --getters-only | --json`
12408
+ );
10792
12409
  }
10793
12410
  function printToolPricingOnly(tool, requestedToolId, options = {}) {
10794
12411
  const contract = toolContractJsonForDescribe(tool, requestedToolId);
10795
- const cost = isRecord4(contract.cost) ? contract.cost : {};
12412
+ const cost = isRecord5(contract.cost) ? contract.cost : {};
10796
12413
  const pricingModel = stringField(cost, "pricingModel") || "unknown";
10797
12414
  const billingMode = stringField(cost, "billingMode") || "unknown";
10798
12415
  const unit = pricingModel === "per_page" ? "page" : pricingModel === "per_result" ? "result" : pricingModel === "fixed" ? "call" : pricingModel.replace(/^per_/, "") || "unit";
@@ -10812,14 +12429,16 @@ function printToolSchemaOnly(tool, requestedToolId) {
10812
12429
  }
10813
12430
  console.log("Inputs:");
10814
12431
  for (const field of inputFields) {
10815
- if (!isRecord4(field)) continue;
12432
+ if (!isRecord5(field)) continue;
10816
12433
  const name = stringField(field, "name");
10817
12434
  if (!name) continue;
10818
12435
  const required = field.required ? "*" : "";
10819
12436
  const type = stringField(field, "type") || "unknown";
10820
12437
  const description = stringField(field, "description");
10821
12438
  const defaultSuffix = Object.prototype.hasOwnProperty.call(field, "default") ? ` default=${JSON.stringify(field.default)}` : "";
10822
- console.log(`- ${name}${required}: ${type}${defaultSuffix}${description ? ` - ${description}` : ""}`);
12439
+ console.log(
12440
+ `- ${name}${required}: ${type}${defaultSuffix}${description ? ` - ${description}` : ""}`
12441
+ );
10823
12442
  }
10824
12443
  }
10825
12444
  function printToolExamplesOnly(tool, requestedToolId, options = {}) {
@@ -10832,16 +12451,21 @@ function printToolExamplesOnly(tool, requestedToolId, options = {}) {
10832
12451
  console.log("const result = await ctx.tools.execute({");
10833
12452
  console.log(` id: '${stableStepIdForTool(toolId)}',`);
10834
12453
  console.log(` tool: '${toolId}',`);
10835
- console.log(` input: ${JSON.stringify(sampleInput || {}, null, 2).replace(/\n/g, "\n ")},`);
12454
+ console.log(
12455
+ ` input: ${JSON.stringify(sampleInput || {}, null, 2).replace(/\n/g, "\n ")},`
12456
+ );
10836
12457
  console.log("});");
10837
- const getters = isRecord4(contract.getters) ? contract.getters : {};
12458
+ const getters = isRecord5(contract.getters) ? contract.getters : {};
10838
12459
  const valueGetters = Array.isArray(getters.extractedValues) ? getters.extractedValues : [];
10839
12460
  const listGetters = Array.isArray(getters.extractedLists) ? getters.extractedLists : [];
10840
- const firstGetter = [...valueGetters, ...listGetters].find(isRecord4);
12461
+ const firstGetter = [...valueGetters, ...listGetters].find(isRecord5);
10841
12462
  if (firstGetter) {
10842
12463
  const name = stringField(firstGetter, "name") || "value";
10843
12464
  const expression = stringField(firstGetter, "expression");
10844
- if (expression) console.log(`const ${safeIdentifier(name)} = ${expression.replace(/^toolExecutionResult\./, "result.")};`);
12465
+ if (expression)
12466
+ console.log(
12467
+ `const ${safeIdentifier2(name)} = ${expression.replace(/^toolExecutionResult\./, "result.")};`
12468
+ );
10845
12469
  }
10846
12470
  console.log("```");
10847
12471
  if (options.includeSamples !== false) {
@@ -10851,31 +12475,40 @@ function printToolExamplesOnly(tool, requestedToolId, options = {}) {
10851
12475
  }
10852
12476
  function printToolGettersOnly(tool, requestedToolId) {
10853
12477
  const contract = toolContractJsonForDescribe(tool, requestedToolId);
10854
- const getters = isRecord4(contract.getters) ? contract.getters : {};
12478
+ const getters = isRecord5(contract.getters) ? contract.getters : {};
10855
12479
  const listGetters = Array.isArray(getters.extractedLists) ? getters.extractedLists : [];
10856
12480
  const valueGetters = Array.isArray(getters.extractedValues) ? getters.extractedValues : [];
10857
12481
  console.log(`Getters: ${contract.toolId}`);
10858
12482
  if (!listGetters.length && !valueGetters.length) {
10859
- console.log("No generated getters declared. Use --json only if you need raw metadata.");
12483
+ console.log(
12484
+ "No generated getters declared. Use --json only if you need raw metadata."
12485
+ );
10860
12486
  return;
10861
12487
  }
10862
12488
  if (listGetters.length) {
10863
12489
  console.log("Lists:");
10864
12490
  for (const entry of listGetters) {
10865
- if (isRecord4(entry)) console.log(`- ${stringField(entry, "name")}: ${playResultExpression(entry)}`);
12491
+ if (isRecord5(entry))
12492
+ console.log(
12493
+ `- ${stringField(entry, "name")}: ${playResultExpression(entry)}`
12494
+ );
10866
12495
  }
10867
12496
  }
10868
12497
  if (valueGetters.length) {
10869
12498
  console.log("Values:");
10870
12499
  for (const entry of valueGetters) {
10871
- if (isRecord4(entry)) console.log(`- ${stringField(entry, "name")}: ${playResultExpression(entry)}`);
12500
+ if (isRecord5(entry))
12501
+ console.log(
12502
+ `- ${stringField(entry, "name")}: ${playResultExpression(entry)}`
12503
+ );
10872
12504
  }
10873
12505
  }
10874
12506
  }
10875
12507
  function sampleValueForField(field) {
10876
12508
  const name = stringField(field, "name").toLowerCase();
10877
12509
  const type = stringField(field, "type").toLowerCase();
10878
- if (Object.prototype.hasOwnProperty.call(field, "default")) return field.default;
12510
+ if (Object.prototype.hasOwnProperty.call(field, "default"))
12511
+ return field.default;
10879
12512
  if (name.includes("email")) return "ada@example.com";
10880
12513
  if (name.includes("domain") || name.includes("website")) return "example.com";
10881
12514
  if (name.includes("first")) return "Ada";
@@ -10890,7 +12523,7 @@ function sampleValueForField(field) {
10890
12523
  function samplePayloadForInputFields(fields) {
10891
12524
  return Object.fromEntries(
10892
12525
  fields.slice(0, 4).flatMap((field) => {
10893
- if (!isRecord4(field)) return [];
12526
+ if (!isRecord5(field)) return [];
10894
12527
  const name = stringField(field, "name");
10895
12528
  if (!name) return [];
10896
12529
  return [[name, sampleValueForField(field)]];
@@ -10900,12 +12533,15 @@ function samplePayloadForInputFields(fields) {
10900
12533
  function stableStepIdForTool(toolId) {
10901
12534
  return toolId.replace(/^[a-z0-9]+_/, "").replace(/[^a-z0-9_]+/gi, "_") || "tool_call";
10902
12535
  }
10903
- function safeIdentifier(name) {
12536
+ function safeIdentifier2(name) {
10904
12537
  const cleaned = name.replace(/[^a-zA-Z0-9_$]+/g, "_").replace(/^[^a-zA-Z_$]+/, "");
10905
12538
  return cleaned || "value";
10906
12539
  }
10907
12540
  function playResultExpression(entry) {
10908
- return stringField(entry, "expression").replace(/^toolExecutionResult\./, "result.");
12541
+ return stringField(entry, "expression").replace(
12542
+ /^toolExecutionResult\./,
12543
+ "result."
12544
+ );
10909
12545
  }
10910
12546
  function toolMetadataJsonForDescribe(tool, requestedToolId) {
10911
12547
  const toolId = String(tool.toolId || requestedToolId);
@@ -10996,12 +12632,13 @@ function formatListedToolCost(tool) {
10996
12632
  return displayText ? `Cost: ${displayText}` : "";
10997
12633
  }
10998
12634
  function toolInputFieldsForDisplay(inputSchema) {
10999
- if (Array.isArray(inputSchema.fields)) return inputSchema.fields.filter(isRecord4);
11000
- const jsonSchema = isRecord4(inputSchema.jsonSchema) ? inputSchema.jsonSchema : inputSchema;
11001
- const properties = isRecord4(jsonSchema.properties) ? jsonSchema.properties : {};
12635
+ if (Array.isArray(inputSchema.fields))
12636
+ return inputSchema.fields.filter(isRecord5);
12637
+ const jsonSchema = isRecord5(inputSchema.jsonSchema) ? inputSchema.jsonSchema : inputSchema;
12638
+ const properties = isRecord5(jsonSchema.properties) ? jsonSchema.properties : {};
11002
12639
  const required = Array.isArray(jsonSchema.required) ? new Set(jsonSchema.required.map(String)) : /* @__PURE__ */ new Set();
11003
12640
  return Object.entries(properties).map(([name, value]) => {
11004
- const property = isRecord4(value) ? value : {};
12641
+ const property = isRecord5(value) ? value : {};
11005
12642
  return {
11006
12643
  name,
11007
12644
  type: typeof property.type === "string" ? property.type : "unknown",
@@ -11016,8 +12653,10 @@ function printSamples(samples) {
11016
12653
  const responsePayload = samplePayload(samples, "response");
11017
12654
  if (requestPayload === void 0 && responsePayload === void 0) return;
11018
12655
  console.log(" Samples:");
11019
- if (requestPayload !== void 0) printJsonPreview("Example payload", requestPayload);
11020
- if (responsePayload !== void 0) printJsonPreview("Example response", responsePayload);
12656
+ if (requestPayload !== void 0)
12657
+ printJsonPreview("Example payload", requestPayload);
12658
+ if (responsePayload !== void 0)
12659
+ printJsonPreview("Example response", responsePayload);
11021
12660
  }
11022
12661
  function printJsonPreview(label, payload) {
11023
12662
  console.log(` ${label}:`);
@@ -11028,15 +12667,15 @@ function printJsonPreview(label, payload) {
11028
12667
  }
11029
12668
  function samplePayload(samples, key) {
11030
12669
  const entry = samples[key];
11031
- if (!isRecord4(entry)) return void 0;
12670
+ if (!isRecord5(entry)) return void 0;
11032
12671
  return Object.prototype.hasOwnProperty.call(entry, "payload") ? entry.payload : entry;
11033
12672
  }
11034
12673
  function commandEnvelopeFromRawResponse(rawResponse) {
11035
- return isRecord4(rawResponse) ? { ...rawResponse } : { status: "completed", result: rawResponse };
12674
+ return isRecord5(rawResponse) ? { ...rawResponse } : { status: "completed", result: rawResponse };
11036
12675
  }
11037
12676
  function listExtractorPathsFromUsageGuidance(tool) {
11038
12677
  const toolExecutionResult = tool.usageGuidance?.toolExecutionResult;
11039
- const extractedLists = Array.isArray(toolExecutionResult?.extractedLists) ? toolExecutionResult.extractedLists : isRecord4(toolExecutionResult?.extractedLists) ? Object.values(toolExecutionResult.extractedLists) : [];
12678
+ const extractedLists = Array.isArray(toolExecutionResult?.extractedLists) ? toolExecutionResult.extractedLists : isRecord5(toolExecutionResult?.extractedLists) ? Object.values(toolExecutionResult.extractedLists) : [];
11040
12679
  return extractedLists.flatMap((entry) => {
11041
12680
  const paths = entry.details?.candidatePaths ?? entry.details?.rawToolOutputPaths;
11042
12681
  if (!Array.isArray(paths)) return [];
@@ -11052,7 +12691,7 @@ function formatDecimal(value) {
11052
12691
  function formatUsd(value) {
11053
12692
  return `$${formatDecimal(value)}`;
11054
12693
  }
11055
- function isRecord4(value) {
12694
+ function isRecord5(value) {
11056
12695
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
11057
12696
  }
11058
12697
  function stringField(source, ...keys) {
@@ -11079,7 +12718,7 @@ function arrayField(source, ...keys) {
11079
12718
  function recordField(source, ...keys) {
11080
12719
  for (const key of keys) {
11081
12720
  const value = source[key];
11082
- if (isRecord4(value)) return value;
12721
+ if (isRecord5(value)) return value;
11083
12722
  }
11084
12723
  return {};
11085
12724
  }
@@ -11102,7 +12741,9 @@ function normalizeOutputFormat(raw) {
11102
12741
  function parseExecuteOptions(args) {
11103
12742
  const toolId = args[0];
11104
12743
  if (!toolId) {
11105
- 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]`);
12744
+ throw new Error(
12745
+ `Usage: deepline tools execute <toolId> [--param key=value ...] [--input '{"k":"v"}'] [--output-format auto|csv|csv_file|json|json_file] [--no-preview]`
12746
+ );
11106
12747
  }
11107
12748
  const params = {};
11108
12749
  let outputFormat = "auto";
@@ -11151,9 +12792,9 @@ function powerShellQuote(value) {
11151
12792
  function seedToolListScript(input) {
11152
12793
  const stem = safeFileStem(input.toolId);
11153
12794
  const fileName = `${stem}-workflow-seed-${Date.now()}.play.ts`;
11154
- const scriptDir = (0, import_node_fs10.mkdtempSync)((0, import_node_path12.join)((0, import_node_os7.tmpdir)(), "deepline-workflow-seed-"));
11155
- (0, import_node_fs10.chmodSync)(scriptDir, 448);
11156
- const scriptPath = (0, import_node_path12.join)(scriptDir, fileName);
12795
+ const scriptDir = (0, import_node_fs11.mkdtempSync)((0, import_node_path13.join)((0, import_node_os7.tmpdir)(), "deepline-workflow-seed-"));
12796
+ (0, import_node_fs11.chmodSync)(scriptDir, 448);
12797
+ const scriptPath = (0, import_node_path13.join)(scriptDir, fileName);
11157
12798
  const projectDir = `deepline/projects/${stem}-workflow`;
11158
12799
  const playName = `${stem}-workflow`;
11159
12800
  const sampleRows = input.rows.length > 0 ? `${JSON.stringify(input.rows.slice(0, 2)).replace(/\]$/, "")}, ...]` : "[]";
@@ -11189,7 +12830,7 @@ export default definePlay(${JSON.stringify(playName)}, async (ctx) => {
11189
12830
  };
11190
12831
  });
11191
12832
  `;
11192
- (0, import_node_fs10.writeFileSync)(scriptPath, script, { encoding: "utf-8", mode: 384 });
12833
+ (0, import_node_fs11.writeFileSync)(scriptPath, script, { encoding: "utf-8", mode: 384 });
11193
12834
  return {
11194
12835
  path: scriptPath,
11195
12836
  sourceCode: script,
@@ -11212,7 +12853,7 @@ function buildToolExecuteBaseEnvelope(input) {
11212
12853
  kind: summaryEntries.length > 0 ? "object" : "raw",
11213
12854
  summary: input.summary
11214
12855
  };
11215
- const envelopeHasCanonicalOutput = isRecord4(envelope.toolResponse) && Object.prototype.hasOwnProperty.call(envelope.toolResponse, "raw");
12856
+ const envelopeHasCanonicalOutput = isRecord5(envelope.toolResponse) && Object.prototype.hasOwnProperty.call(envelope.toolResponse, "raw");
11216
12857
  const inspectCommand = `deepline tools execute ${input.toolId} --input ${shellQuote(JSON.stringify(input.params))} --json`;
11217
12858
  const actions = input.listConversion ? [
11218
12859
  {
@@ -11246,7 +12887,9 @@ function buildToolExecuteBaseEnvelope(input) {
11246
12887
  ] : [
11247
12888
  {
11248
12889
  title: "result",
11249
- lines: summaryEntries.length > 0 ? summaryEntries.map(([key, value]) => `${key}=${String(value)}`) : [JSON.stringify(input.rawResponse, null, 2)]
12890
+ lines: summaryEntries.length > 0 ? summaryEntries.map(
12891
+ ([key, value]) => `${key}=${String(value)}`
12892
+ ) : [JSON.stringify(input.rawResponse, null, 2)]
11250
12893
  }
11251
12894
  ],
11252
12895
  actions
@@ -11273,7 +12916,9 @@ async function executeTool(args) {
11273
12916
  const play = await findPlayForToolId(client, parsed.toolId);
11274
12917
  if (play) {
11275
12918
  if (argsWantJson(args)) {
11276
- printJsonError(new Error(playAliasToolErrorMessage(parsed.toolId, play)));
12919
+ printJsonError(
12920
+ new Error(playAliasToolErrorMessage(parsed.toolId, play))
12921
+ );
11277
12922
  } else {
11278
12923
  printPlayAliasToolError(parsed.toolId, play);
11279
12924
  }
@@ -11309,12 +12954,15 @@ async function executeTool(args) {
11309
12954
  return 0;
11310
12955
  }
11311
12956
  if (parsed.outputFormat === "json_file") {
11312
- const jsonPath = writeJsonOutputFile(rawResponse, `payload_${parsed.toolId}`);
12957
+ const jsonPath = writeJsonOutputFile(
12958
+ rawResponse,
12959
+ `payload_${parsed.toolId}`
12960
+ );
11313
12961
  printCommandEnvelope(
11314
12962
  {
11315
12963
  ...baseEnvelope,
11316
12964
  local: {
11317
- ...isRecord4(baseEnvelope.local) ? baseEnvelope.local : {},
12965
+ ...isRecord5(baseEnvelope.local) ? baseEnvelope.local : {},
11318
12966
  payload_file: jsonPath
11319
12967
  }
11320
12968
  },
@@ -11324,7 +12972,10 @@ async function executeTool(args) {
11324
12972
  }
11325
12973
  if (!listConversion) {
11326
12974
  if (parsed.outputFormat === "csv" || parsed.outputFormat === "csv_file") {
11327
- const jsonPath = writeJsonOutputFile(rawResponse, `payload_${parsed.toolId}`);
12975
+ const jsonPath = writeJsonOutputFile(
12976
+ rawResponse,
12977
+ `payload_${parsed.toolId}`
12978
+ );
11328
12979
  printCommandEnvelope(
11329
12980
  {
11330
12981
  ...baseEnvelope,
@@ -11339,7 +12990,10 @@ async function executeTool(args) {
11339
12990
  printCommandEnvelope(baseEnvelope, { json: false });
11340
12991
  return 0;
11341
12992
  }
11342
- const csv = writeCsvOutputFile(listConversion.rows, `${parsed.toolId}_output`);
12993
+ const csv = writeCsvOutputFile(
12994
+ listConversion.rows,
12995
+ `${parsed.toolId}_output`
12996
+ );
11343
12997
  const seededScript = seedToolListScript({
11344
12998
  toolId: parsed.toolId,
11345
12999
  payload: parsed.params,
@@ -11365,7 +13019,9 @@ async function executeTool(args) {
11365
13019
  title: `${csv.path} (${csv.rowCount} rows)`,
11366
13020
  lines: [
11367
13021
  ...csv.columns.length > 0 ? [`columns: ${JSON.stringify(csv.columns)}`] : [],
11368
- ...Object.keys(summary).length > 0 ? [`summary: ${Object.entries(summary).map(([key, value]) => `${key}=${String(value)}`).join(", ")}`] : [],
13022
+ ...Object.keys(summary).length > 0 ? [
13023
+ `summary: ${Object.entries(summary).map(([key, value]) => `${key}=${String(value)}`).join(", ")}`
13024
+ ] : [],
11369
13025
  `preview: ${JSON.stringify(csv.preview)}`,
11370
13026
  `starter script: ${seededScript.path}`
11371
13027
  ]
@@ -11388,22 +13044,25 @@ async function executeTool(args) {
11388
13044
  }
11389
13045
  };
11390
13046
  if (parsed.outputFormat === "csv_file") {
11391
- printCommandEnvelope({
11392
- ...materializedEnvelope,
11393
- extracted_csv: csv.path,
11394
- extracted_csv_rows: csv.rowCount,
11395
- extracted_csv_columns: csv.columns,
11396
- preview: csv.preview,
11397
- list_strategy: listConversion.strategy,
11398
- list_source_path: listConversion.sourcePath,
11399
- starter_script: seededScript.path,
11400
- project_dir: seededScript.projectDir,
11401
- copy_to_project: {
11402
- macos_linux: seededScript.macCopyCommand,
11403
- windows_powershell: seededScript.windowsCopyCommand
13047
+ printCommandEnvelope(
13048
+ {
13049
+ ...materializedEnvelope,
13050
+ extracted_csv: csv.path,
13051
+ extracted_csv_rows: csv.rowCount,
13052
+ extracted_csv_columns: csv.columns,
13053
+ preview: csv.preview,
13054
+ list_strategy: listConversion.strategy,
13055
+ list_source_path: listConversion.sourcePath,
13056
+ starter_script: seededScript.path,
13057
+ project_dir: seededScript.projectDir,
13058
+ copy_to_project: {
13059
+ macos_linux: seededScript.macCopyCommand,
13060
+ windows_powershell: seededScript.windowsCopyCommand
13061
+ },
13062
+ summary
11404
13063
  },
11405
- summary
11406
- }, { json: true });
13064
+ { json: true }
13065
+ );
11407
13066
  return 0;
11408
13067
  }
11409
13068
  if (parsed.noPreview) {
@@ -11426,8 +13085,8 @@ async function executeTool(args) {
11426
13085
 
11427
13086
  // src/cli/commands/update.ts
11428
13087
  var import_node_child_process = require("child_process");
11429
- var import_node_fs11 = require("fs");
11430
- var import_node_path13 = require("path");
13088
+ var import_node_fs12 = require("fs");
13089
+ var import_node_path14 = require("path");
11431
13090
  function posixShellQuote(value) {
11432
13091
  return `'${value.replace(/'/g, `'\\''`)}'`;
11433
13092
  }
@@ -11446,19 +13105,19 @@ function buildSourceUpdateCommand(sourceRoot) {
11446
13105
  return `${cdCommand} && git fetch origin main --tags && git merge --ff-only origin/main`;
11447
13106
  }
11448
13107
  function findRepoBackedSdkRoot(startPath) {
11449
- let current = (0, import_node_path13.resolve)(startPath);
13108
+ let current = (0, import_node_path14.resolve)(startPath);
11450
13109
  while (true) {
11451
- if ((0, import_node_fs11.existsSync)((0, import_node_path13.join)(current, "sdk", "package.json")) && (0, import_node_fs11.existsSync)((0, import_node_path13.join)(current, "sdk", "bin", "deepline-dev.ts"))) {
13110
+ if ((0, import_node_fs12.existsSync)((0, import_node_path14.join)(current, "sdk", "package.json")) && (0, import_node_fs12.existsSync)((0, import_node_path14.join)(current, "sdk", "bin", "deepline-dev.ts"))) {
11452
13111
  return current;
11453
13112
  }
11454
- const parent = (0, import_node_path13.dirname)(current);
13113
+ const parent = (0, import_node_path14.dirname)(current);
11455
13114
  if (parent === current) return null;
11456
13115
  current = parent;
11457
13116
  }
11458
13117
  }
11459
13118
  function resolveUpdatePlan() {
11460
- const entrypoint = process.argv[1] ? (0, import_node_path13.resolve)(process.argv[1]) : "";
11461
- const sourceRoot = entrypoint ? findRepoBackedSdkRoot((0, import_node_path13.dirname)(entrypoint)) : null;
13119
+ const entrypoint = process.argv[1] ? (0, import_node_path14.resolve)(process.argv[1]) : "";
13120
+ const sourceRoot = entrypoint ? findRepoBackedSdkRoot((0, import_node_path14.dirname)(entrypoint)) : null;
11462
13121
  if (sourceRoot) {
11463
13122
  return {
11464
13123
  kind: "source",
@@ -11551,9 +13210,9 @@ Examples:
11551
13210
 
11552
13211
  // src/cli/skills-sync.ts
11553
13212
  var import_node_child_process2 = require("child_process");
11554
- var import_node_fs12 = require("fs");
13213
+ var import_node_fs13 = require("fs");
11555
13214
  var import_node_os8 = require("os");
11556
- var import_node_path14 = require("path");
13215
+ var import_node_path15 = require("path");
11557
13216
  var CHECK_TIMEOUT_MS2 = 3e3;
11558
13217
  var SDK_SKILL_NAME = "deepline-sdk";
11559
13218
  var SKILL_AGENTS = ["codex", "claude-code", "cursor"];
@@ -11564,28 +13223,28 @@ function shouldSkipSkillsSync() {
11564
13223
  }
11565
13224
  function sdkSkillsVersionPath(baseUrl) {
11566
13225
  const home = process.env.HOME?.trim() || (0, import_node_os8.homedir)();
11567
- return (0, import_node_path14.join)(home, ".local", "deepline", baseUrlSlug(baseUrl), "sdk-skills", ".version");
13226
+ return (0, import_node_path15.join)(home, ".local", "deepline", baseUrlSlug(baseUrl), "sdk-skills", ".version");
11568
13227
  }
11569
13228
  function readLocalSkillsVersion(baseUrl) {
11570
13229
  const path = sdkSkillsVersionPath(baseUrl);
11571
- if (!(0, import_node_fs12.existsSync)(path)) return "";
13230
+ if (!(0, import_node_fs13.existsSync)(path)) return "";
11572
13231
  try {
11573
- return (0, import_node_fs12.readFileSync)(path, "utf-8").trim();
13232
+ return (0, import_node_fs13.readFileSync)(path, "utf-8").trim();
11574
13233
  } catch {
11575
13234
  return "";
11576
13235
  }
11577
13236
  }
11578
13237
  function writeLocalSkillsVersion(baseUrl, version) {
11579
13238
  const path = sdkSkillsVersionPath(baseUrl);
11580
- (0, import_node_fs12.mkdirSync)((0, import_node_path14.dirname)(path), { recursive: true });
11581
- (0, import_node_fs12.writeFileSync)(path, `${version}
13239
+ (0, import_node_fs13.mkdirSync)((0, import_node_path15.dirname)(path), { recursive: true });
13240
+ (0, import_node_fs13.writeFileSync)(path, `${version}
11582
13241
  `, "utf-8");
11583
13242
  }
11584
13243
  function installedSdkSkillHasStalePositionalExecuteExamples() {
11585
13244
  const home = process.env.HOME?.trim() || (0, import_node_os8.homedir)();
11586
13245
  const roots = [
11587
- (0, import_node_path14.join)(home, ".claude", "skills", SDK_SKILL_NAME),
11588
- (0, import_node_path14.join)(home, ".agents", "skills", SDK_SKILL_NAME)
13246
+ (0, import_node_path15.join)(home, ".claude", "skills", SDK_SKILL_NAME),
13247
+ (0, import_node_path15.join)(home, ".agents", "skills", SDK_SKILL_NAME)
11589
13248
  ];
11590
13249
  const staleMarkers = [
11591
13250
  "ctx.tools.execute(key",
@@ -11595,22 +13254,22 @@ function installedSdkSkillHasStalePositionalExecuteExamples() {
11595
13254
  'rowCtx.tools.execute("'
11596
13255
  ];
11597
13256
  const scan = (dir) => {
11598
- for (const entry of (0, import_node_fs12.readdirSync)(dir)) {
11599
- const path = (0, import_node_path14.join)(dir, entry);
11600
- const stat3 = (0, import_node_fs12.statSync)(path);
13257
+ for (const entry of (0, import_node_fs13.readdirSync)(dir)) {
13258
+ const path = (0, import_node_path15.join)(dir, entry);
13259
+ const stat3 = (0, import_node_fs13.statSync)(path);
11601
13260
  if (stat3.isDirectory()) {
11602
13261
  if (scan(path)) return true;
11603
13262
  continue;
11604
13263
  }
11605
13264
  if (!entry.endsWith(".md")) continue;
11606
- const text = (0, import_node_fs12.readFileSync)(path, "utf-8");
13265
+ const text = (0, import_node_fs13.readFileSync)(path, "utf-8");
11607
13266
  if (staleMarkers.some((marker) => text.includes(marker))) return true;
11608
13267
  }
11609
13268
  return false;
11610
13269
  };
11611
13270
  for (const root of roots) {
11612
13271
  try {
11613
- if ((0, import_node_fs12.existsSync)(root) && scan(root)) return true;
13272
+ if ((0, import_node_fs13.existsSync)(root) && scan(root)) return true;
11614
13273
  } catch {
11615
13274
  continue;
11616
13275
  }
@@ -11708,7 +13367,7 @@ function resolveSkillsInstallCommands(baseUrl) {
11708
13367
  return [npxInstall];
11709
13368
  }
11710
13369
  function runOneSkillsInstall(install) {
11711
- return new Promise((resolve11) => {
13370
+ return new Promise((resolve12) => {
11712
13371
  const child = (0, import_node_child_process2.spawn)(install.command, install.args, {
11713
13372
  stdio: ["ignore", "ignore", "pipe"],
11714
13373
  env: process.env
@@ -11718,7 +13377,7 @@ function runOneSkillsInstall(install) {
11718
13377
  stderr += chunk.toString("utf-8");
11719
13378
  });
11720
13379
  child.on("error", (error) => {
11721
- resolve11({
13380
+ resolve12({
11722
13381
  ok: false,
11723
13382
  detail: `failed to start ${install.command}: ${error.message}`,
11724
13383
  manualCommand: install.manualCommand
@@ -11726,11 +13385,11 @@ function runOneSkillsInstall(install) {
11726
13385
  });
11727
13386
  child.on("close", (code) => {
11728
13387
  if (code === 0) {
11729
- resolve11({ ok: true, detail: "", manualCommand: install.manualCommand });
13388
+ resolve12({ ok: true, detail: "", manualCommand: install.manualCommand });
11730
13389
  return;
11731
13390
  }
11732
13391
  const detail = stderr.trim();
11733
- resolve11({
13392
+ resolve12({
11734
13393
  ok: false,
11735
13394
  detail: detail ? `${install.command}: ${detail}` : `${install.command} exited ${code}`,
11736
13395
  manualCommand: install.manualCommand
@@ -11806,8 +13465,8 @@ function shouldDeferSkillsSyncForCommand() {
11806
13465
  return (command === "play" || command === "plays") && subcommand === "run" && args.includes("--json");
11807
13466
  }
11808
13467
  async function runPlayRunnerHealthCheck() {
11809
- const dir = await (0, import_promises5.mkdtemp)((0, import_node_path15.join)((0, import_node_os9.tmpdir)(), "deepline-health-play-"));
11810
- const file = (0, import_node_path15.join)(dir, "health-check.play.ts");
13468
+ const dir = await (0, import_promises5.mkdtemp)((0, import_node_path16.join)((0, import_node_os9.tmpdir)(), "deepline-health-play-"));
13469
+ const file = (0, import_node_path16.join)(dir, "health-check.play.ts");
11811
13470
  try {
11812
13471
  await (0, import_promises5.writeFile)(
11813
13472
  file,