deepline 0.3.293 → 0.3.295

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-pool.ts +269 -267
  4. package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres.ts +3 -4
  5. package/dist/bundling-sources/shared_libs/play-runtime/tool-http-errors.ts +14 -1
  6. package/dist/cli/auth-EDTRERZP.mjs +31 -0
  7. package/dist/cli/auth-TDHKB277.js +31 -0
  8. package/dist/cli/billing-ELIDPILY.js +1749 -0
  9. package/dist/cli/billing-EXGXJVAU.mjs +1749 -0
  10. package/dist/cli/chunk-2S5Y3TZP.js +5688 -0
  11. package/dist/cli/chunk-3KC45UVF.js +150 -0
  12. package/dist/cli/chunk-3XX5TEA4.js +15 -0
  13. package/dist/cli/chunk-4MBOJQPL.mjs +0 -0
  14. package/dist/cli/chunk-4NEFYBF7.js +2240 -0
  15. package/dist/cli/chunk-5JLQPVNX.js +3056 -0
  16. package/dist/cli/chunk-5KDKFHZI.js +1269 -0
  17. package/dist/cli/chunk-6A3TJUWC.js +76 -0
  18. package/dist/cli/chunk-6O5YZOVN.mjs +890 -0
  19. package/dist/cli/chunk-7P5AA3SN.js +344 -0
  20. package/dist/cli/chunk-AYHLUHE5.js +52 -0
  21. package/dist/cli/chunk-CBVIJSHF.mjs +560 -0
  22. package/dist/cli/chunk-CFVVCN4A.js +735 -0
  23. package/dist/cli/chunk-COGTRVWW.js +30 -0
  24. package/dist/cli/chunk-D4AZUZO4.js +190 -0
  25. package/dist/cli/chunk-DLIRSHV6.mjs +28 -0
  26. package/dist/cli/chunk-EACVZI6N.mjs +1995 -0
  27. package/dist/cli/chunk-EDWJY6T4.mjs +3056 -0
  28. package/dist/cli/chunk-EXMLR72R.mjs +0 -0
  29. package/dist/cli/chunk-F35VOIQL.js +890 -0
  30. package/dist/cli/chunk-GAMFK2ZP.mjs +148 -0
  31. package/dist/cli/chunk-GHRQQPW2.mjs +2240 -0
  32. package/dist/cli/chunk-GONRLVV3.js +3440 -0
  33. package/dist/cli/chunk-GVUJJJ5G.mjs +76 -0
  34. package/dist/cli/chunk-H7HIDGZ7.mjs +150 -0
  35. package/dist/cli/chunk-HUZXWOSK.mjs +503 -0
  36. package/dist/cli/chunk-I5YZLGMG.js +1 -0
  37. package/dist/cli/chunk-ITOFSXIU.mjs +15 -0
  38. package/dist/cli/chunk-J5NA2TTX.js +503 -0
  39. package/dist/cli/chunk-JCS5TPNY.mjs +3440 -0
  40. package/dist/cli/chunk-JNNOCMQY.js +47 -0
  41. package/dist/cli/chunk-KRD6H754.mjs +30 -0
  42. package/dist/cli/chunk-LA46MMTL.js +560 -0
  43. package/dist/cli/chunk-LDWT7RJK.mjs +190 -0
  44. package/dist/cli/chunk-M2V26OR5.js +499 -0
  45. package/dist/cli/chunk-MIMASXO4.mjs +389 -0
  46. package/dist/cli/chunk-MROPCKW2.mjs +190 -0
  47. package/dist/cli/chunk-NXDRDJ4K.js +389 -0
  48. package/dist/cli/chunk-NXGCO4JB.mjs +344 -0
  49. package/dist/cli/chunk-OG64RBAC.js +6 -0
  50. package/dist/cli/chunk-OQYEC4GL.mjs +34 -0
  51. package/dist/cli/chunk-OWJZUE3Y.mjs +103 -0
  52. package/dist/cli/chunk-SDK3ZA2C.js +103 -0
  53. package/dist/cli/chunk-SFLARO4Y.mjs +47 -0
  54. package/dist/cli/chunk-SVIIIYIQ.js +923 -0
  55. package/dist/cli/chunk-TAC3JIFE.mjs +354 -0
  56. package/dist/cli/chunk-U3PI7HBM.js +34 -0
  57. package/dist/cli/chunk-UFS752TU.mjs +52 -0
  58. package/dist/cli/chunk-UI37DQE7.mjs +499 -0
  59. package/dist/cli/chunk-UNEMDKXN.js +1 -0
  60. package/dist/cli/chunk-WB6Z2Q44.mjs +1622 -0
  61. package/dist/cli/chunk-WJYPBHTE.js +148 -0
  62. package/dist/cli/chunk-WOHBA5PV.js +354 -0
  63. package/dist/cli/chunk-WQICC2B3.js +190 -0
  64. package/dist/cli/chunk-WZYKRD7T.mjs +6 -0
  65. package/dist/cli/chunk-XL2FO6CW.mjs +5688 -0
  66. package/dist/cli/chunk-XNYIZMNQ.js +28 -0
  67. package/dist/cli/chunk-XRK2TZT5.js +1995 -0
  68. package/dist/cli/chunk-YJYPL5OK.mjs +1269 -0
  69. package/dist/cli/chunk-YWNDYCXR.mjs +735 -0
  70. package/dist/cli/chunk-YWWAF7KZ.mjs +923 -0
  71. package/dist/cli/chunk-ZDO3TO3M.js +1622 -0
  72. package/dist/cli/client-4JVOYVC5.js +20 -0
  73. package/dist/cli/client-EEN2IJN2.mjs +20 -0
  74. package/dist/cli/csv-BOHBEP2I.mjs +585 -0
  75. package/dist/cli/csv-S5NYRUEX.js +585 -0
  76. package/dist/cli/db-CLODWCOB.mjs +486 -0
  77. package/dist/cli/db-F6PKFOOV.js +486 -0
  78. package/dist/cli/executions-5TQAKLJU.js +28 -0
  79. package/dist/cli/executions-MAKW6QOY.mjs +28 -0
  80. package/dist/cli/feedback-GV4QJFEN.js +107 -0
  81. package/dist/cli/feedback-XY24TW7H.mjs +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-6S2C22T5.js +23 -0
  85. package/dist/cli/git-OZLBD5HH.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-LLCGDPQE.js +157 -0
  89. package/dist/cli/legacy-noops-TYH3TW2D.mjs +157 -0
  90. package/dist/cli/monitors-CABMB4DW.js +3251 -0
  91. package/dist/cli/monitors-TTD55HMK.mjs +3251 -0
  92. package/dist/cli/org-MSF3RG76.js +849 -0
  93. package/dist/cli/org-SFJ77MWY.mjs +849 -0
  94. package/dist/cli/play-NXHJSCKL.mjs +18439 -0
  95. package/dist/cli/play-OKSFNNO4.js +18439 -0
  96. package/dist/cli/providers-QC2ERERL.js +95 -0
  97. package/dist/cli/providers-TIIAZEUA.mjs +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-ICANHLMI.js +69 -0
  101. package/dist/cli/quickstart-KWUOP3FI.mjs +69 -0
  102. package/dist/cli/search-U5H2FDOO.mjs +18 -0
  103. package/dist/cli/search-XQRQOLWS.js +18 -0
  104. package/dist/cli/secrets-3J6YTWFA.mjs +400 -0
  105. package/dist/cli/secrets-YNMNZNOM.js +400 -0
  106. package/dist/cli/sessions-CLEES4L6.mjs +15 -0
  107. package/dist/cli/sessions-J6VR47FG.js +15 -0
  108. package/dist/cli/settings-EEKZMTY4.js +846 -0
  109. package/dist/cli/settings-UVLOQZRH.mjs +846 -0
  110. package/dist/cli/setup-DLMDXPGJ.mjs +1257 -0
  111. package/dist/cli/setup-HC4Q7QM4.js +1257 -0
  112. package/dist/cli/skills-33PHFBSB.mjs +28 -0
  113. package/dist/cli/skills-LFRY3KPX.js +28 -0
  114. package/dist/cli/tools-3COEPKML.mjs +2955 -0
  115. package/dist/cli/tools-QXEVCN45.js +2955 -0
  116. package/dist/cli/update-LSAC4FF5.mjs +28 -0
  117. package/dist/cli/update-NXHSPYXA.js +28 -0
  118. package/dist/cli/workflow-7S44OECF.mjs +1936 -0
  119. package/dist/cli/workflow-QPZWYSZE.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,486 @@
