deepline 0.3.294 → 0.3.296

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 (138) hide show
  1. package/dist/bundling-sources/sdk/src/compat.ts +35 -7
  2. package/dist/bundling-sources/sdk/src/release.ts +1 -1
  3. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres.ts +108 -35
  4. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-api-origin.ts +25 -0
  5. package/dist/bundling-sources/shared_libs/play-runtime/tool-http-errors.ts +14 -1
  6. package/dist/cli/auth-JCGIDVDF.mjs +31 -0
  7. package/dist/cli/auth-QDWV3TXX.js +31 -0
  8. package/dist/cli/billing-OQBSIXRG.mjs +1749 -0
  9. package/dist/cli/billing-YBK3J4WP.js +1749 -0
  10. package/dist/cli/chunk-2C3AVPTY.js +5688 -0
  11. package/dist/cli/chunk-2MZ5EQZE.mjs +499 -0
  12. package/dist/cli/chunk-3KC45UVF.js +150 -0
  13. package/dist/cli/chunk-3XX5TEA4.js +15 -0
  14. package/dist/cli/chunk-4MBOJQPL.mjs +0 -0
  15. package/dist/cli/chunk-4Y6CG4GE.js +2240 -0
  16. package/dist/cli/chunk-4ZB3CJRD.js +1269 -0
  17. package/dist/cli/chunk-5JLQPVNX.js +3056 -0
  18. package/dist/cli/chunk-6A3TJUWC.js +76 -0
  19. package/dist/cli/chunk-6HPEDBSJ.js +1995 -0
  20. package/dist/cli/chunk-7D6QG5KF.js +890 -0
  21. package/dist/cli/chunk-7P5AA3SN.js +344 -0
  22. package/dist/cli/chunk-7UAO5MWV.mjs +190 -0
  23. package/dist/cli/chunk-A7427JJH.js +190 -0
  24. package/dist/cli/chunk-AQRTLPHZ.js +735 -0
  25. package/dist/cli/chunk-AYHLUHE5.js +52 -0
  26. package/dist/cli/chunk-BZ77OTRF.mjs +923 -0
  27. package/dist/cli/chunk-CBVIJSHF.mjs +560 -0
  28. package/dist/cli/chunk-COGTRVWW.js +30 -0
  29. package/dist/cli/chunk-DLIRSHV6.mjs +28 -0
  30. package/dist/cli/chunk-DYWHXO7O.mjs +34 -0
  31. package/dist/cli/chunk-EDWJY6T4.mjs +3056 -0
  32. package/dist/cli/chunk-EXMLR72R.mjs +0 -0
  33. package/dist/cli/chunk-G46HHFNB.mjs +1269 -0
  34. package/dist/cli/chunk-GAMFK2ZP.mjs +148 -0
  35. package/dist/cli/chunk-GLKUGBTP.mjs +2240 -0
  36. package/dist/cli/chunk-GONRLVV3.js +3440 -0
  37. package/dist/cli/chunk-GVUJJJ5G.mjs +76 -0
  38. package/dist/cli/chunk-H7HIDGZ7.mjs +150 -0
  39. package/dist/cli/chunk-HUZXWOSK.mjs +503 -0
  40. package/dist/cli/chunk-I5YZLGMG.js +1 -0
  41. package/dist/cli/chunk-ITOFSXIU.mjs +15 -0
  42. package/dist/cli/chunk-J2D3VDOU.mjs +5688 -0
  43. package/dist/cli/chunk-J5NA2TTX.js +503 -0
  44. package/dist/cli/chunk-JCS5TPNY.mjs +3440 -0
  45. package/dist/cli/chunk-JNNOCMQY.js +47 -0
  46. package/dist/cli/chunk-KRD6H754.mjs +30 -0
  47. package/dist/cli/chunk-L4HBNHFW.js +34 -0
  48. package/dist/cli/chunk-LA46MMTL.js +560 -0
  49. package/dist/cli/chunk-LIKFCE7Z.js +190 -0
  50. package/dist/cli/chunk-MIMASXO4.mjs +389 -0
  51. package/dist/cli/chunk-NPPJX3BL.mjs +1995 -0
  52. package/dist/cli/chunk-NTEZFZLE.mjs +890 -0
  53. package/dist/cli/chunk-NXDRDJ4K.js +389 -0
  54. package/dist/cli/chunk-NXGCO4JB.mjs +344 -0
  55. package/dist/cli/chunk-OG64RBAC.js +6 -0
  56. package/dist/cli/chunk-OWJZUE3Y.mjs +103 -0
  57. package/dist/cli/chunk-QSIO4TX2.mjs +190 -0
  58. package/dist/cli/chunk-RCUE5C5C.mjs +735 -0
  59. package/dist/cli/chunk-SDK3ZA2C.js +103 -0
  60. package/dist/cli/chunk-SFLARO4Y.mjs +47 -0
  61. package/dist/cli/chunk-TAC3JIFE.mjs +354 -0
  62. package/dist/cli/chunk-UC6GHEL4.js +499 -0
  63. package/dist/cli/chunk-UFS752TU.mjs +52 -0
  64. package/dist/cli/chunk-UNEMDKXN.js +1 -0
  65. package/dist/cli/chunk-WB6Z2Q44.mjs +1622 -0
  66. package/dist/cli/chunk-WJYPBHTE.js +148 -0
  67. package/dist/cli/chunk-WOHBA5PV.js +354 -0
  68. package/dist/cli/chunk-WZYKRD7T.mjs +6 -0
  69. package/dist/cli/chunk-XNYIZMNQ.js +28 -0
  70. package/dist/cli/chunk-ZDO3TO3M.js +1622 -0
  71. package/dist/cli/chunk-ZDOC4HFL.js +923 -0
  72. package/dist/cli/client-CZDA4JKO.mjs +20 -0
  73. package/dist/cli/client-IZGIN2ZA.js +20 -0
  74. package/dist/cli/csv-6KOMZA2H.mjs +585 -0
  75. package/dist/cli/csv-UTEQY3NA.js +585 -0
  76. package/dist/cli/db-D5EP6TKO.mjs +486 -0
  77. package/dist/cli/db-SIBLPIKC.js +486 -0
  78. package/dist/cli/executions-2PHT57IO.js +28 -0
  79. package/dist/cli/executions-DFWM2YYY.mjs +28 -0
  80. package/dist/cli/feedback-GZW37JMI.mjs +107 -0
  81. package/dist/cli/feedback-IQVWIJZ4.js +107 -0
  82. package/dist/cli/getting-started.js +18 -76
  83. package/dist/cli/getting-started.mjs +10 -37
  84. package/dist/cli/git-563GYLMA.js +23 -0
  85. package/dist/cli/git-B72Y4FFQ.mjs +23 -0
  86. package/dist/cli/index.js +291 -54294
  87. package/dist/cli/index.mjs +209 -54352
  88. package/dist/cli/legacy-noops-37F5MX2P.mjs +157 -0
  89. package/dist/cli/legacy-noops-IFGVDCOM.js +157 -0
  90. package/dist/cli/monitors-42H6LOVT.mjs +3251 -0
  91. package/dist/cli/monitors-GQCHXBXZ.js +3251 -0
  92. package/dist/cli/org-4GCPBTGR.js +849 -0
  93. package/dist/cli/org-JYZA3ZRJ.mjs +849 -0
  94. package/dist/cli/play-46ZJ4FMI.js +18439 -0
  95. package/dist/cli/play-Q2XV3FZZ.mjs +18439 -0
  96. package/dist/cli/providers-CTKQP45X.mjs +95 -0
  97. package/dist/cli/providers-PCNF5E3K.js +95 -0
  98. package/dist/cli/proxy-env-EBANZHPV.js +161 -0
  99. package/dist/cli/proxy-env-M4ZHXHRL.mjs +161 -0
  100. package/dist/cli/quickstart-FTHWRVWN.js +69 -0
  101. package/dist/cli/quickstart-X7EVVWRG.mjs +69 -0
  102. package/dist/cli/search-73YPOFDO.mjs +18 -0
  103. package/dist/cli/search-XA5UVC3G.js +18 -0
  104. package/dist/cli/secrets-OUMPT4FX.mjs +400 -0
  105. package/dist/cli/secrets-UOEVR73Q.js +400 -0
  106. package/dist/cli/sessions-CMKXCN5Y.js +15 -0
  107. package/dist/cli/sessions-ZIFGDZE7.mjs +15 -0
  108. package/dist/cli/settings-OO5R3G52.mjs +846 -0
  109. package/dist/cli/settings-ULZT2NIC.js +846 -0
  110. package/dist/cli/setup-6GZH52OZ.mjs +1257 -0
  111. package/dist/cli/setup-DHGERXPZ.js +1257 -0
  112. package/dist/cli/skills-Q7NUCS2W.js +28 -0
  113. package/dist/cli/skills-T3EY2656.mjs +28 -0
  114. package/dist/cli/tools-BIMOAOTX.mjs +2955 -0
  115. package/dist/cli/tools-ODXVCKO7.js +2955 -0
  116. package/dist/cli/update-UMB3ULBR.js +28 -0
  117. package/dist/cli/update-X4HX7Z3M.mjs +28 -0
  118. package/dist/cli/workflow-EAUFVPIP.mjs +1936 -0
  119. package/dist/cli/workflow-IVLCPFTG.js +1936 -0
  120. package/dist/helpers.js +6 -32
  121. package/dist/helpers.mjs +2 -0
  122. package/dist/index.js +1972 -12825
  123. package/dist/index.mjs +1910 -12672
  124. package/dist/install-integrity.json +110 -0
  125. package/dist/monitor-fleet-contract.js +31 -730
  126. package/dist/monitor-fleet-contract.mjs +18 -667
  127. package/dist/monitor-input-contract.js +10 -390
  128. package/dist/monitor-input-contract.mjs +7 -348
  129. package/dist/plays/bundle-play-file.mjs +13 -5178
  130. package/dist/plays/csv-data-input.js +5 -3132
  131. package/dist/plays/csv-data-input.mjs +5 -3105
  132. package/dist/plays/run-request.js +56 -664
  133. package/dist/plays/run-request.mjs +30 -588
  134. package/dist/release.d.mts +1 -1
  135. package/dist/release.d.ts +1 -1
  136. package/dist/release.js +5 -212
  137. package/dist/release.mjs +5 -185
  138. package/package.json +1 -1
