deepline 0.3.352 → 0.3.353

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.
Files changed (118) hide show
  1. package/dist/bundling-sources/sdk/src/gtm.ts +1 -1
  2. package/dist/bundling-sources/sdk/src/index.ts +1 -20
  3. package/dist/bundling-sources/sdk/src/release.ts +1 -1
  4. package/dist/bundling-sources/sdk/src/types.ts +2 -14
  5. package/dist/bundling-sources/shared_libs/integration-contracts/monitor-input-contract.ts +1 -1
  6. package/dist/bundling-sources/shared_libs/plays/tool-categories.ts +19 -0
  7. package/dist/bundling-sources/shared_libs/plays/tool-category-descriptions.ts +1 -1
  8. package/dist/cli/{auth-6ZAHOPUC.mjs → auth-FVIZVTCB.mjs} +4 -4
  9. package/dist/cli/auth-GJZ3S4QH.js +31 -0
  10. package/dist/cli/{billing-FTCAIIPO.js → billing-NWL7KQPZ.js} +73 -73
  11. package/dist/cli/{billing-KE6CAAO5.mjs → billing-PYTYGWPG.mjs} +4 -4
  12. package/dist/cli/{chunk-SM4G43FY.js → chunk-2UWRFDI4.js} +60 -60
  13. package/dist/cli/{chunk-YIO2PX4J.mjs → chunk-37F4EUJA.mjs} +161 -1848
  14. package/dist/cli/{chunk-5TQPSUU6.js → chunk-55XOA2VW.js} +8 -8
  15. package/dist/cli/{chunk-54IUI747.mjs → chunk-BVHUTDCW.mjs} +5 -5
  16. package/dist/cli/{chunk-J5NA2TTX.js → chunk-C374C22Y.js} +2 -2
  17. package/dist/cli/{chunk-SGFPTY4H.mjs → chunk-CQQ5N4YO.mjs} +2 -2
  18. package/dist/cli/{chunk-J5MZZVDK.mjs → chunk-CXMSK2VV.mjs} +2 -2
  19. package/dist/cli/{chunk-XK7AH232.mjs → chunk-D477W2OQ.mjs} +4 -4
  20. package/dist/cli/{chunk-HD2RKIVK.mjs → chunk-DY253DRK.mjs} +2 -2
  21. package/dist/cli/{chunk-27JIZEAJ.js → chunk-EDEO7NG4.js} +1 -1
  22. package/dist/cli/{chunk-GVESPYSY.mjs → chunk-ERFN2QY4.mjs} +1 -102
  23. package/dist/cli/{chunk-LVEDPCLJ.js → chunk-GEJDBXXM.js} +1 -102
  24. package/dist/cli/{chunk-HMN5SUFL.mjs → chunk-GFLHAA2O.mjs} +1 -1
  25. package/dist/cli/{chunk-2PQR43BD.js → chunk-HU4SUDWU.js} +567 -2254
  26. package/dist/cli/{chunk-WOHBA5PV.js → chunk-IF75RD6U.js} +1 -1
  27. package/dist/cli/{chunk-NNMGGD5Z.mjs → chunk-IVGFLYQ6.mjs} +1 -1
  28. package/dist/cli/{chunk-Q3CSXWFU.js → chunk-JHPVZR6F.js} +4 -4
  29. package/dist/cli/{chunk-2ULH52Q7.mjs → chunk-LLI4RITH.mjs} +3 -3
  30. package/dist/cli/{chunk-QOIXZWOE.js → chunk-M4UPRX3M.js} +8 -8
  31. package/dist/cli/{chunk-TAC3JIFE.mjs → chunk-MI6ZP7XI.mjs} +1 -1
  32. package/dist/cli/{chunk-P6CGAEDF.js → chunk-NFEQHNDQ.js} +26 -26
  33. package/dist/cli/{chunk-4W3B4CNE.js → chunk-NPU4SMKT.js} +9 -9
  34. package/dist/cli/{chunk-OWG4Y7JK.mjs → chunk-NZNUDZDW.mjs} +2 -2
  35. package/dist/cli/{chunk-V5JPRCQ2.js → chunk-R2T4HQ64.js} +6 -6
  36. package/dist/cli/{chunk-HUZXWOSK.mjs → chunk-R4RG4FV5.mjs} +1 -1
  37. package/dist/cli/{chunk-EHYJYOXF.mjs → chunk-RRDCBCRI.mjs} +1 -1
  38. package/dist/cli/{chunk-3EIK6KTE.mjs → chunk-U3FUXTIB.mjs} +1 -1
  39. package/dist/cli/{chunk-VQFBIGMU.js → chunk-VALAAQQM.js} +48 -48
  40. package/dist/cli/{chunk-2JXDY3LE.js → chunk-XI5IMY45.js} +2 -2
  41. package/dist/cli/{chunk-VLQPMYSU.js → chunk-Z6LVVOOJ.js} +15 -15
  42. package/dist/cli/{chunk-L6BHFEYM.js → chunk-ZCCXX55K.js} +45 -45
  43. package/dist/cli/{chunk-ULX7APDZ.mjs → chunk-ZDEO3EGW.mjs} +1 -1
  44. package/dist/cli/{client-25RBAXIY.mjs → client-IH7I5D7T.mjs} +3 -3
  45. package/dist/cli/client-Z6BCEGFA.js +20 -0
  46. package/dist/cli/{csv-7BOK5ZD7.mjs → csv-G5WXNCLQ.mjs} +3 -3
  47. package/dist/cli/{csv-7XXJZ736.js → csv-TJIWKUCX.js} +12 -12
  48. package/dist/cli/{db-TFPYJCZ5.js → db-3DCS2JXS.js} +29 -29
  49. package/dist/cli/{db-7Q7L5SKP.mjs → db-EBHV2MGE.mjs} +4 -4
  50. package/dist/cli/{describe-TQYXSFZ2.js → describe-5XKBPWD7.js} +16 -16
  51. package/dist/cli/{describe-JTEJNG67.mjs → describe-QUOLGZKH.mjs} +9 -9
  52. package/dist/cli/{executions-33MNWCXR.mjs → executions-EERWIJ5I.mjs} +4 -4
  53. package/dist/cli/{executions-XYCJEW5I.js → executions-NYIOENKH.js} +6 -6
  54. package/dist/cli/{feedback-LXSEEBNL.mjs → feedback-4RYJJCYL.mjs} +3 -3
  55. package/dist/cli/{feedback-D3RSQCQE.js → feedback-Z2I5MQYZ.js} +7 -7
  56. package/dist/cli/{git-IES2ZBYO.mjs → git-EMU7AKX3.mjs} +4 -4
  57. package/dist/cli/git-QYQ5ZFIG.js +23 -0
  58. package/dist/cli/index.js +79 -79
  59. package/dist/cli/index.mjs +31 -31
  60. package/dist/cli/{legacy-noops-YIOGLZXX.js → legacy-noops-BEUYYRSU.js} +7 -7
  61. package/dist/cli/{legacy-noops-ILCWGUAR.mjs → legacy-noops-HHLNM523.mjs} +4 -4
  62. package/dist/cli/{monitors-R3CZHVU2.mjs → monitors-BVJSHUV4.mjs} +7 -7
  63. package/dist/cli/{monitors-MQSSH43U.js → monitors-KQXLMPZ4.js} +96 -96
  64. package/dist/cli/{org-62P7YRHW.js → org-HRYNVOUH.js} +60 -60
  65. package/dist/cli/{org-Z75A63SM.mjs → org-KSROOKSJ.mjs} +4 -4
  66. package/dist/cli/play-CRHUA45Q.js +153 -0
  67. package/dist/cli/{play-FUUFAV34.mjs → play-PGFW6PFE.mjs} +8 -8
  68. package/dist/cli/{providers-Q2VZF65A.js → providers-BJM725CV.js} +7 -7
  69. package/dist/cli/{providers-OQNPHTKA.mjs → providers-EUKJK6ZE.mjs} +4 -4
  70. package/dist/cli/{quickstart-7X6HUVWX.mjs → quickstart-72JYHUJC.mjs} +3 -3
  71. package/dist/cli/{quickstart-VZ7BYW4Y.js → quickstart-FEERYTYY.js} +5 -5
  72. package/dist/cli/{search-SJKLKSER.mjs → search-LUAIOM56.mjs} +5 -5
  73. package/dist/cli/search-X25S2U54.js +26 -0
  74. package/dist/cli/{secrets-EKH3FPAO.js → secrets-J65QCH57.js} +13 -13
  75. package/dist/cli/{secrets-JQUKCHON.mjs → secrets-YYFRYS2Z.mjs} +4 -4
  76. package/dist/cli/{sessions-NDLKL26C.js → sessions-FWUUEK6V.js} +5 -5
  77. package/dist/cli/{sessions-RSFW7OYD.mjs → sessions-WBA67YYT.mjs} +4 -4
  78. package/dist/cli/{settings-HPUE5C2G.js → settings-I7AZ4JVI.js} +74 -74
  79. package/dist/cli/{settings-DR4YKJTJ.mjs → settings-RUMTSUE5.mjs} +7 -7
  80. package/dist/cli/{setup-4FT6NMU6.mjs → setup-BHRRNT5C.mjs} +6 -6
  81. package/dist/cli/{setup-Y2HCWQ4D.js → setup-R3IUFNDP.js} +41 -41
  82. package/dist/cli/{skills-EQR5K67V.mjs → skills-EKD5O7GQ.mjs} +4 -4
  83. package/dist/cli/skills-OOZ5SDVB.js +28 -0
  84. package/dist/cli/{tools-ZRCNCMOO.mjs → tools-L5OA2343.mjs} +6 -6
  85. package/dist/cli/tools-MYH33NTL.js +40 -0
  86. package/dist/cli/update-EWNPE3NF.js +28 -0
  87. package/dist/cli/{update-UJNIMTRS.mjs → update-UUHL6FER.mjs} +6 -6
  88. package/dist/cli/{workflow-4M63OBSC.js → workflow-7NBSG5OT.js} +15 -15
  89. package/dist/cli/{workflow-EN3TQFKU.mjs → workflow-V24VHOQT.mjs} +5 -5
  90. package/dist/{client-4DbE-U6e.d.ts → client-Chzd2LFo.d.ts} +1 -25
  91. package/dist/{client-DIJpwhl-.d.mts → client-jV6bQunU.d.mts} +1 -25
  92. package/dist/helpers.d.mts +1 -1
  93. package/dist/helpers.d.ts +1 -1
  94. package/dist/index.d.mts +2 -2
  95. package/dist/index.d.ts +2 -2
  96. package/dist/index.js +25 -39
  97. package/dist/index.mjs +23 -37
  98. package/dist/install-integrity.json +83 -83
  99. package/dist/monitor-fleet-contract.js +3 -3
  100. package/dist/monitor-fleet-contract.mjs +2 -2
  101. package/dist/monitor-input-contract.js +2 -2
  102. package/dist/monitor-input-contract.mjs +1 -1
  103. package/dist/plays/run-request.d.mts +1 -1
  104. package/dist/plays/run-request.d.ts +1 -1
  105. package/dist/release.d.mts +1 -1
  106. package/dist/release.d.ts +1 -1
  107. package/dist/release.js +2 -2
  108. package/dist/release.mjs +1 -1
  109. package/package.json +1 -1
  110. package/dist/bundling-sources/shared_libs/plays/bootstrap-routes.ts +0 -127
  111. package/dist/cli/auth-ZYLA55Y2.js +0 -31
  112. package/dist/cli/client-AY2RSEDD.js +0 -20
  113. package/dist/cli/git-56MVO4Y5.js +0 -23
  114. package/dist/cli/play-K4RS3VMC.js +0 -153
  115. package/dist/cli/search-H3TNOWKP.js +0 -26
  116. package/dist/cli/skills-OGQZAKOB.js +0 -28
  117. package/dist/cli/tools-3HM7A7XQ.js +0 -40
  118. package/dist/cli/update-ZB6CXLCS.js +0 -28
@@ -11,21 +11,15 @@ import {
11
11
  } from "./chunk-EDWJY6T4.mjs";