1
+ import {
2
+ DeeplineClient
3
+ } from "./chunk-XL2FO6CW.mjs";
4
+ import "./chunk-CBVIJSHF.mjs";
5
+ import {
6
+ argsWantJson,
7
+ dataExportColumns,
8
+ dataExportCsvString,
9
+ dataExportRows,
10
+ markdownTableFromRows,
11
+ printCommandEnvelope,
12
+ recordRows
13
+ } from "./chunk-6O5YZOVN.mjs";
14
+ import "./chunk-EACVZI6N.mjs";
15
+ import "./chunk-DLIRSHV6.mjs";
16
+ import "./chunk-LDWT7RJK.mjs";
17
+ import "./chunk-GVUJJJ5G.mjs";
18
+ import {
19
+ DeeplineError
20
+ } from "./chunk-NXGCO4JB.mjs";
21
+ import "./chunk-WZYKRD7T.mjs";
22
+ import "./chunk-KRD6H754.mjs";
23
+
24
+ // src/cli/commands/db.ts
25
+ import { readFileSync, writeFileSync } from "fs";
26
+ import { resolve } from "path";
27
+ var CUSTOMER_DB_QUERY_FORMATS = /* @__PURE__ */ new Set(["table", "json", "csv", "markdown"]);
28
+ var CUSTOMER_DB_QUERY_MAX_ROWS = 1e3;
29
+ function parsePositiveInteger(value, flagName) {
30
+ const parsed = Number.parseInt(value, 10);
31
+ if (!Number.isFinite(parsed) || parsed <= 0) {
32
+ throw new Error(`${flagName} must be a positive integer.`);
33
+ }
34
+ return parsed;
35
+ }
36
+ function parseMaxRows(value) {
37
+ const parsed = parsePositiveInteger(value, "--max-rows");
38
+ if (parsed > CUSTOMER_DB_QUERY_MAX_ROWS) {
39
+ throw new Error(
40
+ `--max-rows must be ${CUSTOMER_DB_QUERY_MAX_ROWS} or less. Add LIMIT/OFFSET to page larger exports.`
41
+ );
42
+ }
43
+ return parsed;
44
+ }
45
+ function formatCell(value) {
46
+ if (value === null || value === void 0) return "";
47
+ const text = typeof value === "object" ? JSON.stringify(value) : String(value);
48
+ return text.length > 80 ? `${text.slice(0, 77)}...` : text;
49
+ }
50
+ function tableLines(result) {
51
+ const rows = dataExportRows(customerDbRows(result));
52
+ const responseColumns = dataExportColumns(
53
+ rows,
54
+ customerDbColumnNames(result)
55
+ );
56
+ const businessColumns = responseColumns.filter(
57
+ (column) => !column.startsWith("_")
58
+ );
59
+ const columns = businessColumns.length > 0 ? businessColumns : responseColumns;
60
+ const hiddenColumns = responseColumns.filter(
61
+ (column) => !columns.includes(column)
62
+ );
63
+ const lines = [
64
+ `${result.command} returned ${result.row_count_returned} row(s)` + (result.truncated ? " (truncated)" : "")
65
+ ];
66
+ if (hiddenColumns.length > 0) {
67
+ lines.push(
68
+ `Showing ${columns.length}/${responseColumns.length} columns; hidden metadata: ${hiddenColumns.join(", ")}`
69
+ );
70
+ lines.push(
71
+ "Use --json or select metadata columns explicitly when you need run ids/errors/stages."
72
+ );
73
+ }
74
+ if (rows.length === 0) {
75
+ return lines;
76
+ }
77
+ const widths = columns.map(
78
+ (column) => Math.min(
79
+ 80,
80
+ Math.max(
81
+ column.length,
82
+ ...rows.slice(0, 20).map((row) => formatCell(row[column]).length)
83
+ )
84
+ )
85
+ );
86
+ lines.push(
87
+ columns.map((column, index) => column.padEnd(widths[index])).join(" ")
88
+ );
89
+ lines.push(widths.map((width) => "-".repeat(width)).join(" "));
90
+ for (const row of rows) {
91
+ lines.push(
92
+ columns.map((column, index) => formatCell(row[column]).padEnd(widths[index])).join(" ")
93
+ );
94
+ }
95
+ return lines;
96
+ }
97
+ function customerDbRows(result) {
98
+ return recordRows(result.rows);
99
+ }
100
+ function customerDbColumnNames(result) {
101
+ return result.columns.map((column) => column.name).filter(Boolean);
102
+ }
103
+ function errorMessage(value) {
104
+ return value instanceof Error ? value.message : String(value ?? "");
105
+ }
106
+ function resolveDbQuerySql(rawSql, readFile = (path) => readFileSync(path, "utf8")) {
107
+ const value = rawSql.trim();
108
+ if (!value.startsWith("@")) return value;
109
+ const filePath = value.slice(1).trim();
110
+ if (!filePath) {
111
+ throw new Error("--sql @file requires a file path after `@`.");
112
+ }
113
+ return readFile(resolve(filePath)).trim();
114
+ }
115
+ function collectErrorText(value) {
116
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
117
+ return errorMessage(value);
118
+ }
119
+ const record = value;
120
+ return [
121
+ errorMessage(value),
122
+ typeof record.error === "string" ? record.error : "",
123
+ typeof record.message === "string" ? record.message : "",
124
+ typeof record.detail === "string" ? record.detail : "",
125
+ typeof record.hint === "string" ? record.hint : "",
126
+ typeof record.code === "string" ? record.code : "",
127
+ record.response ? collectErrorText(record.response) : "",
128
+ record.details ? collectErrorText(record.details) : ""
129
+ ].filter(Boolean).join("\n");
130
+ }
131
+ function formatDbQueryError(sql, error) {
132
+ const text = collectErrorText(error);
133
+ const lower = text.toLowerCase();
134
+ const referencesStorage = /"storage"\.|storage\./i.test(sql);
135
+ const runIdColumnMissing = /column\s+"?run_id"?\s+does not exist/i.test(text) || /run_id.*does not exist/i.test(lower);
136
+ const relationMissing = /relation\s+["']?[^"']*storage[^"']*["']?\s+does not exist/i.test(text) || /42p01/i.test(text);
137
+ if (referencesStorage && relationMissing) {
138
+ return [
139
+ "Customer DB query failed: the referenced storage table does not exist.",
140
+ "Play dataset tables are created only when the corresponding ctx.dataset(...).run(...) call executes. Pilot branches, early returns, and runs that fail before the dataset do not create that table.",
141
+ "Use `deepline runs get <run-id> --full --json` to inspect returned dataset handles, then export them with `deepline runs export <run-id> --dataset result.rows --out rows.csv`.",
142
+ `Original error: ${errorMessage(error)}`
143
+ ].join("\n");
144
+ }
145
+ if (referencesStorage && runIdColumnMissing) {
146
+ return [
147
+ "Customer DB query failed: storage dataset tables use `_run_id`, not `run_id`.",
148
+ "Prefer `deepline runs export <run-id> --dataset result.rows --out rows.csv` unless you are doing deep table debugging.",
149
+ `Original error: ${errorMessage(error)}`
150
+ ].join("\n");
151
+ }
152
+ if (error instanceof DeeplineError) {
153
+ return error.message;
154
+ }
155
+ return errorMessage(error);
156
+ }
157
+ function dbRepairHumanLines(result) {
158
+ const repair = result.repair;
159
+ return [
160
+ "Workspace storage repair completed.",
161
+ ...repair ? [
162
+ `Location changed: ${repair.location.changed ? "yes" : "no"}`,
163
+ `Storage contract: ${repair.storage_contract.current ? "current" : "not ready"}`,
164
+ `Runtime migration: ${repair.runtime_migration.current ? "current" : "not ready"}`,
165
+ `Runtime capability probe: ${repair.runtime_capabilities.after.runtime_capabilities_ready ? "passed" : "failed"}`,
166
+ `Materialized table grants reconciled: ${repair.materialized_tables.repaired_count}`
167
+ ] : [
168
+ "Runtime capability probe: unavailable from this server version",
169
+ `Materialized table grants reconciled: ${result.count}`
170
+ ],
171
+ `Runtime role: ${result.connection_grants.runtime_role}`,
172
+ `Customer DB role: ${result.connection_grants.customer_db_role}`
173
+ ];
174
+ }
175
+ function dbRepairPlainText(result) {
176
+ return result.repair ? "Workspace storage repair completed. Runtime capability probe passed.\n" : `Workspace storage repair completed. ${result.count} materialized table grant(s) reconciled; runtime capability probe unavailable.
177
+ `;
178
+ }
179
+ function writeCustomerDbCsv(result, outPath) {
180
+ const resolved = resolve(outPath);
181
+ writeFileSync(
182
+ resolved,
183
+ dataExportCsvString(customerDbRows(result), customerDbColumnNames(result)),
184
+ "utf-8"
185
+ );
186
+ return resolved;
187
+ }
188
+ function dbQueryExportEnvelope(input) {
189
+ const destination = input.outPath ?? "stdout";
190
+ return {
191
+ command: input.result.command,
192
+ format: input.format,
193
+ row_count: input.result.row_count,
194
+ row_count_returned: input.result.row_count_returned,
195
+ truncated: input.result.truncated,
196
+ ...input.outPath ? { file: input.outPath, local: { file: input.outPath } } : {},
197
+ next: { toolEquivalent: input.toolCommand },
198
+ render: {
199
+ sections: [
200
+ {
201
+ title: "customer db export",
202
+ lines: [
203
+ `Rendered ${input.result.row_count_returned} row(s) as ${input.format} to ${destination}`
204
+ ]
205
+ }
206
+ ],
207
+ actions: [{ label: "Tool equivalent", command: input.toolCommand }]
208
+ }
209
+ };
210
+ }
211
+ async function handleDbQuery(args) {
212
+ const sqlIndex = args.indexOf("--sql");
213
+ const rawSql = sqlIndex >= 0 ? args[sqlIndex + 1]?.trim() : "";
214
+ if (!rawSql) {
215
+ console.error(
216
+ 'Usage: deepline db query --sql "select * from table limit 20"|@query.sql [--max-rows N] [--json]'
217
+ );
218
+ return 1;
219
+ }
220
+ let sql;
221
+ try {
222
+ sql = resolveDbQuerySql(rawSql);
223
+ } catch (error) {
224
+ console.error(errorMessage(error));
225
+ return 1;
226
+ }
227
+ if (!sql) {
228
+ console.error("SQL file is empty.");
229
+ return 1;
230
+ }
231
+ const maxRowsIndex = args.indexOf("--max-rows");
232
+ const maxRows = maxRowsIndex >= 0 && args[maxRowsIndex + 1] ? parseMaxRows(args[maxRowsIndex + 1]) : void 0;
233
+ const formatIndex = args.indexOf("--format");
234
+ const format = formatIndex >= 0 ? args[formatIndex + 1]?.trim().toLowerCase() : "";
235
+ if (format && !CUSTOMER_DB_QUERY_FORMATS.has(format)) {
236
+ console.error(
237
+ 'Usage: deepline db query --sql "select * from table limit 20" [--format table|json|csv|markdown] [--out path]'
238
+ );
239
+ return 1;
240
+ }
241
+ const outIndex = args.indexOf("--out");
242
+ const outPath = outIndex >= 0 ? args[outIndex + 1]?.trim() : "";
243
+ if (outIndex >= 0 && !outPath) {
244
+ console.error("--out requires a path.");
245
+ return 1;
246
+ }
247
+ const jsonOutput = argsWantJson(args);
248
+ const explicitJsonOutput = args.includes("--json");
249
+ const client = new DeeplineClient();
250
+ let result;
251
+ try {
252
+ result = await client.db.query({ sql, maxRows });
253
+ } catch (error) {
254
+ console.error(formatDbQueryError(sql, error));
255
+ return 1;
256
+ }
257
+ const toolCommand = `deepline tools execute query_customer_db --payload ${JSON.stringify(
258
+ {
259
+ sql,
260
+ ...maxRows ? { max_rows: maxRows } : {}
261
+ }
262
+ )} --json`;
263
+ if (format === "csv") {
264
+ if (outPath) {
265
+ const exportedPath = writeCustomerDbCsv(result, outPath);
266
+ printCommandEnvelope(
267
+ dbQueryExportEnvelope({
268
+ result,
269
+ format,
270
+ outPath: exportedPath,
271
+ toolCommand
272
+ }),
273
+ {
274
+ json: jsonOutput,
275
+ text: `Exported ${result.row_count_returned} row(s) to ${exportedPath}
276
+ `
277
+ }
278
+ );
279
+ return 0;
280
+ }
281
+ printCommandEnvelope(
282
+ dbQueryExportEnvelope({
283
+ result,
284
+ format,
285
+ outPath: null,
286
+ toolCommand
287
+ }),
288
+ {
289
+ json: explicitJsonOutput,
290
+ text: dataExportCsvString(
291
+ customerDbRows(result),
292
+ customerDbColumnNames(result)
293
+ )
294
+ }
295
+ );
296
+ return 0;
297
+ }
298
+ if (format === "markdown") {
299
+ const content = markdownTableFromRows(
300
+ customerDbRows(result),
301
+ customerDbColumnNames(result)
302
+ );
303
+ if (outPath) {
304
+ const exportedPath = resolve(outPath);
305
+ writeFileSync(exportedPath, content, "utf-8");
306
+ printCommandEnvelope(
307
+ dbQueryExportEnvelope({
308
+ result,
309
+ format,
310
+ outPath: exportedPath,
311
+ toolCommand
312
+ }),
313
+ {
314
+ json: jsonOutput,
315
+ text: `Exported ${result.row_count_returned} row(s) to ${exportedPath}
316
+ `
317
+ }
318
+ );
319
+ return 0;
320
+ }
321
+ printCommandEnvelope(
322
+ dbQueryExportEnvelope({
323
+ result,
324
+ format,
325
+ outPath: null,
326
+ toolCommand
327
+ }),
328
+ {
329
+ json: explicitJsonOutput,
330
+ text: content
331
+ }
332
+ );
333
+ return 0;
334
+ }
335
+ printCommandEnvelope(
336
+ {
337
+ ...result,
338
+ next: { toolEquivalent: toolCommand },
339
+ render: {
340
+ sections: [{ title: "customer db query", lines: tableLines(result) }],
341
+ actions: [{ label: "Tool equivalent", command: toolCommand }]
342
+ }
343
+ },
344
+ {
345
+ json: explicitJsonOutput || format === "json" || format !== "table" && jsonOutput
346
+ }
347
+ );
348
+ return 0;
349
+ }
350
+ async function handleDbRepair(args) {
351
+ const providerIndex = args.indexOf("--provider");
352
+ const provider = providerIndex >= 0 ? args[providerIndex + 1]?.trim() : void 0;
353
+ const jsonOutput = argsWantJson(args);
354
+ const client = new DeeplineClient();
355
+ let result;
356
+ try {
357
+ result = await client.repairIngestionStorage(
358
+ provider ? { provider } : void 0
359
+ );
360
+ } catch (error) {
361
+ if (error instanceof DeeplineError && error.statusCode === 403) {
362
+ console.error(
363
+ "deepline db repair requires org admin. Ask an organization admin to run it."
364
+ );
365
+ return 1;
366
+ }
367
+ console.error(errorMessage(error));
368
+ return 1;
369
+ }
370
+ printCommandEnvelope(
371
+ {
372
+ command: "db repair",
373
+ status: result.status,
374
+ repaired: result.repaired,
375
+ count: result.count,
376
+ connection_grants: result.connection_grants,
377
+ repair: result.repair,
378
+ render: {
379
+ sections: [
380
+ {
381
+ title: "storage contract repair",
382
+ lines: dbRepairHumanLines(result)
383
+ }
384
+ ]
385
+ }
386
+ },
387
+ {
388
+ json: jsonOutput,
389
+ text: dbRepairPlainText(result)
390
+ }
391
+ );
392
+ return 0;
393
+ }
394
+ function registerDbCommands(program) {
395
+ const db = program.command("db").description("Query the tenant customer database.").addHelpText(
396
+ "after",
397
+ `
398
+ Notes:
399
+ Agent-safe SQL for the active workspace customer database.
400
+ Use --sql @query.sql for multiline or shell-sensitive SQL (portable across macOS and Windows).
401
+ Reads: SELECT, EXPLAIN, and read-only WITH can inspect permitted schemas.
402
+ Writes: CREATE TABLE, INSERT, UPDATE, DELETE, ALTER, DROP, TRUNCATE, and
403
+ CREATE INDEX must target schema-qualified storage tables, such as storage.agent_notes.
404
+ If CREATE TABLE blocked (...) fails, use CREATE TABLE storage.blocked (...).
405
+ Results are bounded by the server and --max-rows. Use --json for stable output.
406
+ Use --format csv or --format markdown for agent-readable exports and display tables.
407
+
408
+ Examples:
409
+ deepline db query --sql "select * from companies limit 20"
410
+ deepline db query --sql "select domain, name from companies limit 20" --json
411
+ deepline db query --sql "create table if not exists storage.agent_notes (id text primary key, note text not null)"
412
+ deepline db query --sql "select * from contacts" --max-rows 100 --json
413
+ deepline db query --sql @query.sql --json
414
+ deepline db query --sql "select * from contacts limit 20" --format csv --out contacts.csv
415
+ deepline db query --sql "select domain, name from companies limit 20" --format markdown
416
+ `
417
+ );
418
+ db.command("query").description("Run SQL against the tenant customer database.").addHelpText(
419
+ "after",
420
+ `
421
+ Notes:
422
+ Requires --sql (inline SQL or @file.sql). Output defaults to a compact table in a terminal
423
+ and JSON when stdout is piped. --format table forces a table even in pipes.
424
+ --json overrides --format for stdout. The active auth workspace determines scope.
425
+ Read permitted schemas with SELECT, EXPLAIN, or read-only WITH.
426
+ Write only to schema-qualified storage tables. For example, use
427
+ CREATE TABLE storage.blocked (...) instead of CREATE TABLE blocked (...).
428
+ --format csv and --format markdown are explicit data/display formats and can
429
+ be written directly with --out.
430
+
431
+ Examples:
432
+ deepline db query --sql "select * from companies limit 20"
433
+ deepline db query --sql "select domain, name from companies limit 20" --json
434
+ deepline db query --sql "create table if not exists storage.agent_notes (id text primary key, note text not null)"
435
+ deepline db query --sql "select count(*) from contacts" --json
436
+ deepline db query --sql @query.sql --json
437
+ deepline db query --sql "select * from contacts limit 20" --format csv --out contacts.csv
438
+ deepline db query --sql "select domain, name from companies limit 20" --format markdown
439
+ `
440
+ ).requiredOption("--sql <sql>", "SQL statement").option("--max-rows <n>", "Maximum returned rows").option("--format <format>", "Output format: table, json, csv, or markdown").option("--out <path>", "Write csv or markdown output to a file").option(
441
+ "--json",
442
+ "Emit raw JSON response. Also automatic when stdout is piped"
443
+ ).action(async (options) => {
444
+ process.exitCode = await handleDbQuery([
445
+ "--sql",
446
+ options.sql,
447
+ ...options.maxRows ? ["--max-rows", options.maxRows] : [],
448
+ ...options.format ? ["--format", options.format] : [],
449
+ ...options.out ? ["--out", options.out] : [],
450
+ ...options.json ? ["--json"] : []
451
+ ]);
452
+ });
453
+ db.command("repair").description(
454
+ "Repair this workspace storage contract (role/DB grants). Org admin only."
455
+ ).addHelpText(
456
+ "after",
457
+ `
458
+ Notes:
459
+ Re-establishes tenant runtime and customer-db role grants plus materialized
460
+ table grants for the active workspace. Run this after a play run fails with
461
+ WORKSPACE_STORAGE_NOT_READY, then re-run the play. Requires org admin.
462
+
463
+ Examples:
464
+ deepline db repair
465
+ deepline db repair --json
466
+ `
467
+ ).option(
468
+ "--provider <provider>",
469
+ "Limit materialized-table repair to one provider"
470
+ ).option(
471
+ "--json",
472
+ "Emit raw JSON response. Also automatic when stdout is piped"
473
+ ).action(async (options) => {
474
+ process.exitCode = await handleDbRepair([
475
+ ...options.provider ? ["--provider", options.provider] : [],
476
+ ...options.json ? ["--json"] : []
477
+ ]);
478
+ });
479
+ }
480
+ export {
481
+ dbRepairHumanLines,
482
+ dbRepairPlainText,
483
+ registerDbCommands,
484
+ resolveDbQuerySql,
485
+ writeCustomerDbCsv
486
+ };