@@ -0,0 +1,20 @@
1
+ import {
2
+ DeeplineClient,
3
+ MONITOR_JOB_PHASES,
4
+ MONITOR_JOB_RECONCILIATION_STATES,
5
+ MONITOR_JOB_STATES
6
+ } from "./chunk-J2D3VDOU.mjs";
7
+ import "./chunk-CBVIJSHF.mjs";
8
+ import "./chunk-NPPJX3BL.mjs";
9
+ import "./chunk-DLIRSHV6.mjs";
10
+ import "./chunk-QSIO4TX2.mjs";
11
+ import "./chunk-GVUJJJ5G.mjs";
12
+ import "./chunk-NXGCO4JB.mjs";
13
+ import "./chunk-WZYKRD7T.mjs";
14
+ import "./chunk-KRD6H754.mjs";
15
+ export {
16
+ DeeplineClient,
17
+ MONITOR_JOB_PHASES,
18
+ MONITOR_JOB_RECONCILIATION_STATES,
19
+ MONITOR_JOB_STATES
20
+ };
@@ -0,0 +1,20 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
+
3
+
4
+
5
+
6
+ var _chunk2C3AVPTYjs = require('./chunk-2C3AVPTY.js');
7
+ require('./chunk-LA46MMTL.js');
8
+ require('./chunk-6HPEDBSJ.js');
9
+ require('./chunk-XNYIZMNQ.js');
10
+ require('./chunk-LIKFCE7Z.js');
11
+ require('./chunk-6A3TJUWC.js');
12
+ require('./chunk-7P5AA3SN.js');
13
+ require('./chunk-OG64RBAC.js');
14
+ require('./chunk-COGTRVWW.js');
15
+
16
+
17
+
18
+
19
+
20
+ exports.DeeplineClient = _chunk2C3AVPTYjs.DeeplineClient; exports.MONITOR_JOB_PHASES = _chunk2C3AVPTYjs.MONITOR_JOB_PHASES; exports.MONITOR_JOB_RECONCILIATION_STATES = _chunk2C3AVPTYjs.MONITOR_JOB_RECONCILIATION_STATES; exports.MONITOR_JOB_STATES = _chunk2C3AVPTYjs.MONITOR_JOB_STATES;
@@ -0,0 +1,585 @@
1
+ import {
2
+ clip,
3
+ csvStringFromRows,
4
+ printCommandEnvelope,
5
+ printJson,
6
+ readCsvRows
7
+ } from "./chunk-NTEZFZLE.mjs";
8
+ import "./chunk-NPPJX3BL.mjs";
9
+ import "./chunk-DLIRSHV6.mjs";
10
+ import "./chunk-QSIO4TX2.mjs";
11
+ import "./chunk-NXGCO4JB.mjs";
12
+ import "./chunk-WZYKRD7T.mjs";
13
+ import "./chunk-KRD6H754.mjs";
14
+
15
+ // src/cli/commands/csv.ts
16
+ import { Option } from "commander";
17
+ import { spawn } from "child_process";
18
+ import { randomUUID } from "crypto";
19
+ import {
20
+ closeSync,
21
+ existsSync,
22
+ mkdirSync,
23
+ openSync,
24
+ readFileSync,
25
+ rmSync,
26
+ writeFileSync
27
+ } from "fs";
28
+ import { homedir } from "os";
29
+ import { join, resolve } from "path";
30
+ function parseRowRange(raw) {
31
+ const source = raw?.trim() || "0:19";
32
+ const [startRaw, endRaw] = source.split(":", 2);
33
+ const start = Number.parseInt(startRaw ?? "", 10);
34
+ const end = Number.parseInt(endRaw ?? "", 10);
35
+ if (!Number.isFinite(start) || !Number.isFinite(end) || start < 0 || end < start) {
36
+ throw new Error(
37
+ `Invalid --rows value: ${source} (expected start:end, e.g. 0:19).`
38
+ );
39
+ }
40
+ return [start, end];
41
+ }
42
+ function selectRows(rows, start, end) {
43
+ return rows.slice(start, end + 1);
44
+ }
45
+ function selectColumns(rows, rawColumns, rawExcludeColumns, availableColumns) {
46
+ const parseNames = (raw, flag) => {
47
+ if (raw === void 0) return null;
48
+ const names = raw.split(",").map((part) => part.trim());
49
+ if (names.some((name) => !name)) {
50
+ throw new Error(
51
+ `Invalid ${flag} value: provide comma-separated column names.`
52
+ );
53
+ }
54
+ const missing = names.filter((name) => !availableColumns.includes(name));
55
+ if (missing.length > 0) {
56
+ throw new Error(`Unknown ${flag} value(s): ${missing.join(", ")}.`);
57
+ }
58
+ return [...new Set(names)];
59
+ };
60
+ const included = parseNames(rawColumns, "--columns") ?? availableColumns;
61
+ const excluded = new Set(
62
+ parseNames(rawExcludeColumns, "--exclude-columns") ?? []
63
+ );
64
+ const requested = included.filter((name) => !excluded.has(name));
65
+ if (requested.length === 0 && availableColumns.length > 0) {
66
+ throw new Error("No columns remain after --columns and --exclude-columns.");
67
+ }
68
+ return {
69
+ columns: requested,
70
+ rows: rows.map((row) => {
71
+ const next = {};
72
+ for (const column of requested) next[column] = row[column] ?? "";
73
+ return next;
74
+ })
75
+ };
76
+ }
77
+ function summarizeColumns(rows, columns) {
78
+ return columns.map((column) => {
79
+ let missing = 0;
80
+ const counts = /* @__PURE__ */ new Map();
81
+ for (const row of rows) {
82
+ const value = row[column] ?? "";
83
+ if (!value.trim()) {
84
+ missing += 1;
85
+ } else {
86
+ counts.set(value, (counts.get(value) ?? 0) + 1);
87
+ }
88
+ }
89
+ const present = rows.length - missing;
90
+ const ranked = [...counts.entries()].sort((a, b) => b[1] - a[1]);
91
+ const top = counts.size < present ? ranked.slice(0, 3) : [];
92
+ const topCount = top.reduce((sum, [, count]) => sum + count, 0);
93
+ return {
94
+ column,
95
+ present,
96
+ missing,
97
+ present_percent: rows.length ? Math.round(present / rows.length * 100) : 0,
98
+ unique: counts.size,
99
+ top_values: top.map(([value, count]) => ({
100
+ value,
101
+ count,
102
+ percent: rows.length ? Math.round(count / rows.length * 100) : 0
103
+ })),
104
+ other_count: top.length > 0 ? present - topCount : 0
105
+ };
106
+ });
107
+ }
108
+ function summaryDisplayRows(summaries) {
109
+ return summaries.map((summary) => ({
110
+ column: summary.column,
111
+ present: String(summary.present),
112
+ missing: String(summary.missing),
113
+ present_percent: `${summary.present_percent}%`,
114
+ unique: String(summary.unique),
115
+ top_values: summary.top_values.map(({ value, count, percent }) => `${value}: ${count} (${percent}%)`).join(", "),
116
+ other_count: String(summary.other_count)
117
+ }));
118
+ }
119
+ function renderTable(rows, totalRows, verbose, footer = `showing ${rows.length} row(s) of ${totalRows}`) {
120
+ const columns = Object.keys(rows[0] ?? {});
121
+ if (columns.length === 0) return "No rows.";
122
+ const widths = Object.fromEntries(
123
+ columns.map((column) => [
124
+ column,
125
+ Math.max(
126
+ column.length,
127
+ ...rows.map((row) => {
128
+ const value = row[column] ?? "";
129
+ return (verbose ? value : clip(value, 42)).length;
130
+ })
131
+ )
132
+ ])
133
+ );
134
+ const header = columns.map((column) => column.padEnd(widths[column])).join(" | ");
135
+ const divider = columns.map((column) => "-".repeat(widths[column])).join("-+-");
136
+ const body = rows.map(
137
+ (row) => columns.map((column) => {
138
+ const raw = row[column] ?? "";
139
+ const display = verbose ? raw : clip(raw, 42);
140
+ return display.padEnd(widths[column]);
141
+ }).join(" | ")
142
+ );
143
+ return [header, divider, ...body, "", footer].join("\n");
144
+ }
145
+ async function handleCsvShow(path, options, command) {
146
+ if (path !== void 0 && options.csv !== void 0) {
147
+ command.error(
148
+ "Specify one CSV path: deepline csv show <path>. Do not combine it with --csv.",
149
+ { exitCode: 2 }
150
+ );
151
+ }
152
+ const csvPath = path ?? options.csv;
153
+ if (!csvPath) {
154
+ command.error(
155
+ "Missing CSV path. Usage: deepline csv show <path> [options]",
156
+ { exitCode: 2 }
157
+ );
158
+ }
159
+ const allRows = readCsvRows(csvPath);
160
+ const [rowStart, rowEnd] = parseRowRange(options.rows);
161
+ const rows = options.summary && options.rows === void 0 ? allRows : selectRows(allRows, rowStart, rowEnd);
162
+ const { rows: selected, columns } = selectColumns(
163
+ rows,
164
+ options.columns,
165
+ options.excludeColumns,
166
+ Object.keys(allRows[0] ?? {})
167
+ );
168
+ const format = options.format ?? "json";
169
+ if (options.summary) {
170
+ const summaries = summarizeColumns(selected, columns);
171
+ if (format === "json") {
172
+ printJson({
173
+ rows: summaries,
174
+ total_rows: selected.length,
175
+ source_total_rows: allRows.length
176
+ });
177
+ return;
178
+ }
179
+ const displayRows = summaryDisplayRows(summaries);
180
+ if (format === "csv") {
181
+ process.stdout.write(csvStringFromRows(displayRows));
182
+ return;
183
+ }
184
+ process.stdout.write(
185
+ `${renderTable(
186
+ displayRows,
187
+ selected.length,
188
+ Boolean(options.verbose),
189
+ `summarized ${summaries.length} column(s) across ${selected.length} row(s) of ${allRows.length}`
190
+ )}
191
+ `
192
+ );
193
+ return;
194
+ }
195
+ if (format === "json") {
196
+ printJson({
197
+ rows: selected.map((row, index) => ({ __row: rowStart + index, ...row }))
198
+ });
199
+ return;
200
+ }
201
+ if (format === "csv") {
202
+ const columns2 = Object.keys(selected[0] ?? {});
203
+ process.stdout.write(`${columns2.join(",")}
204
+ `);
205
+ for (const row of selected) {
206
+ process.stdout.write(
207
+ `${columns2.map((column) => JSON.stringify(row[column] ?? "")).join(",")}
208
+ `
209
+ );
210
+ }
211
+ return;
212
+ }
213
+ process.stdout.write(
214
+ `${renderTable(selected, allRows.length, Boolean(options.verbose))}
215
+ `
216
+ );
217
+ }
218
+ function csvRenderStatePath() {
219
+ return join(homedir(), ".local", "deepline", "runtime", "csv-render.json");
220
+ }
221
+ function csvRenderLogPath() {
222
+ return join(homedir(), ".local", "deepline", "runtime", "csv-render.log");
223
+ }
224
+ function ensureCsvRenderStateDir() {
225
+ mkdirSync(join(homedir(), ".local", "deepline", "runtime"), {
226
+ recursive: true
227
+ });
228
+ }
229
+ function readCsvRenderState() {
230
+ try {
231
+ const parsed = JSON.parse(readFileSync(csvRenderStatePath(), "utf8"));
232
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
233
+ } catch {
234
+ return {};
235
+ }
236
+ }
237
+ function writeCsvRenderState(state) {
238
+ ensureCsvRenderStateDir();
239
+ writeFileSync(csvRenderStatePath(), `${JSON.stringify(state, null, 2)}
240
+ `);
241
+ }
242
+ function parseCsvRenderPort(raw) {
243
+ const value = Number.parseInt(String(raw ?? "4174").replace(/^:/, ""), 10);
244
+ if (!Number.isInteger(value) || value <= 0 || value > 65535) {
245
+ throw new Error(`Invalid --port value: ${raw ?? ""}`);
246
+ }
247
+ return value;
248
+ }
249
+ function processAlive(pid) {
250
+ if (!Number.isInteger(pid) || pid <= 0) {
251
+ return false;
252
+ }
253
+ try {
254
+ process.kill(pid, 0);
255
+ return true;
256
+ } catch {
257
+ return false;
258
+ }
259
+ }
260
+ function isOwnedCsvRenderHealth(health, state) {
261
+ return Boolean(health?.ok) && Number.isInteger(state.pid) && health?.pid === state.pid && Boolean(state.token) && health?.token === state.token;
262
+ }
263
+ async function fetchCsvRenderHealth(url) {
264
+ try {
265
+ const response = await fetch(`${url}/health`);
266
+ if (!response.ok) {
267
+ return null;
268
+ }
269
+ const parsed = await response.json();
270
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
271
+ } catch {
272
+ return null;
273
+ }
274
+ }
275
+ async function waitForRenderHealth(url, state) {
276
+ const deadline = Date.now() + 15e3;
277
+ while (Date.now() < deadline) {
278
+ if (isOwnedCsvRenderHealth(await fetchCsvRenderHealth(url), state)) {
279
+ return true;
280
+ }
281
+ if (state.pid && !processAlive(state.pid)) {
282
+ return false;
283
+ }
284
+ await new Promise((resolveDelay) => setTimeout(resolveDelay, 100));
285
+ }
286
+ return false;
287
+ }
288
+ async function waitForRenderStopped(url) {
289
+ const deadline = Date.now() + 2e3;
290
+ while (Date.now() < deadline) {
291
+ try {
292
+ await fetch(`${url}/health`);
293
+ } catch {
294
+ return;
295
+ }
296
+ await new Promise((resolveDelay) => setTimeout(resolveDelay, 100));
297
+ }
298
+ }
299
+ var CSV_RENDER_SERVER_SOURCE = String.raw`
300
+ const http = require('node:http');
301
+ const fs = require('node:fs');
302
+ const path = require('node:path');
303
+
304
+ const port = Number.parseInt(process.env.DEEPLINE_CSV_RENDER_PORT || '4174', 10);
305
+ const csvPath = process.env.DEEPLINE_CSV_RENDER_CSV || '';
306
+ const token = process.env.DEEPLINE_CSV_RENDER_TOKEN || '';
307
+
308
+ function send(res, status, contentType, body) {
309
+ res.writeHead(status, {
310
+ 'content-type': contentType,
311
+ 'cache-control': 'no-store',
312
+ });
313
+ res.end(body);
314
+ }
315
+
316
+ function readCsvText() {
317
+ if (!csvPath) return '';
318
+ try {
319
+ return fs.readFileSync(csvPath, 'utf8');
320
+ } catch (error) {
321
+ return 'Unable to read CSV: ' + (error && error.message ? error.message : String(error));
322
+ }
323
+ }
324
+
325
+ const server = http.createServer((req, res) => {
326
+ const url = new URL(req.url || '/', 'http://127.0.0.1:' + port);
327
+ if (url.pathname === '/health') {
328
+ send(res, 200, 'application/json', JSON.stringify({ ok: true, pid: process.pid, csvPath, token }));
329
+ return;
330
+ }
331
+ if (url.pathname === '/csv.txt') {
332
+ send(res, 200, 'text/plain; charset=utf-8', readCsvText());
333
+ return;
334
+ }
335
+ if (url.pathname === '/csv.json') {
336
+ send(res, 200, 'application/json', JSON.stringify({ csvPath, text: readCsvText() }));
337
+ return;
338
+ }
339
+ const title = csvPath ? path.basename(csvPath) : 'CSV renderer';
340
+ const escapedTitle = title.replace(/[&<>"]/g, (ch) => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;' }[ch]));
341
+ const escapedCsv = readCsvText().replace(/[&<>]/g, (ch) => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;' }[ch]));
342
+ send(res, 200, 'text/html; charset=utf-8', '<!doctype html><html><head><meta charset="utf-8"><title>' + escapedTitle + '</title><style>body{font:14px system-ui,sans-serif;margin:24px}pre{white-space:pre-wrap;border:1px solid #ddd;padding:16px;border-radius:8px}</style></head><body><h1>' + escapedTitle + '</h1><pre>' + escapedCsv + '</pre></body></html>');
343
+ });
344
+
345
+ server.listen(port, '127.0.0.1');
346
+ server.on('error', (error) => {
347
+ console.error(error && error.stack ? error.stack : error);
348
+ process.exit(1);
349
+ });
350
+ process.on('SIGTERM', () => server.close(() => process.exit(0)));
351
+ process.on('SIGINT', () => server.close(() => process.exit(0)));
352
+ `;
353
+ async function openBrowser(url) {
354
+ const opener = process.platform === "darwin" ? "open" : process.platform === "win32" ? "cmd" : "xdg-open";
355
+ const args = process.platform === "win32" ? ["/c", "start", "", url] : [url];
356
+ const child = spawn(opener, args, { detached: true, stdio: "ignore" });
357
+ child.on("error", () => {
358
+ });
359
+ child.unref();
360
+ }
361
+ async function handleCsvRenderStart(options) {
362
+ const port = parseCsvRenderPort(options.port);
363
+ const csvPath = options.csv ? resolve(options.csv) : "";
364
+ if (csvPath && !existsSync(csvPath)) {
365
+ throw new Error(`CSV not found: ${csvPath}`);
366
+ }
367
+ const url = `http://127.0.0.1:${port}`;
368
+ const existing = readCsvRenderState();
369
+ if (processAlive(existing.pid) && existing.url) {
370
+ const existingOwned = isOwnedCsvRenderHealth(
371
+ await fetchCsvRenderHealth(existing.url),
372
+ existing
373
+ );
374
+ const sameUrl = existing.url === url;
375
+ const sameCsv = !csvPath || existing.csvPath === csvPath;
376
+ if (existingOwned && (!sameUrl || !sameCsv)) {
377
+ try {
378
+ process.kill(existing.pid, "SIGTERM");
379
+ } catch {
380
+ }
381
+ await waitForRenderStopped(existing.url);
382
+ if (processAlive(existing.pid)) {
383
+ try {
384
+ process.kill(existing.pid, "SIGKILL");
385
+ } catch {
386
+ }
387
+ }
388
+ rmSync(csvRenderStatePath(), { force: true });
389
+ } else if (existingOwned) {
390
+ process.stdout.write(
391
+ "CSV render is already running; reusing current process.\n"
392
+ );
393
+ process.stdout.write(`Render URL: ${existing.url}
394
+ `);
395
+ if (options.open) {
396
+ await openBrowser(existing.url);
397
+ }
398
+ return;
399
+ } else {
400
+ rmSync(csvRenderStatePath(), { force: true });
401
+ }
402
+ }
403
+ ensureCsvRenderStateDir();
404
+ const logPath = csvRenderLogPath();
405
+ const logFd = openSync(logPath, "w");
406
+ const token = randomUUID();
407
+ const child = spawn(process.execPath, ["-e", CSV_RENDER_SERVER_SOURCE], {
408
+ detached: true,
409
+ stdio: ["ignore", logFd, logFd],
410
+ env: {
411
+ ...process.env,
412
+ DEEPLINE_CSV_RENDER_PORT: String(port),
413
+ DEEPLINE_CSV_RENDER_CSV: csvPath,
414
+ DEEPLINE_CSV_RENDER_TOKEN: token
415
+ }
416
+ });
417
+ closeSync(logFd);
418
+ child.unref();
419
+ const state = {
420
+ pid: child.pid ?? null,
421
+ port,
422
+ url,
423
+ csvPath,
424
+ logPath,
425
+ startedAt: (/* @__PURE__ */ new Date()).toISOString(),
426
+ token
427
+ };
428
+ const started = await waitForRenderHealth(url, state);
429
+ if (!started) {
430
+ if (processAlive(child.pid)) {
431
+ process.kill(child.pid, "SIGTERM");
432
+ }
433
+ let detail = "";
434
+ try {
435
+ const log = readFileSync(logPath, "utf8").trim();
436
+ if (log) {
437
+ detail = `
438
+ CSV render log:
439
+ ${clip(log, 2e3)}`;
440
+ }
441
+ } catch {
442
+ }
443
+ throw new Error(
444
+ `Timed out waiting for CSV render to start at ${url}.${detail}`
445
+ );
446
+ }
447
+ writeCsvRenderState(state);
448
+ writeFileSync(
449
+ logPath,
450
+ `CSV render started at ${state.startedAt} on ${url}
451
+ `
452
+ );
453
+ process.stdout.write("CSV render is running.\n");
454
+ process.stdout.write(`Render PID: ${child.pid}
455
+ `);
456
+ process.stdout.write(`Render URL: ${url}
457
+ `);
458
+ if (options.open) {
459
+ await openBrowser(url);
460
+ }
461
+ }
462
+ async function handleCsvRenderStatus(options) {
463
+ const state = readCsvRenderState();
464
+ const processExists = processAlive(state.pid);
465
+ const url = state.url ?? "";
466
+ let health = "unknown";
467
+ let owned = false;
468
+ if (processExists && url) {
469
+ const renderHealth = await fetchCsvRenderHealth(url);
470
+ owned = isOwnedCsvRenderHealth(renderHealth, state);
471
+ health = owned ? "healthy" : "unhealthy";
472
+ }
473
+ const status = processExists && owned ? "running" : processExists ? "unhealthy" : "stopped";
474
+ const payload = {
475
+ status,
476
+ pid: owned ? state.pid : null,
477
+ process_alive: owned,
478
+ url,
479
+ log_path: state.logPath ?? "",
480
+ mode: "background",
481
+ started_at: owned ? state.startedAt ?? "" : "",
482
+ health_status: health,
483
+ health_checked_at: (/* @__PURE__ */ new Date()).toISOString(),
484
+ stale_cleaned: true
485
+ };
486
+ const lines = [`Render Status: ${payload.status}`];
487
+ if (payload.pid) lines.push(`Render PID: ${payload.pid}`);
488
+ if (payload.url) lines.push(`Render URL: ${payload.url}`);
489
+ lines.push(`Render Health: ${payload.health_status}`);
490
+ printCommandEnvelope(payload, {
491
+ json: options.json,
492
+ text: `${lines.join("\n")}
493
+ `
494
+ });
495
+ }
496
+ function terminateRenderProcess(pid) {
497
+ try {
498
+ process.kill(pid, "SIGTERM");
499
+ } catch {
500
+ return false;
501
+ }
502
+ return true;
503
+ }
504
+ async function handleCsvRenderStop(options) {
505
+ const state = readCsvRenderState();
506
+ const stopped = [];
507
+ const failed = [];
508
+ const owned = processAlive(state.pid) && Boolean(state.url) && isOwnedCsvRenderHealth(await fetchCsvRenderHealth(state.url), state);
509
+ if (owned && processAlive(state.pid)) {
510
+ if (terminateRenderProcess(state.pid)) {
511
+ stopped.push(state.pid);
512
+ } else {
513
+ failed.push(state.pid);
514
+ }
515
+ }
516
+ rmSync(csvRenderStatePath(), { force: true });
517
+ const payload = {
518
+ ok: failed.length === 0,
519
+ stopped_count: stopped.length,
520
+ failed_count: failed.length,
521
+ stopped_pids: stopped,
522
+ failed_pids: failed
523
+ };
524
+ const text = stopped.length > 0 ? `Stopped CSV render process(es): ${stopped.join(" ")}
525
+ ` : "No running CSV render process found.\n";
526
+ printCommandEnvelope(payload, { json: options.json, text });
527
+ }
528
+ async function handleCsvRender(action, options) {
529
+ const normalized = action ?? "start";
530
+ if (normalized === "start") {
531
+ await handleCsvRenderStart(options);
532
+ return;
533
+ }
534
+ if (normalized === "status") {
535
+ await handleCsvRenderStatus(options);
536
+ return;
537
+ }
538
+ if (normalized === "stop") {
539
+ await handleCsvRenderStop(options);
540
+ return;
541
+ }
542
+ throw new Error(`Unknown csv render action: ${normalized}`);
543
+ }
544
+ function registerCsvCommands(program) {
545
+ const csv = program.command("csv").description("Inspect local CSV files.").addHelpText(
546
+ "after",
547
+ `
548
+ Notes:
549
+ Local-only inspection helpers. These commands do not upload CSV files or call
550
+ Deepline APIs.
551
+
552
+ Examples:
553
+ deepline csv show leads.csv --rows 0:10 --format table
554
+ deepline csv show leads.csv --summary
555
+ `
556
+ );
557
+ csv.command("show").argument("[path]", "Input CSV path").usage("<path> [options]").allowExcessArguments(false).description("Display rows from a CSV file in json, csv, or table form.").addHelpText(
558
+ "after",
559
+ `
560
+ Notes:
561
+ Reads a local CSV path. By default, rows show 0:19 (first 20 rows), while
562
+ --summary analyzes the whole file. An explicit --rows start:end range applies
563
+ to either mode. Column selection and --format apply to both; JSON is default.
564
+
565
+ Examples:
566
+ deepline csv show leads.csv
567
+ deepline csv show leads.csv --rows 20:39 --columns name,email --format table
568
+ deepline csv show leads.csv --exclude-columns raw_response,attempts --format table
569
+ deepline csv show leads.csv --summary
570
+ `
571
+ ).addOption(
572
+ new Option("--csv <path>", "Input CSV path (legacy alias)").hideHelp()
573
+ ).option("--format <format>", "Output format: json, csv, or table", "json").option(
574
+ "--rows <range>",
575
+ "Inclusive row range start:end (show defaults to 0:19)"
576
+ ).option("--columns <names>", "Comma-separated column names to include").option("--exclude-columns <names>", "Comma-separated column names to omit").option(
577
+ "--summary",
578
+ "Summarize selected columns as one row per column; defaults to all rows"
579
+ ).option("--verbose", "Do not truncate long values in table output").action(handleCsvShow);
580
+ const render = csv.command("render").description("Start, inspect, or stop a local CSV renderer.").argument("[action]", "start, status, or stop", "start").option("--port <port>", "Local renderer port.", "4174").option("--csv <path>", "CSV path to display.").option("--open", "Open the renderer in a browser.").option("--json", "Emit JSON for status/stop.").action(handleCsvRender);
581
+ render.showHelpAfterError();
582
+ }
583
+ export {
584
+ registerCsvCommands
585
+ };