12
12
  import {
13
13
  registerDeprecatedSearchCommand
14
- } from "./chunk-2ULH52Q7.mjs";
14
+ } from "./chunk-LLI4RITH.mjs";
15
15
  import {
16
16
  handleDeploymentGet,
17
17
  handleDeploymentsList
18
- } from "./chunk-HD2RKIVK.mjs";
18
+ } from "./chunk-DY253DRK.mjs";
19
19
  import {
20
- PLAY_BOOTSTRAP_COMPANY_PROVIDER_CATEGORY,
21
- PLAY_BOOTSTRAP_OUTPUT_FIELD_BY_FINDER,
22
- PLAY_BOOTSTRAP_PEOPLE_PROVIDER_CATEGORY,
23
- PLAY_BOOTSTRAP_PROVIDER_CATEGORY_BY_FINDER,
24
- formatPlayBootstrapTemplates,
25
- isPlayBootstrapTemplate,
26
20
  pinLocalPlayImports,
27
21
  planLocalPlayExecution
28
- } from "./chunk-GVESPYSY.mjs";
22
+ } from "./chunk-ERFN2QY4.mjs";
29
23
  import {
30
24
  CSV_HEADER_MATCHING_NOTE,
31
25
  DeeplineClient,
@@ -40,7 +34,7 @@ import {
40
34
  normalizeRunEventOperationRequest,
41
35
  parseLogLevel,
42
36
  playInputExampleArgs
43
- } from "./chunk-NNMGGD5Z.mjs";
37
+ } from "./chunk-IVGFLYQ6.mjs";
44
38
  import {
45
39
  CSV_DATA_INPUT_KEY,
46
40
  buildNamedPlayRunRequest,
@@ -73,10 +67,10 @@ import {
73
67
  printJsonError,
74
68
  renderCommandEnvelopeText,
75
69
  shouldEmitJson
76
- } from "./chunk-ULX7APDZ.mjs";
70
+ } from "./chunk-ZDEO3EGW.mjs";
77
71
  import {
78
72
  fetchWithDeploymentProtection
79
- } from "./chunk-3EIK6KTE.mjs";
73
+ } from "./chunk-U3FUXTIB.mjs";
80
74
  import {
81
75
  PLAY_DEFAULT_EXPORT,
82
76
  extractDefinedPlayName,
@@ -3971,8 +3965,8 @@ import {
3971
3965
  readFileSync as readFileSync2,
3972
3966
  readdirSync,
3973
3967
  realpathSync,
3974
- statSync as statSync2,
3975
- writeFileSync as writeFileSync4
3968
+ statSync,
3969
+ writeFileSync as writeFileSync3
3976
3970
  } from "fs";
3977
3971
  import {
3978
3972
  lstat,
@@ -3985,1693 +3979,13 @@ import {
3985
3979
  import {
3986
3980
  basename,
3987
3981
  dirname as dirname2,
3988
- isAbsolute as isAbsolute3,
3982
+ isAbsolute as isAbsolute2,
3989
3983
  join as join6,
3990
- relative as relative4,
3991
- resolve as resolve6
3984
+ relative as relative3,
3985
+ resolve as resolve5
3992
3986
  } from "path";
3993
3987
  import { Option as Option2 } from "commander";
3994
3988
 
3995
- // src/cli/commands/plays/bootstrap.ts
3996
- import {
3997
- closeSync,
3998
- openSync,
3999
- readSync,
4000
- statSync,
4001
- writeFileSync
4002
- } from "fs";
4003
- import { isAbsolute, relative, resolve } from "path";
4004
- import { parse as parseCsvSync } from "csv-parse/sync";
4005
- function parseReferencedPlayTarget(target) {
4006
- const trimmed = target.trim();
4007
- const slashIndex = trimmed.indexOf("/");
4008
- if (slashIndex <= 0 || slashIndex === trimmed.length - 1) {
4009
- return { ownerSlug: null, playName: trimmed, unqualifiedPlayName: trimmed };
4010
- }
4011
- return {
4012
- ownerSlug: trimmed.slice(0, slashIndex),
4013
- playName: trimmed,
4014
- unqualifiedPlayName: trimmed.slice(slashIndex + 1)
4015
- };
4016
- }
4017
- function parsePositiveInteger(value, flagName) {
4018
- const parsed = Number.parseInt(value, 10);
4019
- if (!Number.isFinite(parsed) || parsed <= 0) {
4020
- throw new PlayBootstrapUsageError(
4021
- `${flagName} must be a positive integer.`
4022
- );
4023
- }
4024
- return parsed;
4025
- }
4026
- function isRecord(value) {
4027
- return Boolean(value && typeof value === "object" && !Array.isArray(value));
4028
- }
4029
- function stringValue(value) {
4030
- return typeof value === "string" ? value.trim() : "";
4031
- }
4032
- function extractionEntries(value) {
4033
- if (Array.isArray(value)) return value.filter(isRecord);
4034
- if (!isRecord(value)) return [];
4035
- return Object.entries(value).map(
4036
- ([name, entry]) => isRecord(entry) ? { name, ...entry } : { name }
4037
- );
4038
- }
4039
- var PlayBootstrapError = class extends Error {
4040
- constructor(message, exitCode) {
4041
- super(message);
4042
- this.exitCode = exitCode;
4043
- }
4044
- };
4045
- var PlayBootstrapUsageError = class extends PlayBootstrapError {
4046
- constructor(message) {
4047
- super(message, 2);
4048
- }
4049
- };
4050
- var PlayBootstrapValidationError = class extends PlayBootstrapError {
4051
- constructor(message) {
4052
- super(message, 7);
4053
- }
4054
- };
4055
- var CSV_HEADER_SAMPLE_BYTES = 64 * 1024;
4056
- function parseCsvList(value) {
4057
- return value.split(",").map((item) => item.trim()).filter(Boolean);
4058
- }
4059
- function parseProviderList(value, flag) {
4060
- const providers = parseCsvList(value);
4061
- if (providers.length === 0) {
4062
- throw new PlayBootstrapUsageError(`${flag} provider list cannot be empty.`);
4063
- }
4064
- return providers;
4065
- }
4066
- function parseBootstrapPrefixedRef(value, flag) {
4067
- const separatorIndex = value.indexOf(":");
4068
- if (separatorIndex <= 0 || separatorIndex === value.length - 1) {
4069
- throw new PlayBootstrapUsageError(
4070
- `${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.`
4071
- );
4072
- }
4073
- return {
4074
- prefix: value.slice(0, separatorIndex).trim(),
4075
- body: value.slice(separatorIndex + 1).trim()
4076
- };
4077
- }
4078
- function parseBootstrapSourceRef(value, flag = "--from") {
4079
- const { prefix, body } = parseBootstrapPrefixedRef(value, flag);
4080
- switch (prefix) {
4081
- case "csv":
4082
- return { kind: "csv", value: body };
4083
- case "play":
4084
- return { kind: "play", value: parseReferencedPlayTarget(body).playName };
4085
- case "provider":
4086
- case "providers":
4087
- return { kind: "providers", values: parseProviderList(body, flag) };
4088
- }
4089
- throw new PlayBootstrapUsageError(
4090
- `${flag} does not support ${prefix}:. Use csv:, play:, provider:, or providers:.`
4091
- );
4092
- }
4093
- function parseBootstrapStageRef(value, flag) {
4094
- const { prefix, body } = parseBootstrapPrefixedRef(value, flag);
4095
- switch (prefix) {
4096
- case "play":
4097
- return { kind: "play", value: parseReferencedPlayTarget(body).playName };
4098
- case "provider":
4099
- case "providers":
4100
- return { kind: "providers", values: parseProviderList(body, flag) };
4101
- }
4102
- throw new PlayBootstrapUsageError(
4103
- `${flag} does not support ${prefix}:. Use play:, provider:, or providers:.`
4104
- );
4105
- }
4106
- function playBootstrapTemplateConfig(template) {
4107
- switch (template) {
4108
- case "company-list":
4109
- return { sourceEntity: "company", usingStage: null, requiredStages: [] };
4110
- case "people-list":
4111
- return { sourceEntity: "people", usingStage: null, requiredStages: [] };
4112
- case "people-email":
4113
- return {
4114
- sourceEntity: "people",
4115
- usingStage: "email",
4116
- requiredStages: []
4117
- };
4118
- case "people-phone":
4119
- return {
4120
- sourceEntity: "people",
4121
- usingStage: "phone",
4122
- requiredStages: []
4123
- };
4124
- case "company-people":
4125
- return {
4126
- sourceEntity: "company",
4127
- usingStage: "people",
4128
- requiredStages: []
4129
- };
4130
- case "company-people-email":
4131
- return {
4132
- sourceEntity: "company",
4133
- usingStage: null,
4134
- requiredStages: ["people", "email"]
4135
- };
4136
- case "company-people-phone":
4137
- return {
4138
- sourceEntity: "company",
4139
- usingStage: null,
4140
- requiredStages: ["people", "phone"]
4141
- };
4142
- }
4143
- }
4144
- function templateExample(template) {
4145
- switch (template) {
4146
- case "people-list":
4147
- return "deepline plays bootstrap people-list --from provider:dropleads_search_people --out people.play.ts";
4148
- case "company-list":
4149
- return "deepline plays bootstrap company-list --from provider:crustdata_companydb_search --out companies.play.ts";
4150
- case "people-email":
4151
- return "deepline plays bootstrap people-email --from csv:data/leads.csv --using play:prebuilt/name-and-domain-to-email-waterfall --out email-flow.play.ts";
4152
- case "people-phone":
4153
- return "deepline plays bootstrap people-phone --from csv:data/vp_contacts.csv --using play:prebuilt/person-to-phone --out phone-flow.play.ts";
4154
- case "company-people":
4155
- return "deepline plays bootstrap company-people --from provider:crustdata_companydb_search --using play:prebuilt/company-to-contact --out company-people.play.ts";
4156
- case "company-people-email":
4157
- return "deepline plays bootstrap company-people-email --from provider:crustdata_companydb_search --people play:prebuilt/company-to-contact --email providers:hunter_email_finder,leadmagic_email_finder --out account-emails.play.ts";
4158
- case "company-people-phone":
4159
- return "deepline plays bootstrap company-people-phone --from provider:crustdata_companydb_search --people play:prebuilt/company-to-contact --phone providers:ai_ark_mobile_phone_finder --out account-phones.play.ts";
4160
- }
4161
- }
4162
- var PLAY_BOOTSTRAP_STAGE_NAMES = [
4163
- "people",
4164
- "email",
4165
- "phone"
4166
- ];
4167
- var MONITOR_BOOTSTRAP_TEMPLATE = "monitor-triggered";
4168
- var MONITOR_BOOTSTRAP_DEFAULT_TOOL = "deepline_native.company_radar";
4169
- var MONITOR_BOOTSTRAP_DEFAULT_STREAM = "company_job_openings";
4170
- function isMonitorBootstrapTemplate(value) {
4171
- return value === MONITOR_BOOTSTRAP_TEMPLATE;
4172
- }
4173
- function hasMonitorBootstrapForbiddenChar(value) {
4174
- for (const char of value) {
4175
- const code = char.codePointAt(0) ?? 0;
4176
- if (code < 32 || code === 127) return true;
4177
- if (char === "'" || char === '"' || char === "`" || char === "\\") {
4178
- return true;
4179
- }
4180
- }
4181
- return false;
4182
- }
4183
- function validateMonitorBootstrapFlagValue(flag, value) {
4184
- if (hasMonitorBootstrapForbiddenChar(value)) {
4185
- throw new PlayBootstrapUsageError(
4186
- `${flag} may not contain line breaks, control characters, quotes, or backticks. It is interpolated into the generated play source (including comments); use a plain monitor tool id / stream key / name.`
4187
- );
4188
- }
4189
- return value;
4190
- }
4191
- function parseMonitorBootstrapOptions(args) {
4192
- const [, ...rest] = args;
4193
- const options = {
4194
- name: MONITOR_BOOTSTRAP_TEMPLATE,
4195
- tool: MONITOR_BOOTSTRAP_DEFAULT_TOOL,
4196
- stream: MONITOR_BOOTSTRAP_DEFAULT_STREAM,
4197
- out: null
4198
- };
4199
- for (let index = 0; index < rest.length; index += 1) {
4200
- const arg = rest[index];
4201
- const value = () => nextFlagValue(rest, index, arg);
4202
- switch (arg) {
4203
- case "--name":
4204
- options.name = validateMonitorBootstrapFlagValue("--name", value());
4205
- index += 1;
4206
- break;
4207
- case "--tool":
4208
- options.tool = validateMonitorBootstrapFlagValue("--tool", value());
4209
- index += 1;
4210
- break;
4211
- case "--stream":
4212
- options.stream = validateMonitorBootstrapFlagValue("--stream", value());
4213
- index += 1;
4214
- break;
4215
- case "--out":
4216
- options.out = value();
4217
- index += 1;
4218
- break;
4219
- default:
4220
- throw new PlayBootstrapUsageError(
4221
- `Unknown plays bootstrap option for ${MONITOR_BOOTSTRAP_TEMPLATE}: ${arg}
4222
- Usage: deepline plays bootstrap ${MONITOR_BOOTSTRAP_TEMPLATE} [--tool <monitor-tool-id>] [--stream <stream-key>] [--name NAME] [--out monitor.play.ts]`
4223
- );
4224
- }
4225
- }
4226
- if (!options.tool) {
4227
- throw new PlayBootstrapUsageError(
4228
- `${MONITOR_BOOTSTRAP_TEMPLATE} needs a non-empty --tool.`
4229
- );
4230
- }
4231
- if (!options.stream) {
4232
- throw new PlayBootstrapUsageError(
4233
- `${MONITOR_BOOTSTRAP_TEMPLATE} needs a non-empty --stream.`
4234
- );
4235
- }
4236
- return options;
4237
- }
4238
- function generateMonitorTriggeredPlaySource(options) {
4239
- return `import { definePlay } from 'deepline';
4240
- import type { SqlListenerEvent } from 'deepline';
4241
-
4242
- // Row shape delivered by ${options.tool} / ${options.stream}. This is a starting
4243
- // point only: inspect the real columns with
4244
- // deepline monitors available ${options.tool}
4245
- // and tighten this type to the fields you read below.
4246
- //
4247
- // Before deploying a NEW monitor, run \`deepline monitors list\` \u2014 if one
4248
- // already feeds this stream for your scope, this play will already react to its
4249
- // rows (a play binds to the shared stream), so you may not need to deploy at all.
4250
- type MonitorRow = Record<string, unknown>;
4251
-
4252
- export default definePlay(
4253
- ${jsString(options.name)},
4254
- async (ctx, event: SqlListenerEvent<MonitorRow>) => {
4255
- // The monitor delivers the changed row as event.after. It is null for
4256
- // DELETE operations, so guard before reading fields.
4257
- const row = event.after;
4258
- if (!row) {
4259
- ctx.log(\`Monitor \${event.tool}/\${event.stream} \${event.operation} with no row; nothing to do.\`);
4260
- return { handled: false, operation: event.operation };
4261
- }
4262
-
4263
- ctx.log(
4264
- \`Monitor \${event.tool}/\${event.stream} \${event.operation}: \${JSON.stringify(row).slice(0, 200)}\`,
4265
- );
4266
-
4267
- // Capture the changed row into a durable dataset so the run has inspectable,
4268
- // exportable output. ctx.dataset is a CALLABLE: ctx.dataset(key, rows) where
4269
- // key is a compile-time string LITERAL and rows is an array of row objects.
4270
- // It returns a builder; add per-row columns with .withColumn(name, resolver)
4271
- // and finish with .run(). There is no .push/.add \u2014 pass all rows up front.
4272
- // TODO: replace this plain persist with your real per-row work \u2014 enrich each
4273
- // row via .withColumn('...', (row, rowCtx) => rowCtx.tools.execute(...)),
4274
- // notify, write to another table, or fan out with rowCtx.runPlay.
4275
- const captured = await ctx.dataset('monitor_events', [row]).run({
4276
- description: \`Captured \${event.tool}/\${event.stream} \${event.operation} rows.\`,
4277
- });
4278
-
4279
- return {
4280
- handled: true,
4281
- tool: event.tool,
4282
- stream: event.stream,
4283
- operation: event.operation,
4284
- changedAt: event.changedAt,
4285
- capturedRows: await captured.count(),
4286
- };
4287
- },
4288
- {
4289
- description: ${jsString(`Run whenever ${options.tool} writes a new ${options.stream} row.`)},
4290
- // A monitor trigger: this play wakes on row changes written by the bound
4291
- // monitor tool + stream. Discover a tool's streams and columns with:
4292
- // deepline monitors available ${options.tool}
4293
- // To bind a different monitor, swap tool/stream (and re-check operations)
4294
- // for one of its (tool, stream) pairs.
4295
- sqlListeners: [
4296
- {
4297
- id: 'events',
4298
- tool: ${jsString(options.tool)},
4299
- stream: ${jsString(options.stream)},
4300
- operations: ['INSERT'],
4301
- // Optional: only wake on some rows \u2014 add a where filter to the binding above:
4302
- // where: { after: { <column>: { eq: 'value' } } } // operators: eq, neq, in, notIn, isNull, isNotNull, ilike
4303
- },
4304
- ],
4305
- },
4306
- );
4307
- `;
4308
- }
4309
- function playBootstrapUsageLine() {
4310
- 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] [--out flow.play.ts]`;
4311
- }
4312
- function requireBootstrapTemplate(rawTemplate) {
4313
- if (!rawTemplate) {
4314
- throw new PlayBootstrapUsageError(
4315
- `plays bootstrap needs a route template: ${formatPlayBootstrapTemplates()}|${MONITOR_BOOTSTRAP_TEMPLATE}.
4316
- Example: deepline plays bootstrap people-email --from csv:data/leads.csv --using play:prebuilt/name-and-domain-to-email-waterfall --out email-flow.play.ts`
4317
- );
4318
- }
4319
- if (!isPlayBootstrapTemplate(rawTemplate)) {
4320
- const looksLikePlayReference = rawTemplate.includes("/") || rawTemplate.endsWith(".play.ts");
4321
- throw new PlayBootstrapUsageError(
4322
- `Unknown plays bootstrap template: ${rawTemplate}
4323
- Supported templates: ${formatPlayBootstrapTemplates()}|${MONITOR_BOOTSTRAP_TEMPLATE}` + (looksLikePlayReference ? `
4324
-
4325
- "${rawTemplate}" looks like an existing play reference or file, not a bootstrap template. Do not run plays bootstrap on prebuilt/<play-name>. Use "deepline plays run ${rawTemplate} --input '{...}'" to run it directly, "deepline describe ${rawTemplate}" to inspect its contract, or "deepline plays get ${rawTemplate} --source --out scratchpad.play.ts" to clone/edit it.` : "")
4326
- );
4327
- }
4328
- return rawTemplate;
4329
- }
4330
- function nextFlagValue(args, index, flag) {
4331
- const value = args[index + 1];
4332
- if (!value || value.startsWith("--")) {
4333
- throw new PlayBootstrapUsageError(`${flag} needs a value.`);
4334
- }
4335
- return value;
4336
- }
4337
- function stageFlag(stage) {
4338
- return `--${stage}`;
4339
- }
4340
- function stageRefHelp(stage) {
4341
- switch (stage) {
4342
- case "people":
4343
- return "play:<people-play>";
4344
- case "email":
4345
- case "phone":
4346
- return "<play:REF|provider:ID|providers:ID,ID>";
4347
- }
4348
- }
4349
- function getStageRef(options, stage) {
4350
- switch (stage) {
4351
- case "people":
4352
- return options.people;
4353
- case "email":
4354
- return options.email;
4355
- case "phone":
4356
- return options.phone;
4357
- }
4358
- }
4359
- function setStageRef(options, stage, ref) {
4360
- switch (stage) {
4361
- case "people":
4362
- options.people = ref;
4363
- return;
4364
- case "email":
4365
- options.email = ref;
4366
- return;
4367
- case "phone":
4368
- options.phone = ref;
4369
- return;
4370
- }
4371
- }
4372
- function unsupportedStageMessage(template, stage) {
4373
- switch (stage) {
4374
- case "people":
4375
- return `${template} does not accept --people. Use company-people, company-people-email, or company-people-phone.`;
4376
- case "email":
4377
- return `${template} does not accept --email. Use people-email or company-people-email.`;
4378
- case "phone":
4379
- return `${template} does not accept --phone. Use people-phone or company-people-phone.`;
4380
- }
4381
- }
4382
- function requireSource(options) {
4383
- if (!options.from) {
4384
- throw new PlayBootstrapUsageError(
4385
- `${options.template} needs --from.
4386
- Example: ${templateExample(options.template)}`
4387
- );
4388
- }
4389
- return options.from;
4390
- }
4391
- function assertAllowedStageFlags(options, allowedStages) {
4392
- const allowed = new Set(allowedStages);
4393
- for (const stage of PLAY_BOOTSTRAP_STAGE_NAMES) {
4394
- if (!allowed.has(stage) && getStageRef(options, stage)) {
4395
- throw new PlayBootstrapUsageError(
4396
- unsupportedStageMessage(options.template, stage)
4397
- );
4398
- }
4399
- }
4400
- }
4401
- function assertRequiredStages(options, stages) {
4402
- for (const stage of stages) {
4403
- if (!getStageRef(options, stage)) {
4404
- throw new PlayBootstrapUsageError(
4405
- `${options.template} needs ${stageFlag(stage)} ${stageRefHelp(stage)}.
4406
- Example: ${templateExample(options.template)}`
4407
- );
4408
- }
4409
- }
4410
- }
4411
- function normalizeSingleStageRoute(options, stage) {
4412
- const explicitStage = getStageRef(options, stage);
4413
- if (options.using && explicitStage) {
4414
- throw new PlayBootstrapUsageError(
4415
- `${options.template} received both --using and ${stageFlag(stage)}. Choose one stage binding.`
4416
- );
4417
- }
4418
- const selectedStage = options.using ?? explicitStage;
4419
- if (!selectedStage) {
4420
- throw new PlayBootstrapUsageError(
4421
- `${options.template} needs --using ${stageRefHelp(stage)} or ${stageFlag(stage)} ${stageRefHelp(stage)}.
4422
- Example: ${templateExample(options.template)}`
4423
- );
4424
- }
4425
- setStageRef(options, stage, selectedStage);
4426
- options.using = selectedStage;
4427
- assertAllowedStageFlags(options, [stage]);
4428
- }
4429
- function normalizeMultiStageRoute(options, stages) {
4430
- if (options.using) {
4431
- throw new PlayBootstrapUsageError(
4432
- `${options.template} does not accept --using. Use the explicit stage flags shown in: ${templateExample(options.template)}`
4433
- );
4434
- }
4435
- assertRequiredStages(options, stages);
4436
- assertAllowedStageFlags(options, stages);
4437
- }
4438
- function normalizeTemplateStages(options) {
4439
- const config = playBootstrapTemplateConfig(options.template);
4440
- const from = requireSource(options);
4441
- switch (config.usingStage) {
4442
- case "people":
4443
- case "email":
4444
- case "phone":
4445
- normalizeSingleStageRoute(options, config.usingStage);
4446
- break;
4447
- case null:
4448
- normalizeMultiStageRoute(options, config.requiredStages);
4449
- break;
4450
- }
4451
- return {
4452
- ...options,
4453
- from
4454
- };
4455
- }
4456
- function parsePlayBootstrapOptions(args) {
4457
- const [rawTemplate, ...rest] = args;
4458
- const template = requireBootstrapTemplate(rawTemplate);
4459
- const options = {
4460
- template,
4461
- name: `gtm-${template}`,
4462
- from: null,
4463
- using: null,
4464
- people: null,
4465
- email: null,
4466
- phone: null,
4467
- limit: 5,
4468
- out: null
4469
- };
4470
- for (let index = 0; index < rest.length; index += 1) {
4471
- const arg = rest[index];
4472
- const value = () => nextFlagValue(rest, index, arg);
4473
- switch (arg) {
4474
- case "--name":
4475
- options.name = value();
4476
- index += 1;
4477
- break;
4478
- case "--from":
4479
- options.from = parseBootstrapSourceRef(value(), "--from");
4480
- index += 1;
4481
- break;
4482
- case "--using":
4483
- options.using = parseBootstrapStageRef(value(), "--using");
4484
- index += 1;
4485
- break;
4486
- case "--people":
4487
- options.people = parseBootstrapStageRef(value(), "--people");
4488
- index += 1;
4489
- break;
4490
- case "--email":
4491
- options.email = parseBootstrapStageRef(value(), "--email");
4492
- index += 1;
4493
- break;
4494
- case "--phone":
4495
- options.phone = parseBootstrapStageRef(value(), "--phone");
4496
- index += 1;
4497
- break;
4498
- case "--limit":
4499
- options.limit = parsePositiveInteger(value(), "--limit");
4500
- index += 1;
4501
- break;
4502
- case "--out":
4503
- options.out = value();
4504
- index += 1;
4505
- break;
4506
- default:
4507
- throw new PlayBootstrapUsageError(
4508
- `Unknown plays bootstrap option: ${arg}
4509
- ${playBootstrapUsageLine()}`
4510
- );
4511
- }
4512
- }
4513
- return normalizeTemplateStages(options);
4514
- }
4515
- function jsString(value) {
4516
- return JSON.stringify(value);
4517
- }
4518
- function inferCsvCellTypeExpression(values) {
4519
- const nonEmptyValues = values.map((value) => value.trim()).filter((value) => value.length > 0);
4520
- const hasEmptyValue = values.some((value) => value.trim().length === 0);
4521
- if (nonEmptyValues.length === 0) return "string";
4522
- const numericPattern = /^[+-]?(?:(?:\d+\.?\d*)|(?:\.\d+))(?:[eE][+-]?\d+)?$/;
4523
- const booleanPattern = /^(?:true|false)$/i;
4524
- let inferred = "string";
4525
- if (nonEmptyValues.every((value) => numericPattern.test(value))) {
4526
- inferred = "`${number}`";
4527
- } else if (nonEmptyValues.every((value) => booleanPattern.test(value))) {
4528
- const canonicalBooleanValues = nonEmptyValues.every(
4529
- (value) => value === "true" || value === "false"
4530
- );
4531
- inferred = canonicalBooleanValues ? '"false" | "true"' : [...new Set(nonEmptyValues)].sort().map(jsString).join(" | ");
4532
- }
4533
- return hasEmptyValue && inferred !== "string" ? `${inferred} | ""` : inferred;
4534
- }
4535
- function inferCsvColumnSpecs(headers, rows) {
4536
- return headers.map((header) => ({
4537
- name: header,
4538
- typeExpression: inferCsvCellTypeExpression(
4539
- rows.map((row) => String(row[header] ?? ""))
4540
- )
4541
- }));
4542
- }
4543
- function readCsvSample(csvPath) {
4544
- const resolvedPath = resolve(csvPath);
4545
- const size = statSync(resolvedPath).size;
4546
- const fd = openSync(resolvedPath, "r");
4547
- const byteLength = Math.min(size, CSV_HEADER_SAMPLE_BYTES);
4548
- const buffer = Buffer.alloc(byteLength);
4549
- const bytesRead = readSync(fd, buffer, 0, byteLength, 0);
4550
- closeSync(fd);
4551
- if (bytesRead === 0) {
4552
- throw new PlayBootstrapUsageError(`--from csv:${csvPath} is empty.`);
4553
- }
4554
- return {
4555
- content: buffer.subarray(0, bytesRead).toString("utf8"),
4556
- truncated: size > bytesRead
4557
- };
4558
- }
4559
- function completeCsvSample(csvPath, sample) {
4560
- if (!sample.truncated) return sample.content;
4561
- const lastLineBreak = Math.max(
4562
- sample.content.lastIndexOf("\n"),
4563
- sample.content.lastIndexOf("\r")
4564
- );
4565
- if (lastLineBreak < 0) {
4566
- throw new PlayBootstrapUsageError(
4567
- `CSV header in ${csvPath} is longer than ${CSV_HEADER_SAMPLE_BYTES} bytes; shorten the header row before bootstrapping.`
4568
- );
4569
- }
4570
- return sample.content.slice(0, lastLineBreak + 1);
4571
- }
4572
- function readCsvHeaderFields(csvPath, sample) {
4573
- const records = parseCsvSync(sample, {
4574
- bom: true,
4575
- to_line: 1,
4576
- relax_column_count: true,
4577
- skip_empty_lines: false
4578
- });
4579
- const firstRecord = Array.isArray(records) ? records[0] : null;
4580
- const fields2 = Array.isArray(firstRecord) ? firstRecord.map((field) => String(field ?? "").trim()).filter(Boolean) : [];
4581
- const uniqueFields = [...new Set(fields2)];
4582
- if (uniqueFields.length === 0) {
4583
- throw new PlayBootstrapUsageError(
4584
- `Could not read a header row from --from csv:${csvPath}.`
4585
- );
4586
- }
4587
- return uniqueFields;
4588
- }
4589
- function readCsvSampleRows(sample) {
4590
- const parsedRows = parseCsvSync(sample, {
4591
- bom: true,
4592
- columns: true,
4593
- skip_empty_lines: true,
4594
- relax_column_count: true,
4595
- trim: true
4596
- });
4597
- return Array.isArray(parsedRows) ? parsedRows.filter(isRecord) : [];
4598
- }
4599
- function readSourceCsvColumnSpecs(csvPath) {
4600
- const sample = readCsvSample(csvPath);
4601
- const completeSample = completeCsvSample(csvPath, sample);
4602
- return inferCsvColumnSpecs(
4603
- readCsvHeaderFields(csvPath, sample.content),
4604
- readCsvSampleRows(completeSample)
4605
- );
4606
- }
4607
- function renderSourceCsvRowType(columns) {
4608
- if (columns.length === 0) return "";
4609
- const properties = columns.map((column) => ` ${jsString(column.name)}: ${column.typeExpression};`).join("\n");
4610
- return `// CSV cells are strings at runtime. \`${"${number}"}\` means a numeric-looking CSV string; cast before math.
4611
- type SourceCsvRow = {
4612
- ${properties}
4613
- };
4614
-
4615
- `;
4616
- }
4617
- function packagedCsvPathForPlay(csvPath) {
4618
- const playDir = process.cwd();
4619
- const absoluteCsvPath = resolve(csvPath);
4620
- const relativePath = relative(playDir, absoluteCsvPath);
4621
- if (relativePath === "" || relativePath.startsWith("..") || isAbsolute(relativePath)) {
4622
- throw new PlayBootstrapUsageError(
4623
- `--from csv:${csvPath} must point to a file inside the directory where you run plays bootstrap. Run bootstrap from the intended play directory and write the play with --out there.`
4624
- );
4625
- }
4626
- const portablePath = relativePath.split("\\").join("/");
4627
- return portablePath.startsWith(".") ? portablePath : `./${portablePath}`;
4628
- }
4629
- function getterNamesFromTool(tool, kind) {
4630
- const usageGuidance = isRecord(tool?.usageGuidance) ? tool.usageGuidance : {};
4631
- const resultGuidance = isRecord(usageGuidance.toolExecutionResult) ? usageGuidance.toolExecutionResult : isRecord(usageGuidance.tool_execution_result) ? usageGuidance.tool_execution_result : {};
4632
- const key = kind === "list" ? "extractedLists" : "extractedValues";
4633
- const snakeKey = kind === "list" ? "extracted_lists" : "extracted_values";
4634
- return extractionEntries(resultGuidance[key] ?? resultGuidance[snakeKey]).map((entry) => stringValue(entry.name)).filter(Boolean);
4635
- }
4636
- function targetGettersFromTool(tool) {
4637
- const record3 = isRecord(tool) ? tool : {};
4638
- const raw = record3.targetGetters ?? record3.target_getters;
4639
- if (!isRecord(raw)) return {};
4640
- const entries = [];
4641
- for (const [target, value] of Object.entries(raw)) {
4642
- const paths = Array.isArray(value) ? value.map((path) => typeof path === "string" ? path.trim() : "").filter(Boolean) : [];
4643
- if (target.trim() && paths.length > 0) {
4644
- entries.push([target.trim(), paths]);
4645
- }
4646
- }
4647
- return Object.fromEntries(entries);
4648
- }
4649
- function listRowCandidateKeysFromTool(tool) {
4650
- const keys = /* @__PURE__ */ new Set();
4651
- for (const paths of Object.values(targetGettersFromTool(tool))) {
4652
- for (const path of paths) {
4653
- const key = path.replace(/\[(?:\*|\d+)\]/g, "").split(/[.[\]]/, 1)[0]?.trim();
4654
- if (key) keys.add(key);
4655
- }
4656
- }
4657
- return [...keys].sort();
4658
- }
4659
- function inputPropertyNames(schema) {
4660
- if (!isRecord(schema)) return [];
4661
- if (isRecord(schema.properties)) return Object.keys(schema.properties);
4662
- if (Array.isArray(schema.fields)) {
4663
- return schema.fields.filter(isRecord).map((field) => stringValue(field.name)).filter(Boolean);
4664
- }
4665
- return [];
4666
- }
4667
- function schemaFieldDetails(schema) {
4668
- const required = requiredPlayInputFields({
4669
- inputSchema: schema
4670
- });
4671
- const optional = inputPropertyNames(schema).filter(
4672
- (field) => !required.includes(field)
4673
- );
4674
- return { required, optional };
4675
- }
4676
- function jsonSchemaTypeExpression(schema) {
4677
- if (!isRecord(schema)) return "unknown";
4678
- const type = schema.type;
4679
- if (Array.isArray(type)) {
4680
- return type.map((entry) => jsonSchemaTypeExpression({ ...schema, type: entry })).join(" | ");
4681
- }
4682
- if (Array.isArray(schema.anyOf)) {
4683
- return schema.anyOf.map(jsonSchemaTypeExpression).join(" | ");
4684
- }
4685
- if (Array.isArray(schema.oneOf)) {
4686
- return schema.oneOf.map(jsonSchemaTypeExpression).join(" | ");
4687
- }
4688
- switch (type) {
4689
- case "string":
4690
- return "string";
4691
- case "number":
4692
- case "integer":
4693
- return "number";
4694
- case "boolean":
4695
- return "boolean";
4696
- case "null":
4697
- return "null";
4698
- case "array":
4699
- return `Array<${jsonSchemaTypeExpression(schema.items)}>`;
4700
- case "object":
4701
- return "Record<string, unknown>";
4702
- default:
4703
- return "unknown";
4704
- }
4705
- }
4706
- function objectPropertySchema(schema, property) {
4707
- return isRecord(schema) && isRecord(schema.properties) ? schema.properties[property] : null;
4708
- }
4709
- function playOutputHasField(schema, field) {
4710
- return objectPropertySchema(schema, field) != null;
4711
- }
4712
- function finderResultTypeName(finder) {
4713
- return finder === "email_finder" ? "EmailFinderPlayResult" : "PhoneFinderPlayResult";
4714
- }
4715
- function renderFinderPlayResultType(input) {
4716
- if (!input.play) return null;
4717
- const outputField = PLAY_BOOTSTRAP_OUTPUT_FIELD_BY_FINDER[input.finder];
4718
- const fieldSchema = objectPropertySchema(
4719
- input.play.outputSchema,
4720
- outputField
4721
- );
4722
- if (fieldSchema) {
4723
- const fieldType = jsonSchemaTypeExpression(fieldSchema);
4724
- return `type ${finderResultTypeName(input.finder)} = {
4725
- ${outputField}?: ${fieldType};
4726
- };`;
4727
- }
4728
- return `type ${finderResultTypeName(input.finder)} = ${jsonSchemaTypeExpression(input.play.outputSchema)};`;
4729
- }
4730
- function generatedFinderPlayResultTypes(input) {
4731
- return ["email_finder", "phone_finder"].flatMap((finder) => {
4732
- const stage = finderStage(input.options, finder);
4733
- if (stage?.kind !== "play") return [];
4734
- const typeDefinition = renderFinderPlayResultType({
4735
- finder,
4736
- play: input.finderPlays[finder]
4737
- });
4738
- return typeDefinition ? [typeDefinition] : [];
4739
- }).join("\n\n");
4740
- }
4741
- function exampleValueComment(field) {
4742
- if (field === "limit" || field === "numResults" || field === "num_results" || field === "page_size") {
4743
- return "limit";
4744
- }
4745
- if (field === "roles" || field.endsWith("s")) return '["..."]';
4746
- return '"..."';
4747
- }
4748
- function rowFieldValueExpression(field) {
4749
- if (field === "limit" || field === "numResults" || field === "num_results" || field === "page_size" || field === "max_duration") {
4750
- return `Number(row[${jsString(field)}] ?? 0)`;
4751
- }
4752
- if (field === "roles" || field.endsWith("s")) {
4753
- return `String(row[${jsString(field)}] ?? '').split(',').map((item) => item.trim()).filter(Boolean)`;
4754
- }
4755
- return `String(row[${jsString(field)}] ?? '')`;
4756
- }
4757
- function generateContactInputObjectFromSchema(schema, indent, label, fallbackFields = ["first_name", "last_name", "domain"]) {
4758
- const details = schemaFieldDetails(schema);
4759
- const required = details.required.length ? details.required : fallbackFields;
4760
- const optional = details.optional;
4761
- const lines = [
4762
- `${indent}// TODO: map row fields into ${label}.`,
4763
- ...playInspectionComments(label, indent),
4764
- `${indent}// Required: ${required.join(", ") || "none declared"}.`
4765
- ];
4766
- for (const field of required) {
4767
- lines.push(
4768
- `${indent}${field}: ${rowFieldValueExpression(field)}, // TODO: confirm source field`
4769
- );
4770
- }
4771
- if (optional.length > 0) {
4772
- lines.push("");
4773
- lines.push(`${indent}// optional (delete unused):`);
4774
- for (const field of optional) {
4775
- lines.push(`${indent}// ${field}: row["TODO_SOURCE_FIELD"],`);
4776
- }
4777
- }
4778
- return `{
4779
- ${lines.join("\n")}
4780
- ${indent.slice(2)}}`;
4781
- }
4782
- function generateCompanyInputObjectFromSchema(schema, indent, label, fallbackFields = ["domain", "company_name"]) {
4783
- const details = schemaFieldDetails(schema);
4784
- const required = details.required.length ? details.required : fallbackFields;
4785
- const optional = details.optional;
4786
- const lines = [
4787
- `${indent}// TODO: map company fields into ${label}.`,
4788
- ...playInspectionComments(label, indent),
4789
- `${indent}// Required: ${required.join(", ") || "none declared"}.`
4790
- ];
4791
- for (const field of required) {
4792
- lines.push(`${indent}// ${field}: company["TODO_SOURCE_FIELD"],`);
4793
- }
4794
- if (optional.length > 0) {
4795
- lines.push("");
4796
- lines.push(`${indent}// optional (delete unused):`);
4797
- for (const field of optional) {
4798
- lines.push(`${indent}// ${field}: company["TODO_SOURCE_FIELD"],`);
4799
- }
4800
- }
4801
- return `{
4802
- ${lines.join("\n")}
4803
- ${indent.slice(2)}}`;
4804
- }
4805
- function generateSourceProviderInputObject(input) {
4806
- const { tool, indent, label, entity } = input;
4807
- const properties = inputPropertyNames(tool?.inputSchema);
4808
- const details = schemaFieldDetails(tool?.inputSchema);
4809
- const required = details.required;
4810
- const includeOptional = properties.length === 0 ? ["query", "title", "domain", "limit"] : properties.filter(
4811
- (field) => [
4812
- "query",
4813
- "q",
4814
- "search",
4815
- "title",
4816
- "role",
4817
- "persona",
4818
- "domain",
4819
- "company_domain",
4820
- "limit",
4821
- "numResults",
4822
- "num_results",
4823
- "page_size"
4824
- ].includes(field)
4825
- );
4826
- const lines = [
4827
- `${indent}// TODO: fill ${entity} source inputs for ${label}.`,
4828
- `${indent}// Inspect: deepline describe ${label}`
4829
- ];
4830
- for (const field of required) {
4831
- lines.push(`${indent}// ${field}: ${exampleValueComment(field)},`);
4832
- }
4833
- const activeTodoField = required.length === 0 ? ["query", "q", "search", "title", "role", "persona"].find(
4834
- (field) => includeOptional.includes(field)
4835
- ) ?? "query" : null;
4836
- if (activeTodoField) {
4837
- lines.push(
4838
- `${indent}// ${activeTodoField}: ${exampleValueComment(activeTodoField)},`
4839
- );
4840
- }
4841
- const optionalExamples = includeOptional.filter(
4842
- (field) => !required.includes(field) && field !== activeTodoField
4843
- );
4844
- if (optionalExamples.length > 0) {
4845
- lines.push("");
4846
- lines.push(`${indent}// optional - uncomment what this provider supports:`);
4847
- for (const field of optionalExamples) {
4848
- if (field === "limit" || field === "numResults" || field === "num_results" || field === "page_size") {
4849
- lines.push(`${indent}// ${field}: limit,`);
4850
- } else {
4851
- lines.push(`${indent}// ${field}: ${exampleValueComment(field)},`);
4852
- }
4853
- }
4854
- }
4855
- if (!required.some(
4856
- (field) => ["limit", "numResults", "num_results", "page_size"].includes(field)
4857
- )) {
4858
- lines.push(`${indent}limit,`);
4859
- }
4860
- return `{
4861
- ${lines.join("\n")}
4862
- ${indent.slice(2)}}`;
4863
- }
4864
- function generatePlayInputObject(input) {
4865
- const { schema, indent, label, entity } = input;
4866
- const details = schemaFieldDetails(schema);
4867
- const fallback = entity === "company" ? ["domain", "company_name"] : ["first_name", "last_name", "domain"];
4868
- const required = details.required.length ? details.required : fallback;
4869
- const lines = [
4870
- `${indent}// TODO: fill source play inputs for ${label}.`,
4871
- ...playInspectionComments(label, indent)
4872
- ];
4873
- for (const field of required) {
4874
- lines.push(`${indent}// ${field}: ${exampleValueComment(field)},`);
4875
- }
4876
- if (!required.includes("limit")) lines.push(`${indent}limit,`);
4877
- return `{
4878
- ${lines.join("\n")}
4879
- ${indent.slice(2)}}`;
4880
- }
4881
- function requiredPlayInputFields(play) {
4882
- const schema = play?.inputSchema;
4883
- if (!isRecord(schema)) return [];
4884
- if (Array.isArray(schema.required)) {
4885
- return schema.required.filter(
4886
- (value) => typeof value === "string"
4887
- );
4888
- }
4889
- if (Array.isArray(schema.fields)) {
4890
- return schema.fields.filter(isRecord).filter(
4891
- (field) => field.required === true && typeof field.name === "string"
4892
- ).map((field) => String(field.name));
4893
- }
4894
- return [];
4895
- }
4896
- function sourceProviders(options) {
4897
- return options.from.kind === "providers" ? options.from.values : [];
4898
- }
4899
- function sourcePlayRef(options) {
4900
- return options.from.kind === "play" ? options.from.value : null;
4901
- }
4902
- function stagePlayRef(stage) {
4903
- return stage?.kind === "play" ? stage.value : null;
4904
- }
4905
- function stageProviders(stage) {
4906
- return stage?.kind === "providers" ? stage.values : [];
4907
- }
4908
- function finderStage(options, finder) {
4909
- return finder === "email_finder" ? options.email : options.phone;
4910
- }
4911
- function stepFieldName(finder) {
4912
- return PLAY_BOOTSTRAP_OUTPUT_FIELD_BY_FINDER[finder];
4913
- }
4914
- function finderProviderStepPrefix(finder) {
4915
- return finder === "email_finder" ? "emailFinder" : "phoneFinder";
4916
- }
4917
- function safeIdentifier(value) {
4918
- return value.replace(/[^A-Za-z0-9_]+/g, "_");
4919
- }
4920
- function playInspectionComments(playRef, indent) {
4921
- return [`${indent}// Inspect: deepline describe ${playRef}`];
4922
- }
4923
- function accessorExpression(base, field) {
4924
- return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(field) ? `${base}.${field}` : `${base}[${jsString(field)}]`;
4925
- }
4926
- function sourceCollectionTypeName(entity) {
4927
- return entity === "company" ? "CompanySourceRow" : "ContactSourceRow";
4928
- }
4929
- function renderPartialRowType(input) {
4930
- if (input.fields.length === 0) {
4931
- return `type ${input.typeName} = Record<string, unknown>;`;
4932
- }
4933
- const properties = input.fields.map((field) => ` ${jsString(field)}?: unknown;`).join("\n");
4934
- return `type ${input.typeName} = Record<string, unknown> & Partial<{
4935
- // ${input.comment}
4936
- ${properties}
4937
- }>;`;
4938
- }
4939
- function fieldsFromSchemaDetails(input) {
4940
- return [
4941
- ...input.details.required.length ? input.details.required : input.fallbackFields,
4942
- ...input.details.optional
4943
- ];
4944
- }
4945
- function schemaFieldsForStage(stage, input) {
4946
- switch (stage?.kind) {
4947
- case void 0:
4948
- return [];
4949
- case "play":
4950
- return fieldsFromSchemaDetails({
4951
- details: schemaFieldDetails(input.play?.inputSchema),
4952
- fallbackFields: input.fallbackFields
4953
- });
4954
- case "providers":
4955
- return input.tools.flatMap(
4956
- (tool) => fieldsFromSchemaDetails({
4957
- details: schemaFieldDetails(tool.inputSchema),
4958
- fallbackFields: input.fallbackFields
4959
- })
4960
- );
4961
- }
4962
- }
4963
- function sourceRowTypeDefinition(input) {
4964
- switch (input.options.from.kind) {
4965
- case "csv":
4966
- return `type ${input.sourceTypeName} = SourceCsvRow;`;
4967
- case "providers":
4968
- return renderPartialRowType({
4969
- typeName: input.sourceTypeName,
4970
- fields: [
4971
- ...new Set(input.sourceTools.flatMap(listRowCandidateKeysFromTool))
4972
- ].sort(),
4973
- comment: "Candidate source row keys from described list getters; confirm the actual provider keys with source_*.extractedLists.*.keys before mapping."
4974
- });
4975
- case "play": {
4976
- const details = schemaFieldDetails(input.sourcePlay?.outputSchema);
4977
- return renderPartialRowType({
4978
- typeName: input.sourceTypeName,
4979
- fields: [...details.required, ...details.optional].sort(),
4980
- comment: "Candidate source play output fields; confirm the selected rows field before mapping."
4981
- });
4982
- }
4983
- }
4984
- }
4985
- function contactBridgeRowTypeDefinition(input) {
4986
- const config = playBootstrapTemplateConfig(input.options.template);
4987
- if (config.sourceEntity !== "company" || !input.options.people) return null;
4988
- const emailFields = schemaFieldsForStage(input.options.email, {
4989
- tools: input.finderTools.email_finder ?? [],
4990
- play: input.finderPlays.email_finder,
4991
- fallbackFields: ["first_name", "last_name", "domain"]
4992
- });
4993
- const phoneFields = schemaFieldsForStage(input.options.phone, {
4994
- tools: input.finderTools.phone_finder ?? [],
4995
- play: input.finderPlays.phone_finder,
4996
- fallbackFields: ["first_name", "last_name", "domain"]
4997
- });
4998
- return renderPartialRowType({
4999
- typeName: "ContactSourceRow",
5000
- fields: [
5001
- .../* @__PURE__ */ new Set([
5002
- ...inputPropertyNames(input.peoplePlay?.outputSchema),
5003
- ...emailFields,
5004
- ...phoneFields
5005
- ])
5006
- ].sort(),
5007
- comment: "Fields the people play or later finder stages may need; the generated code still requires explicit mapping."
5008
- });
5009
- }
5010
- function generateRowTypeDefinitions(input) {
5011
- const config = playBootstrapTemplateConfig(input.options.template);
5012
- const sourceTypeName = sourceCollectionTypeName(config.sourceEntity);
5013
- const definitions = [
5014
- sourceRowTypeDefinition({
5015
- options: input.options,
5016
- sourceTypeName,
5017
- sourceTools: input.sourceTools,
5018
- sourcePlay: input.sourcePlay
5019
- }),
5020
- contactBridgeRowTypeDefinition(input)
5021
- ];
5022
- return definitions.filter(Boolean).join("\n\n");
5023
- }
5024
- function validateBootstrapRoutes(input) {
5025
- const config = playBootstrapTemplateConfig(input.options.template);
5026
- const sourceCategory = config.sourceEntity === "company" ? PLAY_BOOTSTRAP_COMPANY_PROVIDER_CATEGORY : PLAY_BOOTSTRAP_PEOPLE_PROVIDER_CATEGORY;
5027
- for (const tool of input.sourceTools) {
5028
- if (!tool.categories.includes(sourceCategory)) {
5029
- throw new PlayBootstrapValidationError(
5030
- `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`
5031
- );
5032
- }
5033
- if (getterNamesFromTool(tool, "list").length === 0) {
5034
- throw new PlayBootstrapValidationError(
5035
- `Cannot use ${tool.toolId} as a ${config.sourceEntity} source: it exposes no extracted list getters. Run: deepline describe ${tool.toolId}`
5036
- );
5037
- }
5038
- }
5039
- if (input.options.people?.kind === "providers") {
5040
- throw new PlayBootstrapValidationError(
5041
- "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."
5042
- );
5043
- }
5044
- assertComposablePlayRoute({
5045
- stageLabel: "--people",
5046
- playRef: stagePlayRef(input.options.people),
5047
- play: input.peoplePlay
5048
- });
5049
- for (const finder of ["email_finder", "phone_finder"]) {
5050
- const requiredCategory = PLAY_BOOTSTRAP_PROVIDER_CATEGORY_BY_FINDER[finder];
5051
- assertComposablePlayRoute({
5052
- stageLabel: finder === "email_finder" ? "--email/--using" : "--phone/--using",
5053
- playRef: stagePlayRef(finderStage(input.options, finder)),
5054
- play: input.finderPlays[finder] ?? null
5055
- });
5056
- for (const tool of input.finderTools[finder] ?? []) {
5057
- if (!tool.categories.includes(requiredCategory)) {
5058
- throw new PlayBootstrapValidationError(
5059
- `Cannot use ${tool.toolId} for ${finder}: expected category ${requiredCategory}, got ${tool.categories.join(", ") || "none"}. Run: deepline tools grep ${requiredCategory} --categories ${requiredCategory} --json`
5060
- );
5061
- }
5062
- if (getterNamesFromTool(tool, "value").length === 0) {
5063
- throw new PlayBootstrapValidationError(
5064
- `Cannot use ${tool.toolId} as a ${finder}: it exposes no extracted value getters. Run: deepline describe ${tool.toolId}`
5065
- );
5066
- }
5067
- }
5068
- }
5069
- }
5070
- function staticPipelineSubsteps(pipeline) {
5071
- if (!isRecord(pipeline)) return [];
5072
- return [
5073
- ...extractionEntries(pipeline.stages),
5074
- ...extractionEntries(pipeline.substeps)
5075
- ];
5076
- }
5077
- function playUsesMapBackedRuntime(play) {
5078
- const pipeline = play?.staticPipeline;
5079
- if (!isRecord(pipeline)) return false;
5080
- if (stringValue(pipeline.tableNamespace)) return true;
5081
- return staticPipelineSubsteps(pipeline).some((substep) => {
5082
- if (stringValue(substep.type) === "map") return true;
5083
- return playUsesMapBackedRuntime({
5084
- name: play?.name ?? "child",
5085
- aliases: [],
5086
- runCommand: "",
5087
- examples: [],
5088
- staticPipeline: isRecord(substep.pipeline) ? substep.pipeline : null
5089
- });
5090
- });
5091
- }
5092
- function assertComposablePlayRoute(input) {
5093
- if (!input.playRef || !playUsesMapBackedRuntime(input.play)) return;
5094
- const runCommand = input.play?.runCommand?.trim() || `deepline plays run ${input.playRef} --input '{...}'`;
5095
- throw new PlayBootstrapValidationError(
5096
- `Cannot use ${input.stageLabel} play:${input.playRef} in plays bootstrap composition: the selected play is dataset-backed/direct-run-only. Child plays that use ctx.dataset() own durable table state and must be run directly, exported, or validated as their own play instead of wrapped with ctx.runPlay. Run it directly first: ${runCommand}`
5097
- );
5098
- }
5099
- function sourcePlayNeedsExportFirst(input) {
5100
- return input.source.kind === "play" && playUsesMapBackedRuntime(input.sourcePlay);
5101
- }
5102
- function sourceCollectionName(entity) {
5103
- switch (entity) {
5104
- case "company":
5105
- return "companies";
5106
- case "people":
5107
- return "contacts";
5108
- }
5109
- }
5110
- function requiredGetterName(input) {
5111
- const getter = getterNamesFromTool(input.tool, input.kind)[0];
5112
- if (!getter) {
5113
- switch (input.kind) {
5114
- case "list":
5115
- throw new PlayBootstrapValidationError(
5116
- `Cannot use ${input.label} as a source: it exposes no extracted list getters.`
5117
- );
5118
- case "value":
5119
- throw new PlayBootstrapValidationError(
5120
- `Cannot use ${input.label} as a finder: it exposes no extracted value getters.`
5121
- );
5122
- }
5123
- }
5124
- return getter;
5125
- }
5126
- function generateCsvSourceRowsBlock(input) {
5127
- return `const sourceDataset = await ctx.csv<SourceCsvRow>(${jsString(input.packagedSourceCsvPath ?? input.source.value)});
5128
- const ${input.collection}: ${input.collectionType}[] = await sourceDataset.peek(limit);`;
5129
- }
5130
- function generatePlaySourceRowsBlock(input) {
5131
- if (sourcePlayNeedsExportFirst({
5132
- source: input.source,
5133
- sourcePlay: input.sourcePlay
5134
- })) {
5135
- const sourcePlay = input.sourcePlay;
5136
- const runCommand = sourcePlay?.runCommand?.trim() || `deepline plays run ${input.source.value} --input '{...}'`;
5137
- return `// Source play ${input.source.value} is dataset-backed/direct-run-only, so this generated play is stage 2.
5138
- // Stage 1:
5139
- // ${runCommand}
5140
- // Stage 2:
5141
- // deepline runs export <stage-1-run-id> --dataset 'result.rows' --out source-export.csv
5142
- // Stage 3:
5143
- // deepline plays run <this-file.play.ts> --input '{"sourceCsv":"source-export.csv","limit":${input.sourcePlay ? "5" : "5"}}'
5144
- const sourceDataset = await ctx.csv<${input.collectionType}>(input.sourceCsv ?? './source-export.csv');
5145
- const ${input.collection}: ${input.collectionType}[] = await sourceDataset.peek(limit);`;
5146
- }
5147
- const playInput = generatePlayInputObject({
5148
- schema: input.sourcePlay?.inputSchema,
5149
- indent: " ",
5150
- label: input.source.value,
5151
- entity: input.entity
5152
- });
5153
- return `const sourceInput = ${playInput};
5154
- throw new Error(${jsString(`TODO: map sourceInput for ${input.source.value}, choose the play output rows field, then delete this throw.`)});
5155
- const sourceResult = (await ctx.runPlay('source_play', ${jsString(input.source.value)}, sourceInput, {
5156
- description: ${jsString(`Seed ${input.entity} rows from the selected play.`)},
5157
- })) as { rows?: unknown[] };
5158
- // TODO: Replace sourceResult.rows with the selected play's actual row output field.
5159
- const ${input.collection}: ${input.collectionType}[] = (sourceResult.rows ?? []) as ${input.collectionType}[];`;
5160
- }
5161
- function generateProviderSourceBlock(input) {
5162
- const getter = requiredGetterName({
5163
- tool: input.tool,
5164
- kind: "list",
5165
- label: input.provider
5166
- });
5167
- const inputName = `${input.entity}Input_${input.index}`;
5168
- return `// ${input.entity === "company" ? "Company" : "People"} source provider: ${input.provider}
5169
- const ${inputName}: Record<string, unknown> = ${generateSourceProviderInputObject(
5170
- {
5171
- tool: input.tool,
5172
- indent: " ",
5173
- label: input.provider,
5174
- entity: input.entity
5175
- }
5176
- )};
5177
- throw new Error(${jsString(`TODO: fill ${inputName} for ${input.provider}, then delete this throw.`)});
5178
- const source_${input.index} = await ctx.tools.execute({
5179
- staleAfterSeconds: 0,
5180
- id: ${jsString(`${input.entity}_source_${input.index}`)},
5181
- tool: ${jsString(input.provider)},
5182
- input: ${inputName},
5183
- description: ${jsString(`Seed ${input.entity} rows from ${input.provider}.`)},
5184
- });
5185
- // extractedLists.${getter}.get() returns provider-shaped rows. Do not assume canonical fields;
5186
- // inspect source_${input.index}.extractedLists.${getter}.keys or the provider output schema, then map explicitly below.
5187
- const sourceList_${input.index} = ${accessorExpression(`source_${input.index}.extractedLists`, getter)}.get();
5188
- // Legacy admitted Plays use a dataset getter; the new contract returns an ordinary array.
5189
- const sourceRows_${input.index} = (Array.isArray(sourceList_${input.index})
5190
- ? sourceList_${input.index}.slice(0, limit)
5191
- : await sourceList_${input.index}.peek(limit)) as ${input.collectionType}[];`;
5192
- }
5193
- function generateProviderSourceRowsBlock(input) {
5194
- const blocks = input.source.values.map(
5195
- (provider, index) => generateProviderSourceBlock({
5196
- provider,
5197
- index,
5198
- tool: input.sourceTools[index] ?? null,
5199
- entity: input.entity,
5200
- collectionType: input.collectionType
5201
- })
5202
- );
5203
- return `${blocks.join("\n\n ")}
5204
- const ${input.collection}: ${input.collectionType}[] = [${input.source.values.map((_, index) => `...sourceRows_${index}`).join(", ")}];`;
5205
- }
5206
- function generateSourceRowsBlock(input) {
5207
- const config = playBootstrapTemplateConfig(input.options.template);
5208
- const entity = config.sourceEntity;
5209
- const collection = sourceCollectionName(entity);
5210
- const collectionType = sourceCollectionTypeName(entity);
5211
- switch (input.options.from.kind) {
5212
- case "csv":
5213
- return generateCsvSourceRowsBlock({
5214
- source: input.options.from,
5215
- collection,
5216
- collectionType,
5217
- packagedSourceCsvPath: input.packagedSourceCsvPath
5218
- });
5219
- case "play":
5220
- return generatePlaySourceRowsBlock({
5221
- source: input.options.from,
5222
- sourcePlay: input.sourcePlay,
5223
- entity,
5224
- collection,
5225
- collectionType
5226
- });
5227
- case "providers":
5228
- return generateProviderSourceRowsBlock({
5229
- source: input.options.from,
5230
- sourceTools: input.sourceTools,
5231
- entity,
5232
- collection,
5233
- collectionType
5234
- });
5235
- }
5236
- }
5237
- function generateSourceSeedBlock(input) {
5238
- const sourceRows = generateSourceRowsBlock(input);
5239
- const peoplePlayRef = stagePlayRef(input.options.people);
5240
- if (!peoplePlayRef) return sourceRows;
5241
- const peopleInput = generateCompanyInputObjectFromSchema(
5242
- input.peoplePlay?.inputSchema,
5243
- " ",
5244
- peoplePlayRef,
5245
- ["domain", "company_name"]
5246
- );
5247
- return `${sourceRows}
5248
- const contacts: ContactSourceRow[] = [];
5249
- for (const [index, company] of companies.slice(0, limit).entries()) {
5250
- const peopleInput = ${peopleInput};
5251
- throw new Error(${jsString(`TODO: map company fields into peopleInput for ${peoplePlayRef}, choose the play output rows field, then delete this throw.`)});
5252
- const peopleResult = (await ctx.runPlay(
5253
- \`people_play_\${index}\`,
5254
- ${jsString(peoplePlayRef)},
5255
- peopleInput,
5256
- {
5257
- description: 'Map one company row into people/contact rows with the selected play.',
5258
- },
5259
- )) as { rows?: unknown[] };
5260
- // TODO: Replace peopleResult.rows with the selected play's actual contact rows field.
5261
- contacts.push(...((peopleResult.rows ?? []) as ContactSourceRow[]));
5262
- }`;
5263
- }
5264
- function finderProviderStepName(input) {
5265
- return `${input.aggregateStepName}${input.index}_${safeIdentifier(input.provider)}`;
5266
- }
5267
- function finderValueGetter(input) {
5268
- const getters = getterNamesFromTool(input.tool, "value");
5269
- const getter = getters.find((name) => name === input.outputField) ?? requiredGetterName({
5270
- tool: input.tool,
5271
- kind: "value",
5272
- label: input.provider
5273
- });
5274
- return getter;
5275
- }
5276
- function optionalFinderValueExpression(candidateExpression, outputField) {
5277
- const valueExpression = /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(outputField) ? `${candidateExpression}?.${outputField}` : `${candidateExpression}?.[${jsString(outputField)}]`;
5278
- return `${valueExpression}?.trim()`;
5279
- }
5280
- function generateFinderPlayStep(input) {
5281
- const outputField = PLAY_BOOTSTRAP_OUTPUT_FIELD_BY_FINDER[input.finder];
5282
- const resultTypeName = finderResultTypeName(input.finder);
5283
- const returnsObjectWithField = playOutputHasField(
5284
- input.play?.outputSchema,
5285
- outputField
5286
- );
5287
- const payload = generateContactInputObjectFromSchema(
5288
- input.play?.inputSchema,
5289
- " ",
5290
- input.stage.value
5291
- );
5292
- return `.withColumn(${jsString(outputField)}, async (row, rowCtx) => {
5293
- const ${input.aggregateStepName}Input = ${payload};
5294
- throw new Error(${jsString(`TODO: map ${input.aggregateStepName}Input for ${input.stage.value}, then delete this throw.`)});
5295
- const ${input.aggregateStepName}Result = await rowCtx.runPlay<${resultTypeName}>(
5296
- ${jsString(`${input.aggregateStepName}Play`)},
5297
- ${jsString(input.stage.value)},
5298
- ${input.aggregateStepName}Input,
5299
- {
5300
- description: ${jsString(`Run ${input.finder} play.`)},
5301
- },
5302
- );
5303
- return ${returnsObjectWithField ? `${input.aggregateStepName}Result.${outputField} ?? null` : `${input.aggregateStepName}Result ?? null`};
5304
- })`;
5305
- }
5306
- function generateFinderProviderResolver(input) {
5307
- const payload = generateContactInputObjectFromSchema(
5308
- input.tool?.inputSchema,
5309
- " ",
5310
- input.provider
5311
- );
5312
- const getter = finderValueGetter({
5313
- tool: input.tool,
5314
- provider: input.provider,
5315
- outputField: input.outputField
5316
- });
5317
- return `async (row, rowCtx) => {
5318
- const providerInput = ${payload};
5319
- throw new Error(${jsString(`TODO: map providerInput for ${input.provider}, then delete this throw.`)});
5320
- const result = await rowCtx.tools.execute({
5321
- staleAfterSeconds: 0,
5322
- id: ${jsString(`${input.aggregateStepName}_${input.providerIndex}`)},
5323
- tool: ${jsString(input.provider)},
5324
- input: providerInput,
5325
- description: ${jsString(`Try ${input.provider} as a ${input.finder}.`)},
5326
- });
5327
- return {
5328
- ${input.outputField}: (${accessorExpression("result.extractedValues", getter)}.get() as string | null) ?? null,
5329
- result,
5330
- };
5331
- }`;
5332
- }
5333
- function generateFinderProviderStep(input) {
5334
- const stepName = input.stepNames[input.index];
5335
- switch (input.index) {
5336
- case 0:
5337
- return `.withColumn(${jsString(stepName)}, ${input.resolver})`;
5338
- default: {
5339
- const priorCandidates = input.stepNames.slice(0, input.index).map((name) => `row.${name}`).join(", ");
5340
- return `.withColumn(
5341
- ${jsString(stepName)},
5342
- ${input.resolver},
5343
- {
5344
- runIf: (row) => ![${priorCandidates}].some((candidate) => ${optionalFinderValueExpression("candidate", input.outputField)}),
5345
- },
5346
- )`;
5347
- }
5348
- }
5349
- }
5350
- function generateFinderProviderWaterfall(input) {
5351
- const legPrefix = finderProviderStepPrefix(input.finder);
5352
- const stepNames = input.stage.values.map(
5353
- (provider, index) => finderProviderStepName({
5354
- aggregateStepName: legPrefix,
5355
- provider,
5356
- index
5357
- })
5358
- );
5359
- const providerSteps = input.stage.values.map(
5360
- (provider, index) => generateFinderProviderStep({
5361
- index,
5362
- stepNames,
5363
- outputField: input.outputField,
5364
- resolver: generateFinderProviderResolver({
5365
- finder: input.finder,
5366
- provider,
5367
- providerIndex: index,
5368
- tool: input.tools[index] ?? null,
5369
- aggregateStepName: input.aggregateStepName,
5370
- outputField: input.outputField
5371
- })
5372
- })
5373
- );
5374
- const candidateNames = stepNames.map((name) => `row.${name}`).join(", ");
5375
- return `// ${input.aggregateStepName} provider waterfall. Each provider leg is active once its TODO throw is removed;
5376
- // delete or comment out legs you do not want before running. Later legs are gated with { runIf }.
5377
- ${providerSteps.join("\n ")}
5378
- .withColumn(${jsString(input.aggregateStepName)}, (row) => {
5379
- const candidates = [${candidateNames}];
5380
- const match = candidates.find((candidate) => ${optionalFinderValueExpression("candidate", input.outputField)});
5381
- return ${optionalFinderValueExpression("match", input.outputField)} ?? null;
5382
- })`;
5383
- }
5384
- function generateFinderStageSteps(input) {
5385
- const outputField = PLAY_BOOTSTRAP_OUTPUT_FIELD_BY_FINDER[input.finder];
5386
- const aggregateStepName = stepFieldName(input.finder);
5387
- switch (input.stage.kind) {
5388
- case "play":
5389
- return generateFinderPlayStep({
5390
- finder: input.finder,
5391
- stage: input.stage,
5392
- play: input.finderPlays[input.finder],
5393
- aggregateStepName
5394
- });
5395
- case "providers":
5396
- return generateFinderProviderWaterfall({
5397
- finder: input.finder,
5398
- stage: input.stage,
5399
- tools: input.finderTools[input.finder] ?? [],
5400
- aggregateStepName,
5401
- outputField
5402
- });
5403
- }
5404
- }
5405
- function generateFinderSteps(input) {
5406
- return ["email_finder", "phone_finder"].flatMap((finder) => {
5407
- const stage = finderStage(input.options, finder);
5408
- return stage ? [
5409
- generateFinderStageSteps({
5410
- ...input,
5411
- finder,
5412
- stage
5413
- })
5414
- ] : [];
5415
- }).join("\n ");
5416
- }
5417
- function generateBootstrapPlaySource(input) {
5418
- const config = playBootstrapTemplateConfig(input.options.template);
5419
- const sourceSeedBlock = generateSourceSeedBlock(input);
5420
- const finderSteps = generateFinderSteps(input);
5421
- const hasPeople = config.sourceEntity === "people" || Boolean(input.options.people);
5422
- const sourceCollection = hasPeople ? "contacts" : "companies";
5423
- const mapSteps = finderSteps ? `
5424
- ${finderSteps}` : "";
5425
- const sourceCsvRowType = input.options.from.kind === "csv" ? renderSourceCsvRowType(input.sourceCsvColumns) : "";
5426
- const rowTypeDefinitions = generateRowTypeDefinitions(input);
5427
- const finderPlayResultTypes = generatedFinderPlayResultTypes(input);
5428
- const typeDefinitions = [
5429
- sourceCsvRowType.trimEnd(),
5430
- rowTypeDefinitions,
5431
- finderPlayResultTypes
5432
- ].filter((definition) => definition.trim().length > 0).join("\n\n");
5433
- return `import { definePlay } from 'deepline';
5434
-
5435
- ${typeDefinitions}
5436
-
5437
- type Input = {
5438
- limit?: number;
5439
- sourceCsv?: string;
5440
- };
5441
-
5442
- export default definePlay(${jsString(input.options.name)}, async (ctx, input: Input = {}) => {
5443
- const limit = Math.max(1, Math.min(Number(input.limit ?? ${input.options.limit}), ${input.options.limit}));
5444
- ${sourceSeedBlock}
5445
-
5446
- const rowsToProcess = ${sourceCollection}.slice(0, limit);
5447
- if (rowsToProcess.length === 0) {
5448
- throw new Error('plays bootstrap found 0 source rows. Check the source provider/play/CSV output.');
5449
- }
5450
-
5451
- const rows = await ctx
5452
- .dataset('bootstrap_rows', rowsToProcess)${mapSteps}
5453
- .run({
5454
- key: (_row, index) => index,
5455
- description: ${jsString(`Bootstrap ${input.options.template}: seed source rows, run requested stages, then return the mapped rows.`)},
5456
- });
5457
-
5458
- return {
5459
- count: await rows.count(),
5460
- rows,
5461
- };
5462
- }, {
5463
- description: ${jsString(`Bootstrap ${input.options.template}: seed source rows, run requested stages, and return mapped rows.`)},
5464
- });
5465
-
5466
- `;
5467
- }
5468
- async function describePlayMaybe(client, playRef) {
5469
- return playRef ? client.describePlay(playRef, { compact: true }) : null;
5470
- }
5471
- function loadTools(client, providers) {
5472
- return Promise.all(providers.map((provider) => client.getTool(provider)));
5473
- }
5474
- async function loadBootstrapContracts(client, options) {
5475
- const [
5476
- sourceTools,
5477
- sourcePlay,
5478
- peoplePlay,
5479
- emailPlay,
5480
- phonePlay,
5481
- emailTools,
5482
- phoneTools
5483
- ] = await Promise.all([
5484
- loadTools(client, sourceProviders(options)),
5485
- describePlayMaybe(client, sourcePlayRef(options)),
5486
- describePlayMaybe(client, stagePlayRef(options.people)),
5487
- describePlayMaybe(client, stagePlayRef(options.email)),
5488
- describePlayMaybe(client, stagePlayRef(options.phone)),
5489
- loadTools(client, stageProviders(options.email)),
5490
- loadTools(client, stageProviders(options.phone))
5491
- ]);
5492
- const contracts = {
5493
- sourceTools,
5494
- sourcePlay,
5495
- peoplePlay,
5496
- finderTools: {
5497
- email_finder: emailTools,
5498
- phone_finder: phoneTools
5499
- },
5500
- finderPlays: {
5501
- email_finder: emailPlay,
5502
- phone_finder: phonePlay
5503
- }
5504
- };
5505
- validateBootstrapRoutes({
5506
- options,
5507
- sourceTools: contracts.sourceTools,
5508
- sourcePlay: contracts.sourcePlay,
5509
- peoplePlay: contracts.peoplePlay,
5510
- finderTools: contracts.finderTools,
5511
- finderPlays: contracts.finderPlays
5512
- });
5513
- return contracts;
5514
- }
5515
- function loadCsvContext(source) {
5516
- switch (source.kind) {
5517
- case "csv":
5518
- return {
5519
- packagedSourceCsvPath: packagedCsvPathForPlay(source.value),
5520
- sourceCsvColumns: readSourceCsvColumnSpecs(source.value)
5521
- };
5522
- case "play":
5523
- case "providers":
5524
- return {
5525
- packagedSourceCsvPath: null,
5526
- sourceCsvColumns: []
5527
- };
5528
- }
5529
- }
5530
- function errorMessage(error) {
5531
- return error instanceof Error ? error.message : String(error);
5532
- }
5533
- function renderPlayBootstrapError(error) {
5534
- console.error(errorMessage(error));
5535
- return error instanceof PlayBootstrapError ? error.exitCode : 1;
5536
- }
5537
- function writeBootstrapSource(source, out) {
5538
- if (out) {
5539
- writeFileSync(resolve(out), source, "utf-8");
5540
- process.stdout.write(`Wrote ${resolve(out)}
5541
- `);
5542
- return 0;
5543
- }
5544
- process.stdout.write(source);
5545
- return 0;
5546
- }
5547
- function runMonitorBootstrap(args) {
5548
- const options = parseMonitorBootstrapOptions(args);
5549
- const source = generateMonitorTriggeredPlaySource(options);
5550
- return writeBootstrapSource(source, options.out);
5551
- }
5552
- async function runPlayBootstrap(args) {
5553
- if (isMonitorBootstrapTemplate(args[0])) {
5554
- return runMonitorBootstrap(args);
5555
- }
5556
- const options = parsePlayBootstrapOptions(args);
5557
- const client = new DeeplineClient();
5558
- const contracts = await loadBootstrapContracts(client, options);
5559
- const csvContext = loadCsvContext(options.from);
5560
- const source = generateBootstrapPlaySource({
5561
- options,
5562
- ...contracts,
5563
- ...csvContext
5564
- });
5565
- return writeBootstrapSource(source, options.out);
5566
- }
5567
- async function handlePlayBootstrap(args) {
5568
- return runPlayBootstrap(args).catch(renderPlayBootstrapError);
5569
- }
5570
- function registerPlayBootstrapCommand(play) {
5571
- play.command("bootstrap <template>").description(
5572
- "Print a scratchpad play for a GTM route or monitor-triggered template."
5573
- ).addHelpText(
5574
- "after",
5575
- `
5576
- Notes:
5577
- Cloud-validated play generator for agents. Pick the JTBD as the positional
5578
- template, bind resources with typed refs, write the .play.ts file with --out,
5579
- then edit the generated TODO mapping comments. Multiple finder providers are
5580
- generated as a waterfall in the order you pass them.
5581
-
5582
- This command requires auth because provider/play contracts are fetched from
5583
- Deepline. It prints TypeScript source only and does not run paid tools; the
5584
- generated play may spend credits later when you run it.
5585
-
5586
- By default stdout is the generated .play.ts source. Use --out to write a file
5587
- directly. Errors and diagnostics go to stderr. There is no JSON mode.
5588
-
5589
- Templates:
5590
- people-list start from people/contact rows
5591
- company-list start from company/account rows
5592
- people-email people/contact rows -> email finder
5593
- people-phone people/contact rows -> phone finder
5594
- company-people company/account rows -> people play
5595
- company-people-email company/account rows -> people play -> email finder
5596
- company-people-phone company/account rows -> people play -> phone finder
5597
- monitor-triggered run a play whenever a monitor writes a new row
5598
- (definePlay with sqlListeners; no --from/stage flags)
5599
-
5600
- Monitor-triggered options (only for the monitor-triggered template):
5601
- --tool <monitor-tool-id> monitor tool to bind (default deepline_native.company_radar)
5602
- --stream <stream-key> output stream to listen on (default company_job_openings)
5603
- Discover a tool's streams/columns with: deepline monitors available <id>
5604
-
5605
- Resource refs:
5606
- csv:./contacts.csv
5607
- play:prebuilt/name-and-domain-to-email-waterfall
5608
- provider:dropleads_search_people
5609
- providers:hunter_email_finder,leadmagic_email_finder
5610
-
5611
- Validation:
5612
- source providers must match the route entity: company_search or people_search
5613
- source providers must expose list getters
5614
- company -> people uses a play only; provider bridge is generated later when a play exists
5615
- email/phone finder providers must match their category and expose value getters
5616
- finder plays/providers must match the route; generated code leaves input mapping explicit
5617
- business-specific provider inputs and company -> people persona fields are TODOs in code
5618
- csv: paths are resolved from the directory where you run bootstrap; write the play file there too
5619
-
5620
- Exit codes:
5621
- 0 success
5622
- 2 usage/local input error
5623
- 7 route validation failed
5624
-
5625
- Examples:
5626
- deepline plays bootstrap people-email --from csv:data/leads.csv --using play:prebuilt/name-and-domain-to-email-waterfall --limit 5 --out email-flow.play.ts
5627
- deepline plays check email-flow.play.ts
5628
- deepline plays run email-flow.play.ts --input '{"limit":5}'
5629
-
5630
- deepline plays bootstrap people-email --from provider:dropleads_search_people --using providers:hunter_email_finder,leadmagic_email_finder --limit 5 --out prospecting.play.ts
5631
- deepline plays bootstrap company-people-email --from provider:crustdata_companydb_search --people play:prebuilt/company-to-contact --email play:prebuilt/name-and-domain-to-email-waterfall --limit 5 --out account-contacts.play.ts
5632
- deepline plays bootstrap company-list --from provider:crustdata_companydb_search --limit 5 --out companies.play.ts
5633
-
5634
- deepline plays bootstrap monitor-triggered --out on-new-row.play.ts
5635
- deepline plays bootstrap monitor-triggered --tool deepline_native.company_radar --stream company_job_openings --out on-new-job.play.ts
5636
- `
5637
- ).option("--name <name>", "Generated play name").option(
5638
- "--from <ref>",
5639
- "Route source: csv:PATH, play:REF, provider:ID, or providers:ID,ID"
5640
- ).option(
5641
- "--using <ref>",
5642
- "Single-stage route shorthand for people-email, people-phone, or company-people"
5643
- ).option(
5644
- "--people <ref>",
5645
- "Company-to-people stage for company-people-email/phone; use play:REF"
5646
- ).option(
5647
- "--email <ref>",
5648
- "Email finder stage: play:REF, provider:ID, or providers:ID,ID"
5649
- ).option(
5650
- "--phone <ref>",
5651
- "Phone finder stage: play:REF, provider:ID, or providers:ID,ID"
5652
- ).option("--limit <n>", "Maximum rows to fan out in the generated play").option(
5653
- "--tool <id>",
5654
- "monitor-triggered only: monitor tool id to bind (e.g. deepline_native.company_radar)"
5655
- ).option(
5656
- "--stream <key>",
5657
- "monitor-triggered only: monitor output stream to listen on (e.g. company_job_openings)"
5658
- ).option("--out <path>", "Write generated play source to a file").action(async (template, options) => {
5659
- process.exitCode = await handlePlayBootstrap([
5660
- template,
5661
- ...options.name ? ["--name", options.name] : [],
5662
- ...options.from ? ["--from", options.from] : [],
5663
- ...options.using ? ["--using", options.using] : [],
5664
- ...options.people ? ["--people", options.people] : [],
5665
- ...options.email ? ["--email", options.email] : [],
5666
- ...options.phone ? ["--phone", options.phone] : [],
5667
- ...options.limit ? ["--limit", options.limit] : [],
5668
- ...options.tool ? ["--tool", options.tool] : [],
5669
- ...options.stream ? ["--stream", options.stream] : [],
5670
- ...options.out ? ["--out", options.out] : []
5671
- ]);
5672
- });
5673
- }
5674
-
5675
3989
  // src/cli/commands/run-receipt.ts
5676
3990
  import { readFile, writeFile } from "fs/promises";
5677
3991
  function registerRunReceiptCommand(runs) {
@@ -6028,8 +4342,8 @@ function formatRunHitCountLines(tables) {
6028
4342
  }
6029
4343
 
6030
4344
  // src/cli/run-dataset-csv.ts
6031
- import { writeFileSync as writeFileSync2 } from "fs";
6032
- import { resolve as resolve2 } from "path";
4345
+ import { writeFileSync } from "fs";
4346
+ import { resolve } from "path";
6033
4347
 
6034
4348
  // ../plays/table-csv.ts
6035
4349
  var TABLE_EXPORT_ERROR_COLUMN = "_error";
@@ -6135,9 +4449,9 @@ var RunDatasetCsv = class _RunDatasetCsv {
6135
4449
  return this.#projection;
6136
4450
  }
6137
4451
  write(outPath) {
6138
- const absolutePath = resolve2(outPath);
4452
+ const absolutePath = resolve(outPath);
6139
4453
  const { rows, columns } = this.#projection;
6140
- writeFileSync2(
4454
+ writeFileSync(
6141
4455
  absolutePath,
6142
4456
  tableCsvText(
6143
4457
  columns,
@@ -6376,24 +4690,24 @@ function sanitizeCsvProjectionInfo(input) {
6376
4690
  const rows = input.rows.map(stripCsvProjectionFields);
6377
4691
  return { rows, columns };
6378
4692
  }
6379
- function isRecord2(value) {
4693
+ function isRecord(value) {
6380
4694
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
6381
4695
  }
6382
4696
  function isSerializedDataset(value) {
6383
- return isRecord2(value) && value.kind === "dataset" && typeof value.count === "number" && (Array.isArray(value.preview) || typeof value.tableNamespace === "string");
4697
+ return isRecord(value) && value.kind === "dataset" && typeof value.count === "number" && (Array.isArray(value.preview) || typeof value.tableNamespace === "string");
6384
4698
  }
6385
4699
  function isPackagedDatasetOutput(value) {
6386
- return isRecord2(value) && value.kind === "dataset" && isRecord2(value.preview) && Array.isArray(value.preview.rows);
4700
+ return isRecord(value) && value.kind === "dataset" && isRecord(value.preview) && Array.isArray(value.preview.rows);
6387
4701
  }
6388
4702
  function hasCurrentTableExport(value) {
6389
- if (!isRecord2(value) || !isRecord2(value.actions)) return false;
4703
+ if (!isRecord(value) || !isRecord(value.actions)) return false;
6390
4704
  const exportCsv = value.actions.exportCsv;
6391
- return isRecord2(exportCsv) && isRecord2(exportCsv.scope) && exportCsv.scope.kind === "database" && exportCsv.scope.mutability === "current";
4705
+ return isRecord(exportCsv) && isRecord(exportCsv.scope) && exportCsv.scope.kind === "database" && exportCsv.scope.mutability === "current";
6392
4706
  }
6393
4707
  function currentTableQueryCommand(value) {
6394
- if (!isRecord2(value) || !isRecord2(value.actions)) return void 0;
4708
+ if (!isRecord(value) || !isRecord(value.actions)) return void 0;
6395
4709
  const query = value.actions.queryCurrentTable;
6396
- const command = isRecord2(query) ? query.command : void 0;
4710
+ const command = isRecord(query) ? query.command : void 0;
6397
4711
  return typeof command === "string" && command.trim() ? command.trim() : void 0;
6398
4712
  }
6399
4713
  function recoveredReturnPaths(value) {
@@ -6425,7 +4739,7 @@ function pathParts(path) {
6425
4739
  function valueAtPath(root, path) {
6426
4740
  let cursor = root;
6427
4741
  for (const part of pathParts(path)) {
6428
- if (!isRecord2(cursor)) {
4742
+ if (!isRecord(cursor)) {
6429
4743
  return void 0;
6430
4744
  }
6431
4745
  cursor = cursor[part];
@@ -6433,17 +4747,17 @@ function valueAtPath(root, path) {
6433
4747
  return cursor;
6434
4748
  }
6435
4749
  function totalRowsForDataset(result, datasetPath) {
6436
- const metadata = isRecord2(result._metadata) ? result._metadata : null;
4750
+ const metadata = isRecord(result._metadata) ? result._metadata : null;
6437
4751
  const parentPath = datasetPath.split(".").slice(0, -1).join(".");
6438
4752
  const parent = parentPath ? valueAtPath({ result }, parentPath) : result;
6439
- return metadata?.totalRows ?? metadata?.rowCount ?? metadata?.count ?? (isRecord2(parent) ? parent.totalRows ?? parent.rowCount ?? parent.count : void 0) ?? result.totalRows ?? result.rowCount ?? result.count;
4753
+ return metadata?.totalRows ?? metadata?.rowCount ?? metadata?.count ?? (isRecord(parent) ? parent.totalRows ?? parent.rowCount ?? parent.count : void 0) ?? result.totalRows ?? result.rowCount ?? result.count;
6440
4754
  }
6441
4755
  function rowArray(value) {
6442
4756
  if (!Array.isArray(value)) {
6443
4757
  return null;
6444
4758
  }
6445
4759
  const rows = value.filter(
6446
- (row) => isRecord2(row)
4760
+ (row) => isRecord(row)
6447
4761
  );
6448
4762
  return rows.length === value.length ? rows : null;
6449
4763
  }
@@ -6467,7 +4781,7 @@ function inferColumns(rows) {
6467
4781
  return columns;
6468
4782
  }
6469
4783
  function columnsFromDatasetSummary(summary) {
6470
- if (!isRecord2(summary) || !isRecord2(summary.columnStats)) {
4784
+ if (!isRecord(summary) || !isRecord(summary.columnStats)) {
6471
4785
  return [];
6472
4786
  }
6473
4787
  return Object.keys(summary.columnStats).filter((column) => column);
@@ -6529,7 +4843,7 @@ function canonicalRowsInfoFromCandidate(input) {
6529
4843
  candidate.value.recoveredReturnPaths
6530
4844
  )
6531
4845
  } : {},
6532
- ...isRecord2(candidate.value.exportUnavailable) && (candidate.value.exportUnavailable.reason === "empty_dataset" || candidate.value.exportUnavailable.reason === "shared_table_namespace" || candidate.value.exportUnavailable.reason === "ambiguous_selector" || candidate.value.exportUnavailable.reason === "returned_dataset_not_persisted") ? {
4846
+ ...isRecord(candidate.value.exportUnavailable) && (candidate.value.exportUnavailable.reason === "empty_dataset" || candidate.value.exportUnavailable.reason === "shared_table_namespace" || candidate.value.exportUnavailable.reason === "ambiguous_selector" || candidate.value.exportUnavailable.reason === "returned_dataset_not_persisted") ? {
6533
4847
  exportUnavailableReason: candidate.value.exportUnavailable.reason,
6534
4848
  ...typeof candidate.value.exportUnavailable.message === "string" ? {
6535
4849
  exportUnavailableMessage: candidate.value.exportUnavailable.message
@@ -6577,7 +4891,7 @@ function collectDatasetCandidates(input) {
6577
4891
  });
6578
4892
  return;
6579
4893
  }
6580
- if (!isRecord2(input.value)) {
4894
+ if (!isRecord(input.value)) {
6581
4895
  return;
6582
4896
  }
6583
4897
  for (const [key, child] of Object.entries(input.value)) {
@@ -6594,12 +4908,12 @@ function collectDatasetCandidates(input) {
6594
4908
  }
6595
4909
  }
6596
4910
  function collectCanonicalRowsInfos(statusOrResult) {
6597
- const root = isRecord2(statusOrResult) ? statusOrResult : null;
6598
- const result = isRecord2(root?.result) ? root.result : root;
4911
+ const root = isRecord(statusOrResult) ? statusOrResult : null;
4912
+ const result = isRecord(root?.result) ? root.result : root;
6599
4913
  if (!result) {
6600
4914
  return [];
6601
4915
  }
6602
- const metadata = isRecord2(result._metadata) ? result._metadata : null;
4916
+ const metadata = isRecord(result._metadata) ? result._metadata : null;
6603
4917
  const totalFromMetadata = metadata?.totalRows ?? metadata?.rowCount ?? metadata?.count;
6604
4918
  const candidates = [
6605
4919
  {
@@ -6623,8 +4937,8 @@ function collectCanonicalRowsInfos(statusOrResult) {
6623
4937
  total: totalFromMetadata ?? result.totalRows ?? result.rowCount ?? result.count
6624
4938
  }
6625
4939
  ];
6626
- if (isRecord2(result.output)) {
6627
- const outputMetadata = isRecord2(result.output._metadata) ? result.output._metadata : null;
4940
+ if (isRecord(result.output)) {
4941
+ const outputMetadata = isRecord(result.output._metadata) ? result.output._metadata : null;
6628
4942
  const outputTotalFromMetadata = outputMetadata?.totalRows ?? outputMetadata?.rowCount ?? outputMetadata?.count;
6629
4943
  candidates.push(
6630
4944
  {
@@ -6651,14 +4965,14 @@ function collectCanonicalRowsInfos(statusOrResult) {
6651
4965
  }
6652
4966
  if (Array.isArray(result.steps)) {
6653
4967
  result.steps.forEach((step, index) => {
6654
- if (!isRecord2(step) || !isRecord2(step.output)) {
4968
+ if (!isRecord(step) || !isRecord(step.output)) {
6655
4969
  return;
6656
4970
  }
6657
4971
  const source = typeof step.output.path === "string" ? step.output.path : typeof step.id === "string" ? `steps.${step.id}.output` : `steps.${index}.output`;
6658
4972
  candidates.push({
6659
4973
  source,
6660
4974
  value: step.output,
6661
- total: step.output.rowCount ?? (isRecord2(step.output.preview) ? step.output.preview.totalRows : void 0) ?? (isRecord2(step.progress) ? step.progress.total : void 0)
4975
+ total: step.output.rowCount ?? (isRecord(step.output.preview) ? step.output.preview.totalRows : void 0) ?? (isRecord(step.progress) ? step.progress.total : void 0)
6662
4976
  });
6663
4977
  });
6664
4978
  }
@@ -6679,15 +4993,15 @@ function collectCanonicalRowsInfos(statusOrResult) {
6679
4993
  return distinctCanonicalRowsInfos(infos);
6680
4994
  }
6681
4995
  function collectPackagedDatasetCandidates(statusOrResult) {
6682
- const root = isRecord2(statusOrResult) ? statusOrResult : null;
4996
+ const root = isRecord(statusOrResult) ? statusOrResult : null;
6683
4997
  if (!root) {
6684
4998
  return [];
6685
4999
  }
6686
- const pkg = isRecord2(root.package) ? root.package : root;
5000
+ const pkg = isRecord(root.package) ? root.package : root;
6687
5001
  const datasets = Array.isArray(pkg.datasets) ? pkg.datasets : [];
6688
5002
  const candidates = [];
6689
5003
  for (const output of datasets) {
6690
- if (!isRecord2(output) || !isPackagedDatasetOutput(output)) {
5004
+ if (!isRecord(output) || !isPackagedDatasetOutput(output)) {
6691
5005
  continue;
6692
5006
  }
6693
5007
  const source = typeof output.path === "string" && output.path.trim() ? output.path.trim() : null;
@@ -6697,18 +5011,18 @@ function collectPackagedDatasetCandidates(statusOrResult) {
6697
5011
  candidates.push({
6698
5012
  source,
6699
5013
  value: output,
6700
- total: output.rowCount ?? (isRecord2(output.preview) ? output.preview.totalRows : void 0)
5014
+ total: output.rowCount ?? (isRecord(output.preview) ? output.preview.totalRows : void 0)
6701
5015
  });
6702
5016
  }
6703
5017
  return candidates;
6704
5018
  }
6705
5019
  function collectPackagedStepDatasetCandidates(statusOrResult) {
6706
- const root = isRecord2(statusOrResult) ? statusOrResult : null;
5020
+ const root = isRecord(statusOrResult) ? statusOrResult : null;
6707
5021
  if (!root) return [];
6708
- const pkg = isRecord2(root.package) ? root.package : root;
5022
+ const pkg = isRecord(root.package) ? root.package : root;
6709
5023
  const steps = Array.isArray(pkg.steps) ? pkg.steps : [];
6710
5024
  return steps.flatMap((step) => {
6711
- if (!isRecord2(step) || !isPackagedDatasetOutput(step.output)) return [];
5025
+ if (!isRecord(step) || !isPackagedDatasetOutput(step.output)) return [];
6712
5026
  const source = typeof step.output.path === "string" && step.output.path.trim() ? step.output.path.trim() : null;
6713
5027
  return source ? [
6714
5028
  {
@@ -6720,8 +5034,8 @@ function collectPackagedStepDatasetCandidates(statusOrResult) {
6720
5034
  });
6721
5035
  }
6722
5036
  function collectSerializedDatasetRowsInfos(statusOrResult) {
6723
- const root = isRecord2(statusOrResult) ? statusOrResult : null;
6724
- const result = root && "result" in root ? isRecord2(root.result) ? root.result : null : root?.kind === "play_run" || isRecord2(root?.package) ? null : root;
5037
+ const root = isRecord(statusOrResult) ? statusOrResult : null;
5038
+ const result = root && "result" in root ? isRecord(root.result) ? root.result : null : root?.kind === "play_run" || isRecord(root?.package) ? null : root;
6725
5039
  const candidates = [];
6726
5040
  if (result) {
6727
5041
  collectDatasetCandidates({
@@ -6729,7 +5043,7 @@ function collectSerializedDatasetRowsInfos(statusOrResult) {
6729
5043
  path: "result",
6730
5044
  output: candidates
6731
5045
  });
6732
- if (isRecord2(result.output)) {
5046
+ if (isRecord(result.output)) {
6733
5047
  collectDatasetCandidates({
6734
5048
  value: result.output,
6735
5049
  path: "result",
@@ -6776,8 +5090,8 @@ function extractCanonicalRowsInfo(statusOrResult) {
6776
5090
  }
6777
5091
 
6778
5092
  // src/cli/run-dataset-selection.ts
6779
- import { writeFileSync as writeFileSync3 } from "fs";
6780
- import { resolve as resolve3 } from "path";
5093
+ import { writeFileSync as writeFileSync2 } from "fs";
5094
+ import { resolve as resolve2 } from "path";
6781
5095
  var Run = class _Run {
6782
5096
  #datasets;
6783
5097
  constructor(input) {
@@ -6903,8 +5217,8 @@ var RunDataset = class _RunDataset {
6903
5217
  );
6904
5218
  }
6905
5219
  if (options.format === "json") {
6906
- const absolutePath = resolve3(outPath);
6907
- writeFileSync3(
5220
+ const absolutePath = resolve2(outPath);
5221
+ writeFileSync2(
6908
5222
  absolutePath,
6909
5223
  `${JSON.stringify(orderRunExportJson(this.rows), null, 2)}
6910
5224
  `,
@@ -6958,7 +5272,7 @@ function withReturnedDatasetAliases(runPackage, available) {
6958
5272
  for (const outputValue of Object.values(outputs)) {
6959
5273
  const output = recordValue(outputValue);
6960
5274
  if (output.kind !== "dataset") continue;
6961
- const alias = stringValue2(output.path);
5275
+ const alias = stringValue(output.path);
6962
5276
  if (!alias) continue;
6963
5277
  const canonical = resolveReturnedDataset(output, available);
6964
5278
  expanded.push(withDatasetAlias(canonical, alias));
@@ -6973,7 +5287,7 @@ function returnedRunDatasets(runPackage, available) {
6973
5287
  for (const outputValue of Object.values(outputs)) {
6974
5288
  const output = recordValue(outputValue);
6975
5289
  if (output.kind !== "dataset") continue;
6976
- const alias = stringValue2(output.path);
5290
+ const alias = stringValue(output.path);
6977
5291
  const info = resolveReturnedDataset(output, available);
6978
5292
  selected.push(alias ? withDatasetAlias(info, alias) : info);
6979
5293
  }
@@ -7004,8 +5318,8 @@ function withDatasetAlias(info, alias) {
7004
5318
  };
7005
5319
  }
7006
5320
  function resolveReturnedDataset(output, available) {
7007
- const datasetId = stringValue2(output.datasetId);
7008
- const path = stringValue2(output.dataset) ?? stringValue2(output.path);
5321
+ const datasetId = stringValue(output.datasetId);
5322
+ const path = stringValue(output.dataset) ?? stringValue(output.path);
7009
5323
  if (datasetId) {
7010
5324
  const identified = uniqueDatasetMatch(
7011
5325
  available.filter((info) => info.datasetId === datasetId),
@@ -7032,7 +5346,7 @@ function resolveReturnedDataset(output, available) {
7032
5346
  function recordValue(value) {
7033
5347
  return value && typeof value === "object" && !Array.isArray(value) ? value : {};
7034
5348
  }
7035
- function stringValue2(value) {
5349
+ function stringValue(value) {
7036
5350
  return typeof value === "string" && value.trim() ? value.trim() : null;
7037
5351
  }
7038
5352
 
@@ -7288,7 +5602,7 @@ function isInternalGlueStepId(stepId) {
7288
5602
  import { randomUUID } from "crypto";
7289
5603
  import { mkdtemp as mkdtemp2, realpath, rm as rm2 } from "fs/promises";
7290
5604
  import { tmpdir } from "os";
7291
- import { join as join4, resolve as resolve4 } from "path";
5605
+ import { join as join4, resolve as resolve3 } from "path";
7292
5606
 
7293
5607
  // ../plays/deploy/run-deployment.ts
7294
5608
  import { join as join3 } from "path";
@@ -7465,7 +5779,7 @@ var DeployApiClient = class {
7465
5779
  // ../plays/deploy/manifest.ts
7466
5780
  var import_picomatch = __toESM(require_picomatch2(), 1);
7467
5781
  import { readdir, readFile as readFile2, stat } from "fs/promises";
7468
- import { join, relative as relative2 } from "path";
5782
+ import { join, relative } from "path";
7469
5783
  var DEFAULT_PLAY_GLOBS = ["**/*.play.ts"];
7470
5784
  var DEFAULT_MONITOR_GLOBS = ["**/*.monitor.json"];
7471
5785
  var MAX_DISCOVERED_FILES = 200;
@@ -7566,7 +5880,7 @@ async function discoverDeploymentFiles(input) {
7566
5880
  continue;
7567
5881
  }
7568
5882
  if (!entry.isFile()) continue;
7569
- const relativePath = relative2(input.projectRoot, absolute);
5883
+ const relativePath = relative(input.projectRoot, absolute);
7570
5884
  if (matchers.some((match) => match(relativePath))) {
7571
5885
  found.push(relativePath);
7572
5886
  if (found.length > MAX_DISCOVERED_FILES) {
@@ -7906,7 +6220,7 @@ async function runDeployment(params, hooks) {
7906
6220
  throw lastError;
7907
6221
  }
7908
6222
  await new Promise(
7909
- (resolve7) => setTimeout(resolve7, hooks.checkRunRetryDelayMs ?? 1e3)
6223
+ (resolve6) => setTimeout(resolve6, hooks.checkRunRetryDelayMs ?? 1e3)
7910
6224
  );
7911
6225
  }
7912
6226
  }
@@ -8389,7 +6703,7 @@ async function runDeployment(params, hooks) {
8389
6703
  "Monitor jobs are still reconciling. Retrying this deployment will resume the same jobs."
8390
6704
  );
8391
6705
  }
8392
- await new Promise((resolve7) => setTimeout(resolve7, 1e3));
6706
+ await new Promise((resolve6) => setTimeout(resolve6, 1e3));
8393
6707
  for (let index = 0; index < monitorOutcomes.length; index += 1) {
8394
6708
  const outcome = monitorOutcomes[index];
8395
6709
  if (outcome.status !== "applying") continue;
@@ -8602,8 +6916,8 @@ function printResult2(input) {
8602
6916
  );
8603
6917
  }
8604
6918
  async function handlePlaysDeploy(directory, options) {
8605
- const root = await realpath(resolve4(directory ?? ".")).catch(() => {
8606
- throw new Error(`No such directory: ${resolve4(directory ?? ".")}`);
6919
+ const root = await realpath(resolve3(directory ?? ".")).catch(() => {
6920
+ throw new Error(`No such directory: ${resolve3(directory ?? ".")}`);
8607
6921
  });
8608
6922
  const { http, config } = getAuthedHttpClient();
8609
6923
  const deliveryId = `local:${randomUUID()}`;
@@ -8674,7 +6988,7 @@ async function handlePlaysDeploy(directory, options) {
8674
6988
 
8675
6989
  // src/cli/operations/play-run-options.ts
8676
6990
  import { existsSync, readFileSync } from "fs";
8677
- import { resolve as resolve5 } from "path";
6991
+ import { resolve as resolve4 } from "path";
8678
6992
 
8679
6993
  // ../play-runtime/fixture-behavior.ts
8680
6994
  var FIXTURE_BEHAVIOR_VERSION = 1;
@@ -9119,7 +7433,7 @@ function parsePlayRunHeaderFlag(raw) {
9119
7433
  function isBarePlayRunDebugFlag(args, index) {
9120
7434
  return args[index] === "--debug" && (args[index + 1] === void 0 || args[index + 1].startsWith("--"));
9121
7435
  }
9122
- function parseReferencedPlayTarget2(target) {
7436
+ function parseReferencedPlayTarget(target) {
9123
7437
  const trimmed = target.trim();
9124
7438
  const slashIndex = trimmed.indexOf("/");
9125
7439
  if (slashIndex <= 0 || slashIndex === trimmed.length - 1) {
@@ -9132,7 +7446,7 @@ function parseReferencedPlayTarget2(target) {
9132
7446
  };
9133
7447
  }
9134
7448
  function isFileTarget(target) {
9135
- return existsSync(resolve5(target));
7449
+ return existsSync(resolve4(target));
9136
7450
  }
9137
7451
  function looksLikeFilePath(target) {
9138
7452
  if (target.trim().toLowerCase().startsWith("prebuilt/")) {
@@ -9143,7 +7457,7 @@ function looksLikeFilePath(target) {
9143
7457
  }
9144
7458
  return target.includes("\\") || /\.(ts|js|mjs|play\.ts)$/.test(target);
9145
7459
  }
9146
- function parsePositiveInteger2(value, flagName) {
7460
+ function parsePositiveInteger(value, flagName) {
9147
7461
  const parsed = Number.parseInt(value, 10);
9148
7462
  if (!Number.isFinite(parsed) || parsed <= 0) {
9149
7463
  throw new Error(`${flagName} must be a positive integer.`);
@@ -9151,7 +7465,7 @@ function parsePositiveInteger2(value, flagName) {
9151
7465
  return parsed;
9152
7466
  }
9153
7467
  function parseJsonInput(raw, flag = "--input") {
9154
- const source = raw.startsWith("@") ? readFileSync(resolve5(raw.slice(1)), "utf-8") : raw;
7468
+ const source = raw.startsWith("@") ? readFileSync(resolve4(raw.slice(1)), "utf-8") : raw;
9155
7469
  let parsed;
9156
7470
  try {
9157
7471
  parsed = JSON.parse(source);
@@ -9243,7 +7557,7 @@ function parsePlayRunOptions(args, initialInput = null) {
9243
7557
  continue;
9244
7558
  }
9245
7559
  if (arg === "--name" && args[index + 1]) {
9246
- playName = parseReferencedPlayTarget2(args[++index]).playName;
7560
+ playName = parseReferencedPlayTarget(args[++index]).playName;
9247
7561
  continue;
9248
7562
  }
9249
7563
  if ((arg === "--input" || arg === "-i") && args[index + 1]) {
@@ -9310,7 +7624,7 @@ function parsePlayRunOptions(args, initialInput = null) {
9310
7624
  "--max-concurrent-external-calls requires a positive whole number."
9311
7625
  );
9312
7626
  }
9313
- maxConcurrentExternalCalls = parsePositiveInteger2(
7627
+ maxConcurrentExternalCalls = parsePositiveInteger(
9314
7628
  value,
9315
7629
  "--max-concurrent-external-calls"
9316
7630
  );
@@ -9328,7 +7642,7 @@ function parsePlayRunOptions(args, initialInput = null) {
9328
7642
  "--max-concurrent-rows requires a positive whole number."
9329
7643
  );
9330
7644
  }
9331
- maxConcurrentRows = parsePositiveInteger2(value, "--max-concurrent-rows");
7645
+ maxConcurrentRows = parsePositiveInteger(value, "--max-concurrent-rows");
9332
7646
  resolveMaxConcurrentRows(maxConcurrentRows);
9333
7647
  index += 1;
9334
7648
  continue;
@@ -9376,7 +7690,7 @@ function parsePlayRunOptions(args, initialInput = null) {
9376
7690
  );
9377
7691
  }
9378
7692
  if ((arg === "--tail-timeout-ms" || arg === "--timeout-ms") && args[index + 1]) {
9379
- waitTimeoutMs = parsePositiveInteger2(args[++index], arg);
7693
+ waitTimeoutMs = parsePositiveInteger(args[++index], arg);
9380
7694
  continue;
9381
7695
  }
9382
7696
  if (arg === "--debug" && args[index + 1] && !args[index + 1].startsWith("--")) {
@@ -9424,7 +7738,7 @@ function parsePlayRunOptions(args, initialInput = null) {
9424
7738
  if (isFileTarget(arg) || looksLikeFilePath(arg)) {
9425
7739
  filePath = arg;
9426
7740
  } else {
9427
- playName = parseReferencedPlayTarget2(arg).playName;
7741
+ playName = parseReferencedPlayTarget(arg).playName;
9428
7742
  }
9429
7743
  continue;
9430
7744
  }
@@ -9512,7 +7826,7 @@ function resolvePlayRunCliOptions(target, options, inputArgs = []) {
9512
7826
  );
9513
7827
  const resolvedTarget = file !== void 0 ? { kind: "file", path: file } : name !== void 0 ? {
9514
7828
  kind: "name",
9515
- name: parseReferencedPlayTarget2(name).playName
7829
+ name: parseReferencedPlayTarget(name).playName
9516
7830
  } : base.target;
9517
7831
  const revisionId = stringOption(options.revisionId, "--revision-id") ?? base.revisionId;
9518
7832
  const selectors = [
@@ -9616,12 +7930,12 @@ function resolvePlayRunCliOptions(target, options, inputArgs = []) {
9616
7930
  }
9617
7931
 
9618
7932
  // src/plays/authoring-graph-path.ts
9619
- import { dirname, isAbsolute as isAbsolute2, join as join5, relative as relative3 } from "path";
7933
+ import { dirname, isAbsolute, join as join5, relative as relative2 } from "path";
9620
7934
  function playAuthoringGraphPath(parent, filePath) {
9621
- if (isAbsolute2(parent.artifact.entryFile)) return filePath;
7935
+ if (isAbsolute(parent.artifact.entryFile)) return filePath;
9622
7936
  return join5(
9623
7937
  dirname(parent.artifact.entryFile),
9624
- relative3(dirname(parent.filePath), filePath)
7938
+ relative2(dirname(parent.filePath), filePath)
9625
7939
  ).replaceAll("\\", "/");
9626
7940
  }
9627
7941
 
@@ -9696,7 +8010,7 @@ async function removeRunIdTempFile(path) {
9696
8010
  }
9697
8011
  }
9698
8012
  async function preflightRunIdFile(path) {
9699
- const destination = resolve6(path);
8013
+ const destination = resolve5(path);
9700
8014
  if (await pathExistsIncludingSymlink(destination)) {
9701
8015
  throw new Error(
9702
8016
  `--run-id-file destination already exists: ${destination}. Choose a new path so this run cannot overwrite another run identity.`
@@ -9811,9 +8125,9 @@ function traceCliSync(phase, fields2, run) {
9811
8125
  }
9812
8126
  }
9813
8127
  function sleep(ms) {
9814
- return new Promise((resolve7) => setTimeout(resolve7, ms));
8128
+ return new Promise((resolve6) => setTimeout(resolve6, ms));
9815
8129
  }
9816
- function parseReferencedPlayTarget3(target) {
8130
+ function parseReferencedPlayTarget2(target) {
9817
8131
  const trimmed = target.trim();
9818
8132
  const slashIndex = trimmed.indexOf("/");
9819
8133
  if (slashIndex <= 0 || slashIndex === trimmed.length - 1) {
@@ -9860,7 +8174,7 @@ function playSuggestionReference(play) {
9860
8174
  return ownerSlug ? `${ownerSlug}/${play.name}` : play.name;
9861
8175
  }
9862
8176
  function scorePlayReferenceSuggestion(requested, play) {
9863
- const parsed = parseReferencedPlayTarget3(requested);
8177
+ const parsed = parseReferencedPlayTarget2(requested);
9864
8178
  const requestedTrimmed = requested.trim();
9865
8179
  const requestedRef = requestedTrimmed.toLowerCase();
9866
8180
  const requestedName = parsed.unqualifiedPlayName;
@@ -9938,7 +8252,7 @@ function rankPlayReferenceSuggestions(input) {
9938
8252
  }).slice(0, input.limit ?? 5);
9939
8253
  }
9940
8254
  function searchQueryForMissingPlayReference(target) {
9941
- return parseReferencedPlayTarget3(target).unqualifiedPlayName.replace(/[-_./]+/g, " ").replace(/\s+/g, " ").trim();
8255
+ return parseReferencedPlayTarget2(target).unqualifiedPlayName.replace(/[-_./]+/g, " ").replace(/\s+/g, " ").trim();
9942
8256
  }
9943
8257
  function buildPlayReferenceNotFoundMessage(input) {
9944
8258
  const lines = [`Play not found: ${input.requested}`];
@@ -10015,7 +8329,7 @@ async function isMissingRunPlayReferenceError(input) {
10015
8329
  }
10016
8330
  try {
10017
8331
  await input.client.getPlay(
10018
- parseReferencedPlayTarget3(input.playName).playName
8332
+ parseReferencedPlayTarget2(input.playName).playName
10019
8333
  );
10020
8334
  return false;
10021
8335
  } catch (lookupError) {
@@ -10023,7 +8337,7 @@ async function isMissingRunPlayReferenceError(input) {
10023
8337
  }
10024
8338
  }
10025
8339
  async function assertCanonicalNamedPlayReference(client, target, options = {}) {
10026
- const parsed = parseReferencedPlayTarget3(target);
8340
+ const parsed = parseReferencedPlayTarget2(target);
10027
8341
  let detail;
10028
8342
  try {
10029
8343
  detail = await client.getPlay(
@@ -10060,10 +8374,10 @@ function formatPlayListReference(play) {
10060
8374
  return play.reference || play.name;
10061
8375
  }
10062
8376
  function defaultMaterializedPlayPath(reference) {
10063
- return resolve6(defaultStarterPlayPath(reference));
8377
+ return resolve5(defaultStarterPlayPath(reference));
10064
8378
  }
10065
8379
  function defaultStarterPlayPath(reference) {
10066
- const playName = parseReferencedPlayTarget3(reference).unqualifiedPlayName;
8380
+ const playName = parseReferencedPlayTarget2(reference).unqualifiedPlayName;
10067
8381
  const safeName = playName.trim().toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
10068
8382
  return `./${safeName || "play"}.play.ts`;
10069
8383
  }
@@ -10093,23 +8407,23 @@ function materializeRemotePlaySource(input) {
10093
8407
  `Play ${input.playName} has ${files.length} source files. Use --out <directory> to write the complete bundle.`
10094
8408
  );
10095
8409
  }
10096
- const outputDirectory = resolve6(input.outPath);
8410
+ const outputDirectory = resolve5(input.outPath);
10097
8411
  let created = 0;
10098
8412
  let updated = 0;
10099
8413
  for (const [logicalPath, sourceCode] of files) {
10100
- const outputPath2 = resolve6(outputDirectory, logicalPath);
10101
- const outputRelativePath = relative4(outputDirectory, outputPath2);
10102
- if (!outputRelativePath || outputRelativePath.startsWith("..") || isAbsolute3(outputRelativePath)) {
8414
+ const outputPath2 = resolve5(outputDirectory, logicalPath);
8415
+ const outputRelativePath = relative3(outputDirectory, outputPath2);
8416
+ if (!outputRelativePath || outputRelativePath.startsWith("..") || isAbsolute2(outputRelativePath)) {
10103
8417
  throw new Error(
10104
8418
  `Refusing to materialize unsafe Play source path ${JSON.stringify(logicalPath)}.`
10105
8419
  );
10106
8420
  }
10107
8421
  mkdirSync(dirname2(outputPath2), { recursive: true });
10108
8422
  if (!existsSync2(outputPath2)) {
10109
- writeFileSync4(outputPath2, sourceCode, "utf-8");
8423
+ writeFileSync3(outputPath2, sourceCode, "utf-8");
10110
8424
  created += 1;
10111
8425
  } else if (readFileSync2(outputPath2, "utf-8") !== sourceCode) {
10112
- writeFileSync4(outputPath2, sourceCode, "utf-8");
8426
+ writeFileSync3(outputPath2, sourceCode, "utf-8");
10113
8427
  updated += 1;
10114
8428
  }
10115
8429
  }
@@ -10126,10 +8440,10 @@ function materializeRemotePlaySource(input) {
10126
8440
  if (existingSource === entrySource) {
10127
8441
  return { path: outputPath, status: "unchanged", created: false };
10128
8442
  }
10129
- writeFileSync4(outputPath, entrySource, "utf-8");
8443
+ writeFileSync3(outputPath, entrySource, "utf-8");
10130
8444
  return { path: outputPath, status: "updated", created: false };
10131
8445
  }
10132
- writeFileSync4(outputPath, entrySource, "utf-8");
8446
+ writeFileSync3(outputPath, entrySource, "utf-8");
10133
8447
  return { path: outputPath, status: "created", created: true };
10134
8448
  }
10135
8449
  function formatLoadedPlayMessage(materializedFile) {
@@ -10154,7 +8468,7 @@ To make your own version:
10154
8468
  );
10155
8469
  }
10156
8470
  async function ensureEditableRemotePlay(client, target) {
10157
- const parsed = parseReferencedPlayTarget3(target);
8471
+ const parsed = parseReferencedPlayTarget2(target);
10158
8472
  const detail = await client.getPlay(parsed.playName);
10159
8473
  if (detail.play.ownerType === "deepline") {
10160
8474
  throw buildReadonlyPrebuiltPlayError(formatPlayReference(detail.play));
@@ -10174,7 +8488,7 @@ function extractPlayName(code, filePath) {
10174
8488
  throw buildMissingDefinePlayError(filePath);
10175
8489
  }
10176
8490
  function isFileTarget2(target) {
10177
- return existsSync2(resolve6(target));
8491
+ return existsSync2(resolve5(target));
10178
8492
  }
10179
8493
  function looksLikeRunId(target) {
10180
8494
  return /^play\/[^/]+\/run\/[^/]+/.test(target.trim());
@@ -10195,7 +8509,7 @@ function looksLikeFilePath2(target) {
10195
8509
  }
10196
8510
  return target.includes("\\") || /\.(ts|js|mjs|play\.ts)$/.test(target);
10197
8511
  }
10198
- function parsePositiveInteger3(value, flagName) {
8512
+ function parsePositiveInteger2(value, flagName) {
10199
8513
  const parsed = Number.parseInt(value, 10);
10200
8514
  if (!Number.isFinite(parsed) || parsed <= 0) {
10201
8515
  throw new Error(`${flagName} must be a positive integer.`);
@@ -10205,7 +8519,7 @@ function parsePositiveInteger3(value, flagName) {
10205
8519
  function isLocalFilePathValue(value) {
10206
8520
  if (typeof value !== "string" || !value.trim()) return false;
10207
8521
  if (/^[a-z][a-z0-9+.-]*:\/\//i.test(value.trim())) return false;
10208
- return existsSync2(resolve6(value));
8522
+ return existsSync2(resolve5(value));
10209
8523
  }
10210
8524
  function inputContainsLocalFilePath(value) {
10211
8525
  if (isLocalFilePathValue(value)) {
@@ -10251,7 +8565,7 @@ function collectLocalFileInputRefs(value, inputPath, key, out) {
10251
8565
  const looksLikeFile = /\.[a-z0-9]{1,8}$/i.test(trimmed);
10252
8566
  if (keyIsCsvData) {
10253
8567
  out.push({ inputPath, value: trimmed, isCsvData: true });
10254
- } else if (endsWithCsv || looksLikeFile && existsSync2(resolve6(trimmed))) {
8568
+ } else if (endsWithCsv || looksLikeFile && existsSync2(resolve5(trimmed))) {
10255
8569
  out.push({ inputPath, value: trimmed, isCsvData: false });
10256
8570
  }
10257
8571
  return;
@@ -10293,7 +8607,7 @@ function preflightLocalFileInputs(runtimeInput) {
10293
8607
  collectLocalFileInputRefs(value, key, key, refs);
10294
8608
  }
10295
8609
  for (const ref of refs) {
10296
- const absolutePath = resolve6(ref.value);
8610
+ const absolutePath = resolve5(ref.value);
10297
8611
  if (!existsSync2(absolutePath)) {
10298
8612
  throw new DeeplineError(
10299
8613
  `Input ${ref.inputPath} references a local file that does not exist: ${ref.value} (resolved to ${absolutePath}). No run was created.`,
@@ -10304,7 +8618,7 @@ function preflightLocalFileInputs(runtimeInput) {
10304
8618
  }
10305
8619
  let stat2;
10306
8620
  try {
10307
- stat2 = statSync2(absolutePath);
8621
+ stat2 = statSync(absolutePath);
10308
8622
  } catch (error) {
10309
8623
  throw new DeeplineError(
10310
8624
  `Input ${ref.inputPath} references a local file that is not readable: ${ref.value} (${error instanceof Error ? error.message : String(error)}). No run was created.`,
@@ -10358,7 +8672,7 @@ async function stageFileInputArgs(input) {
10358
8672
  codec: NODE_STAGED_FILE_CODEC,
10359
8673
  resolveLocalFile: (value) => {
10360
8674
  if (!isLocalFilePathValue(value)) return null;
10361
- const absolutePath = resolve6(value);
8675
+ const absolutePath = resolve5(value);
10362
8676
  return {
10363
8677
  logicalPath: basename(absolutePath),
10364
8678
  read: async () => readFileSync2(absolutePath)
@@ -10381,9 +8695,9 @@ function stageFile(logicalPath, absolutePath) {
10381
8695
  }
10382
8696
  function normalizePlayPath(filePath) {
10383
8697
  try {
10384
- return realpathSync.native(resolve6(filePath));
8698
+ return realpathSync.native(resolve5(filePath));
10385
8699
  } catch {
10386
- return resolve6(filePath);
8700
+ return resolve5(filePath);
10387
8701
  }
10388
8702
  }
10389
8703
  var PlayBundleGraphError = class extends Error {
@@ -13473,7 +11787,7 @@ async function resolvePlayRunOutputStatus(input) {
13473
11787
  }
13474
11788
  var RUN_EXPORT_PAGE_SIZE = 5e3;
13475
11789
  function runExportRetryCommand(runId, outPath, datasetPath, options = {}) {
13476
- return `deepline runs export ${runId}${datasetPath ? ` --dataset ${shellQuote(datasetPath)}` : ""} --out ${shellQuote(resolve6(outPath))}${options.format === "json" ? " --format json" : ""}`;
11790
+ return `deepline runs export ${runId}${datasetPath ? ` --dataset ${shellQuote(datasetPath)}` : ""} --out ${shellQuote(resolve5(outPath))}${options.format === "json" ? " --format json" : ""}`;
13477
11791
  }
13478
11792
  function extractRunPlayName(status) {
13479
11793
  const run = status.run;
@@ -13999,7 +12313,7 @@ function extractPlayValidationErrors(value) {
13999
12313
  if (value instanceof DeeplineError) {
14000
12314
  return extractPlayValidationErrors(value.details);
14001
12315
  }
14002
- if (!isRecord3(value)) {
12316
+ if (!isRecord2(value)) {
14003
12317
  return [];
14004
12318
  }
14005
12319
  const directErrors = stringArrayField(value, "errors");
@@ -14390,34 +12704,34 @@ function formatPlayRuntimeLimit(runtimeLimit) {
14390
12704
  if (seconds % 60 === 0) return `${seconds / 60} min`;
14391
12705
  return `${seconds} sec`;
14392
12706
  }
14393
- function isRecord3(value) {
12707
+ function isRecord2(value) {
14394
12708
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
14395
12709
  }
14396
- function stringValue3(value) {
12710
+ function stringValue2(value) {
14397
12711
  return typeof value === "string" ? value.trim() : "";
14398
12712
  }
14399
12713
  function asArray(value) {
14400
12714
  return Array.isArray(value) ? value : [];
14401
12715
  }
14402
- function extractionEntries2(value) {
14403
- if (Array.isArray(value)) return value.filter(isRecord3);
14404
- if (!isRecord3(value)) return [];
12716
+ function extractionEntries(value) {
12717
+ if (Array.isArray(value)) return value.filter(isRecord2);
12718
+ if (!isRecord2(value)) return [];
14405
12719
  return Object.entries(value).map(
14406
- ([name, entry]) => isRecord3(entry) ? { name, ...entry } : { name }
12720
+ ([name, entry]) => isRecord2(entry) ? { name, ...entry } : { name }
14407
12721
  );
14408
12722
  }
14409
12723
  function firstRawPath(entry) {
14410
- const details = isRecord3(entry.details) ? entry.details : {};
12724
+ const details = isRecord2(entry.details) ? entry.details : {};
14411
12725
  const paths = [
14412
12726
  ...asArray(details.rawToolOutputPaths),
14413
12727
  ...asArray(details.raw_tool_output_paths),
14414
12728
  ...asArray(details.candidatePaths),
14415
12729
  ...asArray(details.candidate_paths)
14416
- ].map(stringValue3).filter(Boolean);
12730
+ ].map(stringValue2).filter(Boolean);
14417
12731
  return paths[0];
14418
12732
  }
14419
12733
  function checkHintExpression(value) {
14420
- return stringValue3(value).replace(/^toolExecutionResult\./, "result.");
12734
+ return stringValue2(value).replace(/^toolExecutionResult\./, "result.");
14421
12735
  }
14422
12736
  function checkHintRawPath(value) {
14423
12737
  return value?.startsWith("toolResponse.rawV2") ? value.replace(/^toolResponse\./, "result.toolResponse.") : void 0;
@@ -14425,14 +12739,14 @@ function checkHintRawPath(value) {
14425
12739
  function collectStaticPipelineToolIds(staticPipeline) {
14426
12740
  const seen = /* @__PURE__ */ new Set();
14427
12741
  const visitPipeline = (pipeline) => {
14428
- if (!isRecord3(pipeline)) return;
12742
+ if (!isRecord2(pipeline)) return;
14429
12743
  for (const step of [
14430
12744
  ...asArray(pipeline.stages),
14431
12745
  ...asArray(pipeline.substeps)
14432
12746
  ]) {
14433
- if (!isRecord3(step)) continue;
12747
+ if (!isRecord2(step)) continue;
14434
12748
  if (step.type === "tool") {
14435
- const toolId = stringValue3(step.toolId) || stringValue3(step.tool);
12749
+ const toolId = stringValue2(step.toolId) || stringValue2(step.tool);
14436
12750
  if (toolId) seen.add(toolId);
14437
12751
  }
14438
12752
  if (step.type === "play_call") {
@@ -14444,20 +12758,20 @@ function collectStaticPipelineToolIds(staticPipeline) {
14444
12758
  return [...seen].sort();
14445
12759
  }
14446
12760
  function toolGetterHintFromMetadata(toolId, tool) {
14447
- const usageGuidance = isRecord3(tool.usageGuidance) ? tool.usageGuidance : {};
14448
- const resultGuidance = isRecord3(usageGuidance.toolExecutionResult) ? usageGuidance.toolExecutionResult : isRecord3(usageGuidance.tool_execution_result) ? usageGuidance.tool_execution_result : {};
14449
- const toolResponse = isRecord3(resultGuidance.toolResponse) ? resultGuidance.toolResponse : isRecord3(resultGuidance.tool_response) ? resultGuidance.tool_response : {};
14450
- const lists = extractionEntries2(
12761
+ const usageGuidance = isRecord2(tool.usageGuidance) ? tool.usageGuidance : {};
12762
+ const resultGuidance = isRecord2(usageGuidance.toolExecutionResult) ? usageGuidance.toolExecutionResult : isRecord2(usageGuidance.tool_execution_result) ? usageGuidance.tool_execution_result : {};
12763
+ const toolResponse = isRecord2(resultGuidance.toolResponse) ? resultGuidance.toolResponse : isRecord2(resultGuidance.tool_response) ? resultGuidance.tool_response : {};
12764
+ const lists = extractionEntries(
14451
12765
  resultGuidance.extractedLists ?? resultGuidance.extracted_lists
14452
12766
  ).map((entry) => ({
14453
- name: stringValue3(entry.name),
12767
+ name: stringValue2(entry.name),
14454
12768
  expression: checkHintExpression(entry.expression),
14455
12769
  raw: checkHintRawPath(firstRawPath(entry))
14456
12770
  })).filter((entry) => entry.name && entry.expression);
14457
- const values = extractionEntries2(
12771
+ const values = extractionEntries(
14458
12772
  resultGuidance.extractedValues ?? resultGuidance.extracted_values
14459
12773
  ).map((entry) => ({
14460
- name: stringValue3(entry.name),
12774
+ name: stringValue2(entry.name),
14461
12775
  expression: checkHintExpression(entry.expression),
14462
12776
  raw: checkHintRawPath(firstRawPath(entry))
14463
12777
  })).filter((entry) => entry.name && entry.expression);
@@ -14584,7 +12898,7 @@ async function handlePlayCheck(args) {
14584
12898
  command: "check"
14585
12899
  });
14586
12900
  const play = await client.describePlay(
14587
- parseReferencedPlayTarget3(options.target).playName,
12901
+ parseReferencedPlayTarget2(options.target).playName,
14588
12902
  { compact: true }
14589
12903
  );
14590
12904
  const result = {
@@ -14614,7 +12928,7 @@ async function handlePlayCheck(args) {
14614
12928
  });
14615
12929
  return 0;
14616
12930
  } catch (error) {
14617
- const resolved = resolve6(options.target);
12931
+ const resolved = resolve5(options.target);
14618
12932
  const message = error instanceof Error && error.message ? error.message : `File not found: ${resolved}`;
14619
12933
  if (options.jsonOutput) {
14620
12934
  printCommandEnvelope(
@@ -14635,7 +12949,7 @@ async function handlePlayCheck(args) {
14635
12949
  return 1;
14636
12950
  }
14637
12951
  }
14638
- const absolutePlayPath = resolve6(options.target);
12952
+ const absolutePlayPath = resolve5(options.target);
14639
12953
  const sourceCode = readFileSync2(absolutePlayPath, "utf-8");
14640
12954
  const exportNames = resolvePlayCheckExportNames(sourceCode);
14641
12955
  const outcomes = [];
@@ -14685,7 +12999,7 @@ function artifactForProductionCompatibilityCheck(artifact) {
14685
12999
  "DEEPLINE_PROD_CHECK_AUTHORING_CONTRACT_EDITION must be a positive integer."
14686
13000
  );
14687
13001
  }
14688
- const compatibility = isRecord3(artifact.compatibility) ? artifact.compatibility : {};
13002
+ const compatibility = isRecord2(artifact.compatibility) ? artifact.compatibility : {};
14689
13003
  return {
14690
13004
  ...artifact,
14691
13005
  compatibility: {
@@ -14755,7 +13069,7 @@ async function handleFileBackedRun(options, hooks) {
14755
13069
  }
14756
13070
  let client;
14757
13071
  const progress = getActiveCliProgress() ?? createCliProgress(!options.jsonOutput);
14758
- const absolutePlayPath = resolve6(options.target.path);
13072
+ const absolutePlayPath = resolve5(options.target.path);
14759
13073
  progress.phase("compiling play");
14760
13074
  const sourceCode = traceCliSync(
14761
13075
  "cli.play_file_read_source",
@@ -15164,7 +13478,7 @@ async function handlePlayRun(args, hooks) {
15164
13478
  const parsedOptions = Array.isArray(args) ? parsePlayRunOptions(args) : args;
15165
13479
  const options = parsedOptions.runIdFile ? {
15166
13480
  ...parsedOptions,
15167
- runIdFile: parsedOptions.dryRun ? resolve6(parsedOptions.runIdFile) : await preflightRunIdFile(parsedOptions.runIdFile)
13481
+ runIdFile: parsedOptions.dryRun ? resolve5(parsedOptions.runIdFile) : await preflightRunIdFile(parsedOptions.runIdFile)
15168
13482
  } : parsedOptions;
15169
13483
  const runHooks = options.runIdFile ? {
15170
13484
  ...hooks,
@@ -15197,7 +13511,7 @@ async function handlePlayRun(args, hooks) {
15197
13511
  if (isFileTarget2(options.target.path)) {
15198
13512
  return handleFileBackedRun(options, runHooks);
15199
13513
  }
15200
- const resolved = resolve6(options.target.path);
13514
+ const resolved = resolve5(options.target.path);
15201
13515
  console.error(`File not found: ${resolved}`);
15202
13516
  const dir = dirname2(resolved);
15203
13517
  if (existsSync2(dir)) {
@@ -15958,11 +14272,11 @@ async function handleRunLogs(args) {
15958
14272
  continue;
15959
14273
  }
15960
14274
  if (arg === "--limit" && args[index + 1]) {
15961
- limit = parsePositiveInteger3(args[++index], "--limit");
14275
+ limit = parsePositiveInteger2(args[++index], "--limit");
15962
14276
  continue;
15963
14277
  }
15964
14278
  if (arg === "--out" && args[index + 1]) {
15965
- outPath = resolve6(args[++index]);
14279
+ outPath = resolve5(args[++index]);
15966
14280
  continue;
15967
14281
  }
15968
14282
  if (arg === "--cursor" && args[index + 1]) {
@@ -15997,7 +14311,7 @@ async function handleRunLogs(args) {
15997
14311
  if (outPath) {
15998
14312
  const result2 = await client.runs.logs(runId, { all: true });
15999
14313
  const logs = result2.entries.filter((line) => logLevelReaches(classifyLogLine(line).level, logLevel)).map((line) => classifyLogLine(line).line);
16000
- writeFileSync4(outPath, `${logs.join("\n")}${logs.length > 0 ? "\n" : ""}`);
14314
+ writeFileSync3(outPath, `${logs.join("\n")}${logs.length > 0 ? "\n" : ""}`);
16001
14315
  printCommandEnvelope(
16002
14316
  {
16003
14317
  runId: result2.runId,
@@ -16483,7 +14797,7 @@ async function handleRunExport(args) {
16483
14797
  for (let index = 0; index < args.length; index += 1) {
16484
14798
  const arg = args[index];
16485
14799
  if (arg === "--out" && args[index + 1]) {
16486
- outPath = resolve6(args[++index]);
14800
+ outPath = resolve5(args[++index]);
16487
14801
  continue;
16488
14802
  }
16489
14803
  if (arg === "--dataset" && args[index + 1]) {
@@ -16491,11 +14805,11 @@ async function handleRunExport(args) {
16491
14805
  continue;
16492
14806
  }
16493
14807
  if (arg === "--metadata-out" && args[index + 1]) {
16494
- metadataOutPath = resolve6(args[++index]);
14808
+ metadataOutPath = resolve5(args[++index]);
16495
14809
  }
16496
14810
  if (arg === "--format") format = args[++index] ?? "";
16497
14811
  if (arg === "--timeout-ms") {
16498
- waitTimeoutMs = parsePositiveInteger3(args[++index] ?? "", arg);
14812
+ waitTimeoutMs = parsePositiveInteger2(args[++index] ?? "", arg);
16499
14813
  if (!wait) {
16500
14814
  throw new DeeplineError(
16501
14815
  "--timeout-ms requires --wait.",
@@ -16625,7 +14939,7 @@ async function handleRunExport(args) {
16625
14939
  payload.actions
16626
14940
  );
16627
14941
  if (metadataOutPath) {
16628
- writeFileSync4(
14942
+ writeFileSync3(
16629
14943
  metadataOutPath,
16630
14944
  `${JSON.stringify(payload, null, 2)}
16631
14945
  `,
@@ -16676,7 +14990,7 @@ async function handlePlayGet(args) {
16676
14990
  for (let index = 1; index < args.length; index += 1) {
16677
14991
  const arg = args[index];
16678
14992
  if (arg === "--out" && args[index + 1]) {
16679
- outPath = resolve6(args[++index]);
14993
+ outPath = resolve5(args[++index]);
16680
14994
  }
16681
14995
  if (arg === "--revision") {
16682
14996
  const rawVersion = args[++index];
@@ -16697,7 +15011,7 @@ async function handlePlayGet(args) {
16697
15011
  );
16698
15012
  return 2;
16699
15013
  }
16700
- const playName = isFileTarget2(target) ? extractPlayName(readFileSync2(resolve6(target), "utf-8"), resolve6(target)) : parseReferencedPlayTarget3(target).playName;
15014
+ const playName = isFileTarget2(target) ? extractPlayName(readFileSync2(resolve5(target), "utf-8"), resolve5(target)) : parseReferencedPlayTarget2(target).playName;
16701
15015
  const includeSource = sourceOutput || outPath !== null;
16702
15016
  const detail = isFileTarget2(target) ? await client.getPlay(
16703
15017
  playName,
@@ -16810,7 +15124,7 @@ async function handlePlayVersions(args) {
16810
15124
  command: "versions"
16811
15125
  });
16812
15126
  const versions = await client.listPlayVersions(
16813
- parseReferencedPlayTarget3(playName).playName
15127
+ parseReferencedPlayTarget2(playName).playName
16814
15128
  );
16815
15129
  if (jsonOutput) {
16816
15130
  printCompactJson({ versions });
@@ -16970,7 +15284,7 @@ async function handlePlayPin(args, pinned) {
16970
15284
  );
16971
15285
  return 2;
16972
15286
  }
16973
- const parsedTarget = parseReferencedPlayTarget3(target);
15287
+ const parsedTarget = parseReferencedPlayTarget2(target);
16974
15288
  if (parsedTarget.ownerSlug) {
16975
15289
  console.error(
16976
15290
  `deepline plays ${pinned ? "pin" : "unpin"} accepts an org-owned Play identifier without a namespace. Use "${parsedTarget.unqualifiedPlayName}" instead of "${target}".`
@@ -16989,12 +15303,12 @@ async function handlePlayPin(args, pinned) {
16989
15303
  return 0;
16990
15304
  }
16991
15305
  function csvColumnLines(csvInput) {
16992
- const rowSchema = isRecord3(csvInput.rowInputSchema) ? csvInput.rowInputSchema : {};
16993
- const columns = isRecord3(rowSchema.properties) ? Object.keys(rowSchema.properties) : [];
15306
+ const rowSchema = isRecord2(csvInput.rowInputSchema) ? csvInput.rowInputSchema : {};
15307
+ const columns = isRecord2(rowSchema.properties) ? Object.keys(rowSchema.properties) : [];
16994
15308
  const required = new Set(
16995
15309
  Array.isArray(rowSchema.required) ? rowSchema.required.map(String) : []
16996
15310
  );
16997
- const defaults = isRecord3(csvInput.defaultColumns) ? csvInput.defaultColumns : {};
15311
+ const defaults = isRecord2(csvInput.defaultColumns) ? csvInput.defaultColumns : {};
16998
15312
  return [
16999
15313
  ...columns.map((column) => {
17000
15314
  const headers = [defaults[column]].flat().filter((header) => header && header !== column);
@@ -17007,7 +15321,7 @@ function describedPlay(play) {
17007
15321
  const reference = formatPlayListReference(play);
17008
15322
  const starter = play.cloneEditStarter ?? buildCloneEditStarter(play);
17009
15323
  const csv = play.csvInput ?? {};
17010
- const headers = isRecord3(csv.defaultColumns) ? csv.defaultColumns : {};
15324
+ const headers = isRecord2(csv.defaultColumns) ? csv.defaultColumns : {};
17011
15325
  const rowInputs = schemaFields(csv.rowInputSchema).map((field) => {
17012
15326
  const header = [headers[field.name]].flat().filter((name) => name && name !== field.name).join(" or ");
17013
15327
  return header ? {
@@ -17016,7 +15330,7 @@ function describedPlay(play) {
17016
15330
  } : field;
17017
15331
  });
17018
15332
  const rowOutput = play.rowOutputSchema ?? {};
17019
- const added = isRecord3(rowOutput.addedColumns) ? rowOutput.addedColumns : {};
15333
+ const added = isRecord2(rowOutput.addedColumns) ? rowOutput.addedColumns : {};
17020
15334
  const rowOutputs = schemaFields(
17021
15335
  Object.keys(added).length ? { properties: added } : rowOutput
17022
15336
  ).map((field) => ({ ...field, required: true }));
@@ -17195,7 +15509,7 @@ async function handlePlayDescribe(args) {
17195
15509
  const definedName = isFileTarget2(playName) ? (() => {
17196
15510
  try {
17197
15511
  return extractPlayName(
17198
- readFileSync2(resolve6(playName), "utf-8"),
15512
+ readFileSync2(resolve5(playName), "utf-8"),
17199
15513
  playName
17200
15514
  );
17201
15515
  } catch {
@@ -17226,7 +15540,7 @@ async function handlePlayDescribe(args) {
17226
15540
  command: "describe"
17227
15541
  });
17228
15542
  const play = await client.describePlay(
17229
- parseReferencedPlayTarget3(playName).playName,
15543
+ parseReferencedPlayTarget2(playName).playName,
17230
15544
  {
17231
15545
  compact: args.includes("--compact")
17232
15546
  }
@@ -17258,7 +15572,7 @@ async function handlePlaySave(args) {
17258
15572
  graph = await traceCliSpan(
17259
15573
  "cli.play_save_bundle_graph",
17260
15574
  { targetKind: "file" },
17261
- () => collectBundledPlayGraph(resolve6(options.target))
15575
+ () => collectBundledPlayGraph(resolve5(options.target))
17262
15576
  );
17263
15577
  assertPlayGraphAuthoring(graph);
17264
15578
  } catch (error) {
@@ -17383,7 +15697,7 @@ async function handlePlayPublish(args) {
17383
15697
  graph = await traceCliSpan(
17384
15698
  "cli.play_publish_bundle_graph",
17385
15699
  { targetKind: "file" },
17386
- () => collectBundledPlayGraph(resolve6(playName))
15700
+ () => collectBundledPlayGraph(resolve5(playName))
17387
15701
  );
17388
15702
  assertPlayGraphAuthoring(graph);
17389
15703
  } catch (error) {
@@ -17527,7 +15841,7 @@ async function handlePlayPublish(args) {
17527
15841
  printCompactJson(result2);
17528
15842
  return 0;
17529
15843
  }
17530
- const resolvedName = parseReferencedPlayTarget3(playName).playName;
15844
+ const resolvedName = parseReferencedPlayTarget2(playName).playName;
17531
15845
  if (useLatest) {
17532
15846
  const versions = await client.listPlayVersions(resolvedName);
17533
15847
  const latest = versions[0];
@@ -17591,7 +15905,7 @@ async function handlePlayDelete(args) {
17591
15905
  const client = new DeeplineClient();
17592
15906
  let detail;
17593
15907
  try {
17594
- detail = await client.getPlay(parseReferencedPlayTarget3(playName).playName);
15908
+ detail = await client.getPlay(parseReferencedPlayTarget2(playName).playName);
17595
15909
  } catch (error) {
17596
15910
  console.error(error instanceof Error ? error.message : String(error));
17597
15911
  return 5;
@@ -17602,7 +15916,7 @@ async function handlePlayDelete(args) {
17602
15916
  );
17603
15917
  return 2;
17604
15918
  }
17605
- const resolvedName = parseReferencedPlayTarget3(
15919
+ const resolvedName = parseReferencedPlayTarget2(
17606
15920
  formatPlayReference(detail.play)
17607
15921
  ).playName;
17608
15922
  if (args.includes("--dry-run")) {
@@ -17666,7 +15980,7 @@ async function handlePlayRestore(args) {
17666
15980
  const client = new DeeplineClient();
17667
15981
  try {
17668
15982
  const result = await client.restorePlay(
17669
- parseReferencedPlayTarget3(playName).playName
15983
+ parseReferencedPlayTarget2(playName).playName
17670
15984
  );
17671
15985
  if (argsWantJson(args)) {
17672
15986
  printCompactJson(result);
@@ -17960,7 +16274,6 @@ JSON field selection:
17960
16274
  process.exitCode = exitCode;
17961
16275
  }
17962
16276
  );
17963
- registerPlayBootstrapCommand(play);
17964
16277
  registerPlaySettingsCommands(play);
17965
16278
  registerPlayTriggerConfigCommands(play);
17966
16279
  play.command("get <target>").description(
@@ -18160,7 +16473,7 @@ Examples:
18160
16473
  process.exitCode = await ownView();
18161
16474
  return;
18162
16475
  }
18163
- const { describeAnything } = await import("./describe-JTEJNG67.mjs");
16476
+ const { describeAnything } = await import("./describe-QUOLGZKH.mjs");
18164
16477
  process.exitCode = await describeAnything(
18165
16478
  name,
18166
16479
  {
@@ -18898,7 +17211,7 @@ async function handlePlayShareStatus(args) {
18898
17211
  console.error("Usage: deepline plays share status <play> [--json]");
18899
17212
  return 2;
18900
17213
  }
18901
- const name = parseReferencedPlayTarget3(target).playName;
17214
+ const name = parseReferencedPlayTarget2(target).playName;
18902
17215
  const status = await new DeeplineClient().getSharePage(name);
18903
17216
  const outputStatus = shareStatusForOutput(status);
18904
17217
  if (argsWantJson(args)) {
@@ -18940,7 +17253,7 @@ async function handlePlaySharePublish(args) {
18940
17253
  );
18941
17254
  return 2;
18942
17255
  }
18943
- const name = parseReferencedPlayTarget3(target).playName;
17256
+ const name = parseReferencedPlayTarget2(target).playName;
18944
17257
  const client = new DeeplineClient();
18945
17258
  let revisionId = shareFlagValue(args, "--revision-id");
18946
17259
  let resolvedVersion;
@@ -19032,7 +17345,7 @@ async function handlePlayShareUpdate(args) {
19032
17345
  );
19033
17346
  return 2;
19034
17347
  }
19035
- const name = parseReferencedPlayTarget3(target).playName;
17348
+ const name = parseReferencedPlayTarget2(target).playName;
19036
17349
  const seo = shareFlagValue(args, "--seo");
19037
17350
  const seoIndexing = seo === "index" ? "index" : seo === "noindex" ? "noindex" : void 0;
19038
17351
  const request = {
@@ -19056,7 +17369,7 @@ async function handlePlayShareRegenerate(args) {
19056
17369
  );
19057
17370
  return 2;
19058
17371
  }
19059
- const name = parseReferencedPlayTarget3(target).playName;
17372
+ const name = parseReferencedPlayTarget2(target).playName;
19060
17373
  const client = new DeeplineClient();
19061
17374
  let revisionId = shareFlagValue(args, "--revision-id");
19062
17375
  const versionFlag = shareFlagValue(args, "--version");
@@ -19099,7 +17412,7 @@ async function handlePlayShareUnpublish(args) {
19099
17412
  );
19100
17413
  return 2;
19101
17414
  }
19102
- const name = parseReferencedPlayTarget3(target).playName;
17415
+ const name = parseReferencedPlayTarget2(target).playName;
19103
17416
  const status = await new DeeplineClient().unpublishSharePage(name);
19104
17417
  if (argsWantJson(args)) {
19105
17418
  printCompactJson(status);