deepline 0.3.294 → 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 (136) 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/tool-http-errors.ts +14 -1
  4. package/dist/cli/auth-EDTRERZP.mjs +31 -0
  5. package/dist/cli/auth-TDHKB277.js +31 -0
  6. package/dist/cli/billing-ELIDPILY.js +1749 -0
  7. package/dist/cli/billing-EXGXJVAU.mjs +1749 -0
  8. package/dist/cli/chunk-2S5Y3TZP.js +5688 -0
  9. package/dist/cli/chunk-3KC45UVF.js +150 -0
  10. package/dist/cli/chunk-3XX5TEA4.js +15 -0
  11. package/dist/cli/chunk-4MBOJQPL.mjs +0 -0
  12. package/dist/cli/chunk-4NEFYBF7.js +2240 -0
  13. package/dist/cli/chunk-5JLQPVNX.js +3056 -0
  14. package/dist/cli/chunk-5KDKFHZI.js +1269 -0
  15. package/dist/cli/chunk-6A3TJUWC.js +76 -0
  16. package/dist/cli/chunk-6O5YZOVN.mjs +890 -0
  17. package/dist/cli/chunk-7P5AA3SN.js +344 -0
  18. package/dist/cli/chunk-AYHLUHE5.js +52 -0
  19. package/dist/cli/chunk-CBVIJSHF.mjs +560 -0
  20. package/dist/cli/chunk-CFVVCN4A.js +735 -0
  21. package/dist/cli/chunk-COGTRVWW.js +30 -0
  22. package/dist/cli/chunk-D4AZUZO4.js +190 -0
  23. package/dist/cli/chunk-DLIRSHV6.mjs +28 -0
  24. package/dist/cli/chunk-EACVZI6N.mjs +1995 -0
  25. package/dist/cli/chunk-EDWJY6T4.mjs +3056 -0
  26. package/dist/cli/chunk-EXMLR72R.mjs +0 -0
  27. package/dist/cli/chunk-F35VOIQL.js +890 -0
  28. package/dist/cli/chunk-GAMFK2ZP.mjs +148 -0
  29. package/dist/cli/chunk-GHRQQPW2.mjs +2240 -0
  30. package/dist/cli/chunk-GONRLVV3.js +3440 -0
  31. package/dist/cli/chunk-GVUJJJ5G.mjs +76 -0
  32. package/dist/cli/chunk-H7HIDGZ7.mjs +150 -0
  33. package/dist/cli/chunk-HUZXWOSK.mjs +503 -0
  34. package/dist/cli/chunk-I5YZLGMG.js +1 -0
  35. package/dist/cli/chunk-ITOFSXIU.mjs +15 -0
  36. package/dist/cli/chunk-J5NA2TTX.js +503 -0
  37. package/dist/cli/chunk-JCS5TPNY.mjs +3440 -0
  38. package/dist/cli/chunk-JNNOCMQY.js +47 -0
  39. package/dist/cli/chunk-KRD6H754.mjs +30 -0
  40. package/dist/cli/chunk-LA46MMTL.js +560 -0
  41. package/dist/cli/chunk-LDWT7RJK.mjs +190 -0
  42. package/dist/cli/chunk-M2V26OR5.js +499 -0
  43. package/dist/cli/chunk-MIMASXO4.mjs +389 -0
  44. package/dist/cli/chunk-MROPCKW2.mjs +190 -0
  45. package/dist/cli/chunk-NXDRDJ4K.js +389 -0
  46. package/dist/cli/chunk-NXGCO4JB.mjs +344 -0
  47. package/dist/cli/chunk-OG64RBAC.js +6 -0
  48. package/dist/cli/chunk-OQYEC4GL.mjs +34 -0
  49. package/dist/cli/chunk-OWJZUE3Y.mjs +103 -0
  50. package/dist/cli/chunk-SDK3ZA2C.js +103 -0
  51. package/dist/cli/chunk-SFLARO4Y.mjs +47 -0
  52. package/dist/cli/chunk-SVIIIYIQ.js +923 -0
  53. package/dist/cli/chunk-TAC3JIFE.mjs +354 -0
  54. package/dist/cli/chunk-U3PI7HBM.js +34 -0
  55. package/dist/cli/chunk-UFS752TU.mjs +52 -0
  56. package/dist/cli/chunk-UI37DQE7.mjs +499 -0
  57. package/dist/cli/chunk-UNEMDKXN.js +1 -0
  58. package/dist/cli/chunk-WB6Z2Q44.mjs +1622 -0
  59. package/dist/cli/chunk-WJYPBHTE.js +148 -0
  60. package/dist/cli/chunk-WOHBA5PV.js +354 -0
  61. package/dist/cli/chunk-WQICC2B3.js +190 -0
  62. package/dist/cli/chunk-WZYKRD7T.mjs +6 -0
  63. package/dist/cli/chunk-XL2FO6CW.mjs +5688 -0
  64. package/dist/cli/chunk-XNYIZMNQ.js +28 -0
  65. package/dist/cli/chunk-XRK2TZT5.js +1995 -0
  66. package/dist/cli/chunk-YJYPL5OK.mjs +1269 -0
  67. package/dist/cli/chunk-YWNDYCXR.mjs +735 -0
  68. package/dist/cli/chunk-YWWAF7KZ.mjs +923 -0
  69. package/dist/cli/chunk-ZDO3TO3M.js +1622 -0
  70. package/dist/cli/client-4JVOYVC5.js +20 -0
  71. package/dist/cli/client-EEN2IJN2.mjs +20 -0
  72. package/dist/cli/csv-BOHBEP2I.mjs +585 -0
  73. package/dist/cli/csv-S5NYRUEX.js +585 -0
  74. package/dist/cli/db-CLODWCOB.mjs +486 -0
  75. package/dist/cli/db-F6PKFOOV.js +486 -0
  76. package/dist/cli/executions-5TQAKLJU.js +28 -0
  77. package/dist/cli/executions-MAKW6QOY.mjs +28 -0
  78. package/dist/cli/feedback-GV4QJFEN.js +107 -0
  79. package/dist/cli/feedback-XY24TW7H.mjs +107 -0
  80. package/dist/cli/getting-started.js +18 -76
  81. package/dist/cli/getting-started.mjs +10 -37
  82. package/dist/cli/git-6S2C22T5.js +23 -0
  83. package/dist/cli/git-OZLBD5HH.mjs +23 -0
  84. package/dist/cli/index.js +291 -54294
  85. package/dist/cli/index.mjs +209 -54352
  86. package/dist/cli/legacy-noops-LLCGDPQE.js +157 -0
  87. package/dist/cli/legacy-noops-TYH3TW2D.mjs +157 -0
  88. package/dist/cli/monitors-CABMB4DW.js +3251 -0
  89. package/dist/cli/monitors-TTD55HMK.mjs +3251 -0
  90. package/dist/cli/org-MSF3RG76.js +849 -0
  91. package/dist/cli/org-SFJ77MWY.mjs +849 -0
  92. package/dist/cli/play-NXHJSCKL.mjs +18439 -0
  93. package/dist/cli/play-OKSFNNO4.js +18439 -0
  94. package/dist/cli/providers-QC2ERERL.js +95 -0
  95. package/dist/cli/providers-TIIAZEUA.mjs +95 -0
  96. package/dist/cli/proxy-env-EBANZHPV.js +161 -0
  97. package/dist/cli/proxy-env-M4ZHXHRL.mjs +161 -0
  98. package/dist/cli/quickstart-ICANHLMI.js +69 -0
  99. package/dist/cli/quickstart-KWUOP3FI.mjs +69 -0
  100. package/dist/cli/search-U5H2FDOO.mjs +18 -0
  101. package/dist/cli/search-XQRQOLWS.js +18 -0
  102. package/dist/cli/secrets-3J6YTWFA.mjs +400 -0
  103. package/dist/cli/secrets-YNMNZNOM.js +400 -0
  104. package/dist/cli/sessions-CLEES4L6.mjs +15 -0
  105. package/dist/cli/sessions-J6VR47FG.js +15 -0
  106. package/dist/cli/settings-EEKZMTY4.js +846 -0
  107. package/dist/cli/settings-UVLOQZRH.mjs +846 -0
  108. package/dist/cli/setup-DLMDXPGJ.mjs +1257 -0
  109. package/dist/cli/setup-HC4Q7QM4.js +1257 -0
  110. package/dist/cli/skills-33PHFBSB.mjs +28 -0
  111. package/dist/cli/skills-LFRY3KPX.js +28 -0
  112. package/dist/cli/tools-3COEPKML.mjs +2955 -0
  113. package/dist/cli/tools-QXEVCN45.js +2955 -0
  114. package/dist/cli/update-LSAC4FF5.mjs +28 -0
  115. package/dist/cli/update-NXHSPYXA.js +28 -0
  116. package/dist/cli/workflow-7S44OECF.mjs +1936 -0
  117. package/dist/cli/workflow-QPZWYSZE.js +1936 -0
  118. package/dist/helpers.js +6 -32
  119. package/dist/helpers.mjs +2 -0
  120. package/dist/index.js +1972 -12825
  121. package/dist/index.mjs +1910 -12672
  122. package/dist/install-integrity.json +110 -0
  123. package/dist/monitor-fleet-contract.js +31 -730
  124. package/dist/monitor-fleet-contract.mjs +18 -667
  125. package/dist/monitor-input-contract.js +10 -390
  126. package/dist/monitor-input-contract.mjs +7 -348
  127. package/dist/plays/bundle-play-file.mjs +13 -5178
  128. package/dist/plays/csv-data-input.js +5 -3132
  129. package/dist/plays/csv-data-input.mjs +5 -3105
  130. package/dist/plays/run-request.js +56 -664
  131. package/dist/plays/run-request.mjs +30 -588
  132. package/dist/release.d.mts +1 -1
  133. package/dist/release.d.ts +1 -1
  134. package/dist/release.js +5 -212
  135. package/dist/release.mjs +5 -185
  136. package/package.json +1 -1
@@ -0,0 +1,3251 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _class2;require('./chunk-I5YZLGMG.js');
2
+
3
+
4
+ var _chunk2S5Y3TZPjs = require('./chunk-2S5Y3TZP.js');
5
+ require('./chunk-LA46MMTL.js');
6
+
7
+
8
+
9
+ var _chunkJ5NA2TTXjs = require('./chunk-J5NA2TTX.js');
10
+ require('./chunk-UNEMDKXN.js');
11
+
12
+
13
+ var _chunkWOHBA5PVjs = require('./chunk-WOHBA5PV.js');
14
+
15
+
16
+
17
+
18
+
19
+ var _chunkF35VOIQLjs = require('./chunk-F35VOIQL.js');
20
+
21
+
22
+ var _chunkXRK2TZT5js = require('./chunk-XRK2TZT5.js');
23
+ require('./chunk-XNYIZMNQ.js');
24
+ require('./chunk-D4AZUZO4.js');
25
+ require('./chunk-6A3TJUWC.js');
26
+
27
+
28
+ var _chunk7P5AA3SNjs = require('./chunk-7P5AA3SN.js');
29
+ require('./chunk-OG64RBAC.js');
30
+ require('./chunk-COGTRVWW.js');
31
+
32
+ // src/cli/commands/monitors.ts
33
+ var _crypto = require('crypto');
34
+ var _fs = require('fs');
35
+ var _path = require('path');
36
+ var _promises = require('readline/promises');
37
+ var JSON_OPTION_DESCRIPTION = "Emit JSON output. Also automatic when stdout is piped";
38
+ function withJsonOption(command) {
39
+ return command.option("--json", JSON_OPTION_DESCRIPTION);
40
+ }
41
+ var COMPACT_OPTION_DESCRIPTION = "Ask the server for high-signal fields only (smaller output for agent loops)";
42
+ var MonitorsUsageError = (_class = class extends Error {
43
+ __init() {this.code = "MONITORS_USAGE_ERROR"}
44
+ constructor(message) {
45
+ super(message);_class.prototype.__init.call(this);;
46
+ this.name = "MonitorsUsageError";
47
+ }
48
+ }, _class);
49
+ var MonitorDryRunUnsupportedError = (_class2 = class extends Error {
50
+ __init2() {this.code = "MONITOR_DRY_RUN_UNSUPPORTED"}
51
+ constructor(message) {
52
+ super(message);_class2.prototype.__init2.call(this);;
53
+ this.name = "MonitorDryRunUnsupportedError";
54
+ }
55
+ }, _class2);
56
+ function monitorsErrorExitCode(error) {
57
+ if (error instanceof MonitorsUsageError) return 2;
58
+ if (error instanceof MonitorFleetStateError) return 6;
59
+ if (error instanceof _chunkXRK2TZT5js.AuthError) return 3;
60
+ if (error instanceof _chunk7P5AA3SNjs.DeeplineError) {
61
+ const status = error.statusCode;
62
+ if (status === 401 || status === 403) return 3;
63
+ if (status === 404) return 4;
64
+ if (status === 400 || status === 409 || status === 422) return 7;
65
+ return 5;
66
+ }
67
+ return 5;
68
+ }
69
+ function monitorsFailureNextCommand(error, exitCode, options) {
70
+ if (error instanceof MonitorFleetStateError) return error.next;
71
+ if (error instanceof _chunk7P5AA3SNjs.DeeplineError) {
72
+ const response = asRecord(_optionalChain([asRecord, 'call', _ => _(error.details), 'optionalAccess', _2 => _2.response]));
73
+ const serverNext = _nullishCoalesce(asString(_optionalChain([response, 'optionalAccess', _3 => _3.next])), () => ( asString(_optionalChain([response, 'optionalAccess', _4 => _4.next_action]))));
74
+ if (serverNext) return serverNext;
75
+ }
76
+ if (exitCode === 5 && _optionalChain([options, 'optionalAccess', _5 => _5.retryCommand])) return options.retryCommand;
77
+ if (error instanceof _chunk7P5AA3SNjs.DeeplineError && error.code === "monitor_access_required") {
78
+ return "deepline monitors status";
79
+ }
80
+ if (error instanceof _chunk7P5AA3SNjs.DeeplineError && error.code === "monitor_tool_not_found") {
81
+ return "deepline monitors available --json";
82
+ }
83
+ if (exitCode === 3) return "deepline auth status --json";
84
+ if (exitCode === 4) return "deepline monitors list --status all --json";
85
+ return void 0;
86
+ }
87
+ function readValidationIssues(error) {
88
+ if (!(error instanceof _chunk7P5AA3SNjs.DeeplineError)) return [];
89
+ const response = asRecord(_optionalChain([asRecord, 'call', _6 => _6(error.details), 'optionalAccess', _7 => _7.response]));
90
+ const issues = Array.isArray(_optionalChain([response, 'optionalAccess', _8 => _8.issues])) ? response.issues : [];
91
+ return issues.flatMap((raw) => {
92
+ const issue = asRecord(raw);
93
+ if (!issue) return [];
94
+ return [
95
+ {
96
+ ...asString(issue.path) ? { path: asString(issue.path) } : {},
97
+ ...asString(issue.message) ? { message: asString(issue.message) } : {}
98
+ }
99
+ ];
100
+ });
101
+ }
102
+ function reportMonitorsFailure(error, options) {
103
+ const exitCode = monitorsErrorExitCode(error);
104
+ const next = monitorsFailureNextCommand(error, exitCode, options);
105
+ const retrySafe = exitCode === 5 && _optionalChain([options, 'optionalAccess', _9 => _9.retryCommand]) !== void 0;
106
+ const wantsJson = _chunkF35VOIQLjs.shouldEmitJson.call(void 0, process.argv.includes("--json"));
107
+ if (wantsJson) {
108
+ const payload = _chunkF35VOIQLjs.errorToJsonPayload.call(void 0, error);
109
+ _chunkF35VOIQLjs.printJson.call(void 0, {
110
+ ok: false,
111
+ exitCode,
112
+ ...next ? { next } : {},
113
+ ...retrySafe ? { retry_safe: true } : {},
114
+ error: retrySafe ? {
115
+ ...payload.error,
116
+ message: `${payload.error.message} ${FLEET_RETRY_SAFE_NOTE}`
117
+ } : payload.error
118
+ });
119
+ } else {
120
+ const base = error instanceof Error ? error.message : String(error);
121
+ const message = retrySafe ? `${base} ${FLEET_RETRY_SAFE_NOTE}` : base;
122
+ process.stderr.write(`Error: ${message}
123
+ `);
124
+ for (const issue of readValidationIssues(error)) {
125
+ process.stderr.write(
126
+ ` - ${issue.path ? `${issue.path}: ` : ""}${_nullishCoalesce(issue.message, () => ( ""))}
127
+ `
128
+ );
129
+ }
130
+ if (next) process.stderr.write(`Next: ${next}
131
+ `);
132
+ }
133
+ process.exitCode = exitCode;
134
+ }
135
+ function monitorsAction(handler) {
136
+ return async (...args) => {
137
+ try {
138
+ await handler(...args);
139
+ } catch (error) {
140
+ reportMonitorsFailure(error);
141
+ }
142
+ };
143
+ }
144
+ function parseJsonObjectArg(raw, argLabel) {
145
+ let parsed;
146
+ try {
147
+ parsed = JSON.parse(raw);
148
+ } catch (error) {
149
+ throw new MonitorsUsageError(
150
+ `${argLabel} must be a JSON object. ${error instanceof Error ? error.message : String(error)}`
151
+ );
152
+ }
153
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
154
+ throw new MonitorsUsageError(`${argLabel} must be a JSON object.`);
155
+ }
156
+ return parsed;
157
+ }
158
+ function resolveMonitorJsonBody(input) {
159
+ const readFile = _nullishCoalesce(input.readFile, () => ( ((path) => _fs.readFileSync.call(void 0, path, "utf-8"))));
160
+ const readStdin = _nullishCoalesce(input.readStdin, () => ( (() => _fs.readFileSync.call(void 0, 0, "utf-8"))));
161
+ if (input.positional !== void 0 && input.file !== void 0) {
162
+ throw new MonitorsUsageError(
163
+ `Pass exactly one source for ${input.argLabel}: the positional JSON or --file, not both.`
164
+ );
165
+ }
166
+ if (input.positional !== void 0) {
167
+ return parseJsonObjectArg(input.positional, input.argLabel);
168
+ }
169
+ if (input.file !== void 0) {
170
+ if (input.file === "-") {
171
+ return parseJsonObjectArg(readStdin(), `${input.argLabel} (stdin)`);
172
+ }
173
+ let raw;
174
+ try {
175
+ raw = readFile(input.file);
176
+ } catch (error) {
177
+ throw new MonitorsUsageError(
178
+ `Could not read --file ${input.file}: ${error instanceof Error ? error.message : String(error)}`
179
+ );
180
+ }
181
+ return parseJsonObjectArg(raw, `${input.argLabel} (--file ${input.file})`);
182
+ }
183
+ throw new MonitorsUsageError(
184
+ `${input.command} needs ${input.argLabel} (a JSON object). Pass it positionally:
185
+ ${input.command} '{"key":"job-openings","tool":"deepline_native.company_radar","payload":{"domain":"stripe.com","radar_type":"company_job_openings"}}'
186
+ or from a file / stdin:
187
+ ${input.command} --file monitor.json
188
+ cat monitor.json | ${input.command} --file -`
189
+ );
190
+ }
191
+ function asRecord(value) {
192
+ return value && typeof value === "object" && !Array.isArray(value) ? value : null;
193
+ }
194
+ function asString(value) {
195
+ return typeof value === "string" && value.trim() ? value : void 0;
196
+ }
197
+ var MONITOR_STATES = /* @__PURE__ */ new Set([
198
+ "active",
199
+ "billing_suspended",
200
+ "disabled"
201
+ ]);
202
+ function customerMonitorState(value) {
203
+ if (typeof value === "string" && MONITOR_STATES.has(value)) {
204
+ return value;
205
+ }
206
+ return void 0;
207
+ }
208
+ function readMonitorState(record) {
209
+ const state = customerMonitorState(record.state);
210
+ if (state) return state;
211
+ const legacyStatus = asString(record.status);
212
+ if (legacyStatus === "active") return "active";
213
+ if (legacyStatus === "billing_suspended") return "billing_suspended";
214
+ if (legacyStatus === "disabled") return "disabled";
215
+ if (legacyStatus === "inactive") return "disabled";
216
+ if (typeof record.active === "boolean") {
217
+ return record.active ? "active" : "disabled";
218
+ }
219
+ return void 0;
220
+ }
221
+ function monitorStateFilter(value) {
222
+ if (value === "all") return "all";
223
+ return customerMonitorState(value);
224
+ }
225
+ function monitorStateFilterLabel(value, fallback = "active") {
226
+ const canonical = monitorStateFilter(value);
227
+ if (canonical) return canonical;
228
+ if (value === "inactive") return "disabled";
229
+ return fallback;
230
+ }
231
+ function asFiniteNumber(value) {
232
+ return typeof value === "number" && Number.isFinite(value) ? value : void 0;
233
+ }
234
+ function monitorPricingLine(rawPricing) {
235
+ const pricing = asRecord(rawPricing);
236
+ if (!pricing) return void 0;
237
+ const display = asString(pricing.display);
238
+ if (display) return display;
239
+ const credits = asFiniteNumber(pricing.deepline_credits);
240
+ const basis = asString(pricing.billing_basis);
241
+ if (credits === void 0 || !basis) return void 0;
242
+ return `${credits} Deepline credits (${basis.replaceAll("_", " ")})`;
243
+ }
244
+ function yesNo(value) {
245
+ if (value === true) return "yes";
246
+ if (value === false) return "no";
247
+ return "unknown";
248
+ }
249
+ function readDeployOutputContract(payload) {
250
+ const contract = asRecord(payload.output_contract);
251
+ if (!contract) return { streams: [] };
252
+ const rawOutputs = Array.isArray(contract.outputs) ? contract.outputs : [];
253
+ const streams = rawOutputs.flatMap((raw) => {
254
+ const output = asRecord(raw);
255
+ const stream = output ? asString(output.stream) : void 0;
256
+ const table = output ? asString(output.table) : void 0;
257
+ if (!output || !stream || !table) return [];
258
+ const columns = Array.isArray(output.columns) ? output.columns.flatMap((rawColumn) => {
259
+ const column = asRecord(rawColumn);
260
+ const name = column ? asString(column.name) : void 0;
261
+ return name ? [name] : [];
262
+ }) : [];
263
+ return [
264
+ {
265
+ stream,
266
+ table,
267
+ columns,
268
+ isEvent: output.is_event_stream === true,
269
+ matchesPayload: output.matches_payload === true
270
+ }
271
+ ];
272
+ });
273
+ return { tool: asString(contract.tool), streams };
274
+ }
275
+ function renderDeployReplacementWarning(input) {
276
+ const summary = asRecord(input.payload.change_summary);
277
+ const upstream = summary ? asRecord(summary.upstream) : void 0;
278
+ if (!summary || !upstream || upstream.resource_replaced !== true) return [];
279
+ const definition = asRecord(summary.definition);
280
+ const changed = definition && Array.isArray(definition.changed) ? definition.changed : [];
281
+ const lines = [
282
+ input.completed ? "WARNING: this deploy replaced the existing upstream monitor." : "WARNING: this deploy replaces the existing upstream monitor.",
283
+ "Existing Customer DB rows are preserved. Provider backfill is not implied."
284
+ ];
285
+ for (const raw of changed) {
286
+ const item = asRecord(raw);
287
+ const path = item ? asString(item.path) : void 0;
288
+ if (!item || !path) continue;
289
+ lines.push(
290
+ ` ${path}: ${JSON.stringify(_nullishCoalesce(item.before, () => ( null)))} \u2192 ${JSON.stringify(
291
+ _nullishCoalesce(item.after, () => ( null))
292
+ )}`
293
+ );
294
+ }
295
+ lines.push(
296
+ input.monitorKey ? `Use \`deepline monitors update ${input.monitorKey} <patch>\` for a patch-style change.` : "Use `deepline monitors update <key> <patch>` for a patch-style change."
297
+ );
298
+ return lines;
299
+ }
300
+ function renderDeployFilterRemovalWarning(payload) {
301
+ const summary = asRecord(payload.change_summary);
302
+ const definition = summary ? asRecord(summary.definition) : void 0;
303
+ const changed = definition && Array.isArray(definition.changed) ? definition.changed : [];
304
+ const removed = changed.some((raw) => {
305
+ const item = asRecord(raw);
306
+ return asString(_optionalChain([item, 'optionalAccess', _10 => _10.path])) === "payload.job_titles" && _optionalChain([item, 'optionalAccess', _11 => _11.before]) != null && item.after == null;
307
+ });
308
+ return removed ? [
309
+ "WARNING: this full deploy removes the job_titles filter.",
310
+ "Future findings will be unfiltered. Existing Customer DB rows are preserved.",
311
+ 'Use `deepline monitors update <key> {"payload":{"job_titles":"..."}}` to change only the filter.'
312
+ ] : [];
313
+ }
314
+ function renderMonitorDeployCompletion(payload) {
315
+ const monitor = asRecord(payload.monitor);
316
+ const key = monitor ? asString(monitor.key) : void 0;
317
+ const { tool, streams } = readDeployOutputContract(payload);
318
+ if (!key || streams.length === 0) return void 0;
319
+ const toolId = _nullishCoalesce(_nullishCoalesce(tool, () => ( (monitor ? asString(monitor.tool) : void 0))), () => ( "<tool>"));
320
+ const name = monitor ? asString(monitor.name) : void 0;
321
+ const state = monitor ? readMonitorState(monitor) : void 0;
322
+ const pricingLine = monitorPricingLine(_nullishCoalesce(_optionalChain([monitor, 'optionalAccess', _12 => _12.pricing]), () => ( payload.pricing)));
323
+ const eventStreams = streams.filter((stream) => stream.isEvent);
324
+ const matched = eventStreams.filter((stream) => stream.matchesPayload);
325
+ const shown = matched.length ? matched : eventStreams.length ? eventStreams : streams;
326
+ const primary = shown[0];
327
+ const lines = [
328
+ `\u2713 Deployed monitor "${key}"${name ? ` (${name})` : ""} \u2014 tool ${toolId}${state ? `, status ${state}` : ""}`,
329
+ "",
330
+ "Output \u2192 Customer DB:"
331
+ ];
332
+ for (const stream of shown) {
333
+ lines.push(` ${stream.table} (stream: ${stream.stream})`);
334
+ lines.push(
335
+ ` columns: ${stream.columns.length ? stream.columns.join(", ") : "(promoted dynamically as events arrive)"}`
336
+ );
337
+ }
338
+ if (pricingLine) {
339
+ lines.push("", `Pricing: ${pricingLine}`);
340
+ }
341
+ const replacementWarning = renderDeployReplacementWarning({
342
+ payload,
343
+ completed: true,
344
+ monitorKey: key
345
+ });
346
+ if (replacementWarning.length) lines.push("", ...replacementWarning);
347
+ const filterRemovalWarning = renderDeployFilterRemovalWarning(payload);
348
+ if (filterRemovalWarning.length) lines.push("", ...filterRemovalWarning);
349
+ const guidance = asRecord(payload.setup_guidance);
350
+ if (guidance) {
351
+ const callbackUrl = asString(guidance.callback_url);
352
+ const steps = Array.isArray(guidance.steps) ? guidance.steps : [];
353
+ const docs = Array.isArray(guidance.documentation) ? guidance.documentation : [];
354
+ lines.push("", _nullishCoalesce(asString(guidance.title), () => ( "Provider setup:")));
355
+ if (callbackUrl) lines.push(` Callback URL: ${callbackUrl}`);
356
+ for (const step of steps)
357
+ if (asString(step)) lines.push(` \u2022 ${asString(step)}`);
358
+ for (const raw of docs) {
359
+ const doc = asRecord(raw);
360
+ const label = asString(_optionalChain([doc, 'optionalAccess', _13 => _13.label]));
361
+ const url = asString(_optionalChain([doc, 'optionalAccess', _14 => _14.url]));
362
+ if (label && url) lines.push(` Docs: ${label} \u2014 ${url}`);
363
+ }
364
+ const payloadExample = asRecord(guidance.payload_example);
365
+ if (payloadExample) {
366
+ lines.push(` Payload example: ${JSON.stringify(payloadExample)}`);
367
+ }
368
+ }
369
+ lines.push(
370
+ "",
371
+ "This monitor streams new rows into your Customer DB \u2014 there is no manual run.",
372
+ "Next:",
373
+ " \u2022 Query the table above directly, or",
374
+ " \u2022 Run a play on each new row (third arg to definePlay in your .play.ts):",
375
+ ` sqlListeners: [{ id: '${primary.stream}', tool: '${toolId}', stream: '${primary.stream}', operations: ['INSERT'] }]`,
376
+ " The changed row arrives to your handler as the sqlListener event's `after`.",
377
+ "",
378
+ "Reuse: many plays can bind to this one stream \u2014 you do NOT need a separate",
379
+ "monitor per play. Before deploying another monitor on this tool, run",
380
+ "`deepline monitors list` and reuse an existing one that covers your scope."
381
+ );
382
+ return `${lines.join("\n")}
383
+ `;
384
+ }
385
+ function renderMonitorDeployPlan(payload) {
386
+ const valid = payload.valid !== false;
387
+ const lines = [
388
+ "DRY RUN \u2014 nothing was deployed.",
389
+ valid ? "Definition: valid" : "Definition: INVALID"
390
+ ];
391
+ if (!valid) {
392
+ const issues = Array.isArray(payload.issues) ? payload.issues : [];
393
+ for (const raw of issues) {
394
+ const issue = asRecord(raw);
395
+ const path = issue ? asString(issue.path) : void 0;
396
+ const message = issue ? asString(issue.message) : void 0;
397
+ if (message) lines.push(` - ${path ? `${path}: ` : ""}${message}`);
398
+ }
399
+ }
400
+ const replacementWarning = renderDeployReplacementWarning({
401
+ payload,
402
+ completed: false
403
+ });
404
+ if (replacementWarning.length) lines.push("", ...replacementWarning);
405
+ const filterRemovalWarning = renderDeployFilterRemovalWarning(payload);
406
+ if (filterRemovalWarning.length) lines.push("", ...filterRemovalWarning);
407
+ const estimate = asRecord(payload.deploy_cost_estimate);
408
+ const credits = estimate ? asFiniteNumber(estimate.credits) : void 0;
409
+ if (credits !== void 0) {
410
+ const note = estimate ? asString(estimate.note) : void 0;
411
+ lines.push(
412
+ `Deploy cost: would cost ${credits} Deepline credits${note ? ` \u2014 ${note}` : ""}.`
413
+ );
414
+ } else {
415
+ lines.push(
416
+ "Deploy cost: estimate unavailable from this server (validation only)."
417
+ );
418
+ }
419
+ const pricingLine = monitorPricingLine(payload.pricing);
420
+ if (pricingLine) {
421
+ lines.push(`Selected pricing: ${pricingLine}`);
422
+ }
423
+ const candidates = Array.isArray(payload.reuse_candidates) ? payload.reuse_candidates : [];
424
+ const candidateLines = candidates.flatMap((raw) => {
425
+ const candidate = asRecord(raw);
426
+ const key = candidate ? asString(candidate.key) : void 0;
427
+ if (!candidate || !key) return [];
428
+ const name = asString(candidate.name);
429
+ const state = readMonitorState(candidate);
430
+ const covers = asString(candidate.covers);
431
+ return [
432
+ ` ${key}${name ? ` (${name})` : ""}${state ? ` \u2014 ${state}` : ""}${covers ? `; covers ${covers}` : ""}`
433
+ ];
434
+ });
435
+ if (candidateLines.length > 0) {
436
+ lines.push(
437
+ "",
438
+ "You may already have a monitor covering this \u2014 check before deploying:",
439
+ ...candidateLines,
440
+ " Inspect: deepline monitors get <key> --json"
441
+ );
442
+ }
443
+ const identityConflict = asRecord(payload.identity_conflict);
444
+ const identityOwner = identityConflict ? asRecord(identityConflict.existing_monitor) : null;
445
+ const identityOwnerKey = identityOwner ? asString(identityOwner.key) : void 0;
446
+ const identityOwnerStatus = identityOwner ? asString(identityOwner.status) : void 0;
447
+ if (identityConflict) {
448
+ if (identityOwnerStatus === "provisioning") {
449
+ lines.push(
450
+ "",
451
+ "An in-progress provider operation owns this upstream identity.",
452
+ "Do not deploy this key yet. Wait, then rerun this dry run."
453
+ );
454
+ } else if (identityOwnerKey) {
455
+ lines.push(
456
+ "",
457
+ `An existing monitor owns this upstream identity: ${identityOwnerKey}.`,
458
+ `Inspect: deepline monitors get ${identityOwnerKey} --json`,
459
+ "Do not deploy this key unless that conflict is resolved."
460
+ );
461
+ } else {
462
+ lines.push(
463
+ "",
464
+ "An existing monitor owns this upstream identity.",
465
+ "Do not deploy this key until that conflict is resolved."
466
+ );
467
+ }
468
+ }
469
+ lines.push(
470
+ "",
471
+ identityConflict ? "Do not deploy for real until this identity conflict clears." : valid ? "Deploy for real: re-run this command without --dry-run." : "Fix the definition, then re-run this command."
472
+ );
473
+ return `${lines.join("\n")}
474
+ `;
475
+ }
476
+ function renderMonitorDeletePlan(payload, fallbackKey) {
477
+ const plan = asRecord(payload.plan);
478
+ const key = _nullishCoalesce((plan ? asString(plan.monitor_key) : void 0), () => ( fallbackKey));
479
+ const lines = [
480
+ "DRY RUN \u2014 nothing was deleted.",
481
+ `Delete plan for monitor "${key}":`,
482
+ ` delete Deepline record: ${yesNo(_optionalChain([plan, 'optionalAccess', _15 => _15.would_delete_record]))}`,
483
+ ` deprovision upstream provider resource: ${yesNo(_optionalChain([plan, 'optionalAccess', _16 => _16.would_deprovision_upstream]))}`,
484
+ "",
485
+ `Delete for real: deepline monitors delete ${key} --yes`
486
+ ];
487
+ return `${lines.join("\n")}
488
+ `;
489
+ }
490
+ function renderMonitorReactivatePlan(payload, key) {
491
+ const estimate = asRecord(payload.cost_estimate);
492
+ const credits = estimate ? asFiniteNumber(estimate.credits) : void 0;
493
+ const monitor = asRecord(payload.monitor);
494
+ const tool = monitor ? asString(monitor.tool) : void 0;
495
+ const hasTamradarHistoricalCatchup = tool === "deepline_native.company_radar" || tool === "deepline_native.contact_radar" || tool === "deepline_native.industry_radar";
496
+ const lines = [
497
+ "DRY RUN \u2014 nothing was reactivated.",
498
+ credits !== void 0 ? `Reactivate cost: would cost ${credits} Deepline credits.` : "Reactivate cost: estimate unavailable from this server.",
499
+ ...hasTamradarHistoricalCatchup ? [
500
+ "Source boundary: ordinary reactivation starts at provider creation. Saved updates_since values are not forwarded during reactivation."
501
+ ] : [],
502
+ "",
503
+ `Reactivate for real: deepline monitors reactivate ${key}`
504
+ ];
505
+ return `${lines.join("\n")}
506
+ `;
507
+ }
508
+ function assertMonitorDryRunAcknowledged(payload, context) {
509
+ if (payload.dry_run === true) return;
510
+ throw new MonitorDryRunUnsupportedError(
511
+ `${context.command} --dry-run: the server response did not acknowledge dry-run mode (missing "dry_run": true). This Deepline server may not support --dry-run for ${context.mutation}, so the response cannot be trusted as a plan. Nothing was rendered as a plan. Verify current state with \`deepline monitors get <key> --json\`, and re-run without --dry-run only when you intend the real ${context.mutation}.`
512
+ );
513
+ }
514
+ function monitorDeleteRequiresYesError(key) {
515
+ return new MonitorsUsageError(
516
+ `monitors delete is destructive: it deletes monitor "${key}" and deprovisions its upstream provider resource. Non-interactive runs must confirm with --yes:
517
+ deepline monitors delete ${key} --yes
518
+ Preview the plan first with:
519
+ deepline monitors delete ${key} --dry-run`
520
+ );
521
+ }
522
+ async function handleMonitorsStatus(options) {
523
+ const payload = await new (0, _chunk2S5Y3TZPjs.DeeplineClient)().monitors.status();
524
+ const hasAccess = payload.has_access === true;
525
+ const reason = typeof payload.reason === "string" && payload.reason.trim() ? payload.reason.trim() : void 0;
526
+ const text = hasAccess ? `\u2713 You have access to Deepline Monitors${reason ? `
527
+ ${reason}` : ""}
528
+ ` : `\u2717 No access to Deepline Monitors${reason ? ` \u2014 ${reason}` : ""}
529
+ `;
530
+ _chunkF35VOIQLjs.printCommandEnvelope.call(void 0,
531
+ { has_access: hasAccess, ...reason ? { reason } : {} },
532
+ { json: options.json, text }
533
+ );
534
+ if (!hasAccess) {
535
+ process.exitCode = 1;
536
+ }
537
+ }
538
+ function renderAvailableToolsText(payload) {
539
+ const tools = Array.isArray(payload.tools) ? payload.tools : null;
540
+ if (!tools) return void 0;
541
+ const returned = _nullishCoalesce(asFiniteNumber(payload.returned), () => ( tools.length));
542
+ const total = asFiniteNumber(payload.total);
543
+ const lines = [
544
+ total !== void 0 ? `Monitor types you can deploy (${returned} of ${total}):` : "Monitor types you can deploy:"
545
+ ];
546
+ let currentProvider;
547
+ for (const raw of tools) {
548
+ const entry = asRecord(raw);
549
+ const id = entry ? asString(entry.tool) : void 0;
550
+ if (!entry || !id) continue;
551
+ const name = _nullishCoalesce(asString(entry.name), () => ( asString(entry.display_name)));
552
+ const deployedCount = asFiniteNumber(entry.deployed_count);
553
+ const description = asString(entry.description);
554
+ const streams = Array.isArray(entry.streams) ? entry.streams.map((stream) => asString(stream)).filter((stream) => Boolean(stream)) : [];
555
+ const provider = id.split(".")[0];
556
+ if (provider && provider !== currentProvider) {
557
+ currentProvider = provider;
558
+ lines.push("", ` ${provider}:`);
559
+ }
560
+ lines.push(
561
+ ` ${id.split(".").slice(1).join(".") || id}${name ? ` \u2014 ${name}` : ""}${deployedCount !== void 0 ? ` (${deployedCount} deployed)` : ""}`
562
+ );
563
+ if (description) lines.push(` ${description}`);
564
+ if (streams.length > 0) {
565
+ lines.push(` emits: ${streams.join(", ")}`);
566
+ }
567
+ }
568
+ if (payload.is_truncated === true) {
569
+ lines.push("List truncated; raise --limit to see more.");
570
+ }
571
+ lines.push(
572
+ "",
573
+ "Next:",
574
+ " Inspect payload fields, output columns, and a play binding:",
575
+ " deepline monitors available <provider.tool> --json",
576
+ " See monitors already deployed in this workspace:",
577
+ " deepline monitors list",
578
+ " Validate a monitor definition before deploying:",
579
+ ` deepline monitors check '{"key":"my-monitor","tool":"<provider.tool>","payload":{...}}'`
580
+ );
581
+ return `${lines.join("\n")}
582
+ `;
583
+ }
584
+ async function handleMonitorsAvailable(toolId, options) {
585
+ process.stderr.write(
586
+ "`deepline monitors available` is deprecated.\n Browse types: deepline tools list --categories monitors\n Inspect a type: deepline tools get <monitor-type>\n"
587
+ );
588
+ if (toolId !== void 0 && options.tool !== void 0) {
589
+ if (toolId !== options.tool) {
590
+ throw new MonitorsUsageError(
591
+ `Pass the tool id once: got positional "${toolId}" and --tool "${options.tool}". Use: deepline monitors available ${toolId}`
592
+ );
593
+ }
594
+ }
595
+ const tool = _nullishCoalesce(toolId, () => ( options.tool));
596
+ const payload = await new (0, _chunk2S5Y3TZPjs.DeeplineClient)().monitors.available(tool, {
597
+ ...options.provider ? { provider: options.provider } : {},
598
+ ...options.search ? { search: options.search } : {},
599
+ ...options.limit ? { limit: options.limit } : {},
600
+ ...options.full ? { full: true } : {},
601
+ ...options.compact ? { compact: true } : {}
602
+ });
603
+ _chunkF35VOIQLjs.printCommandEnvelope.call(void 0, payload, {
604
+ json: options.json,
605
+ // Human list view shows id + name + deployed_count ("deployed: N") so
606
+ // can-deploy vs already-deployed is visible in one view. Describing a
607
+ // single tool keeps the full JSON contract (payload schema, streams).
608
+ text: tool ? void 0 : renderAvailableToolsText(payload)
609
+ });
610
+ }
611
+ function renderDeployedListText(payload, requestedStatus, filterKind = "status") {
612
+ const monitors = Array.isArray(payload.monitors) ? payload.monitors : null;
613
+ if (!monitors) return void 0;
614
+ const total = asFiniteNumber(payload.total);
615
+ const header = monitors.length === 0 ? "No deployed monitors matched." : total !== void 0 && total > monitors.length ? `Deployed monitors (${monitors.length} of ${total}):` : `Deployed monitors (${monitors.length}):`;
616
+ const lines = [header];
617
+ for (const raw of monitors) {
618
+ const entry = asRecord(raw);
619
+ const key = entry ? _nullishCoalesce(asString(entry.key), () => ( asString(entry.monitor_key))) : void 0;
620
+ if (!entry || !key) continue;
621
+ const state = readMonitorState(entry);
622
+ const tool = asString(entry.tool);
623
+ const monitorType = asString(entry.type);
624
+ const name = asString(entry.name);
625
+ const outputTable = asString(entry.output_table);
626
+ const webhookState = asString(entry.webhook_state);
627
+ const executionType = asString(entry.execution_type);
628
+ const hasLastReceivedEvent = "last_received_event" in entry;
629
+ const lastReceivedEvent = asString(entry.last_received_event);
630
+ const boundPlays = Array.isArray(entry.bound_plays) ? entry.bound_plays.length : void 0;
631
+ lines.push(
632
+ ` ${key}${state ? ` ${state}` : ""}${tool ? ` ${tool}` : ""}${name ? ` (${name})` : ""}`
633
+ );
634
+ if (outputTable || monitorType || webhookState || executionType || boundPlays !== void 0) {
635
+ lines.push(
636
+ ` ${[
637
+ outputTable ? `table: ${outputTable}` : null,
638
+ monitorType ? `type: ${monitorType}` : null,
639
+ webhookState ? `webhook: ${webhookState}` : null,
640
+ executionType ? `execution: ${executionType}` : null,
641
+ boundPlays !== void 0 ? `bound Plays: ${boundPlays}` : null
642
+ ].filter(Boolean).join(" ")}`
643
+ );
644
+ }
645
+ if (hasLastReceivedEvent) {
646
+ lines.push(` last received: ${_nullishCoalesce(lastReceivedEvent, () => ( "never"))}`);
647
+ }
648
+ if (Array.isArray(entry.bound_plays)) {
649
+ for (const rawPlay of entry.bound_plays) {
650
+ const play = asRecord(rawPlay);
651
+ const playName = _nullishCoalesce(asString(_optionalChain([play, 'optionalAccess', _17 => _17.name])), () => ( "unnamed Play"));
652
+ const health = asRecord(_optionalChain([play, 'optionalAccess', _18 => _18.consumer_health]));
653
+ const healthRequested = Boolean(play && "consumer_health" in play);
654
+ const state2 = healthRequested ? _nullishCoalesce(asString(_optionalChain([health, 'optionalAccess', _19 => _19.last_run_status])), () => ( "no delivery yet")) : "health not requested";
655
+ const lastError = asString(_optionalChain([health, 'optionalAccess', _20 => _20.last_error]));
656
+ lines.push(
657
+ ` consumer: ${playName} \u2014 ${state2}${lastError ? ` (${lastError})` : ""}`
658
+ );
659
+ }
660
+ }
661
+ }
662
+ const applied = monitorStateFilterLabel(
663
+ _nullishCoalesce(payload.state_filter_applied, () => ( payload.status_filter_applied)),
664
+ monitorStateFilterLabel(requestedStatus)
665
+ );
666
+ lines.push(
667
+ `State filter: ${applied}${requestedStatus === void 0 && applied === "active" ? " (default)" : ""} \u2014 use --state all to include all monitors.`
668
+ );
669
+ const rawSummary = Array.isArray(payload.state_summary) ? payload.state_summary : Array.isArray(payload.status_summary) ? payload.status_summary : [];
670
+ const summary = rawSummary.flatMap((raw) => {
671
+ const item = asRecord(raw);
672
+ const state = item ? readMonitorState(item) : void 0;
673
+ const count = item ? asFiniteNumber(item.count) : void 0;
674
+ return state && count !== void 0 ? [`${state}: ${count}`] : [];
675
+ }).join(" ");
676
+ if (summary) {
677
+ lines.push(
678
+ `${payload.state_summary_scope === "filter_total" ? "Matching monitors" : "Current page states"}: ${summary}`
679
+ );
680
+ }
681
+ if (payload.has_more === true || payload.is_truncated === true) {
682
+ const nextCursor = asString(payload.next_cursor);
683
+ lines.push(
684
+ total !== void 0 ? `List truncated \u2014 showing ${monitors.length} of ${total}. Before concluding "no matching monitor exists," page the full registry:` : 'List truncated. Before concluding "no matching monitor exists," page the full registry:',
685
+ nextCursor ? ` deepline monitors list${requestedStatus ? ` --${filterKind} ${filterKind === "state" ? monitorStateFilterLabel(requestedStatus) : requestedStatus}` : ""} --cursor ${nextCursor}` : " raise --limit above the reported total."
686
+ );
687
+ }
688
+ if (monitors.length > 0) {
689
+ lines.push("", "Inspect one: deepline monitors get <key> --json");
690
+ }
691
+ return `${lines.join("\n")}
692
+ `;
693
+ }
694
+ async function handleMonitorsList(options) {
695
+ const state = options.state ? monitorStateFilter(options.state) : void 0;
696
+ if (options.state !== void 0 && !state) {
697
+ throw new MonitorsUsageError(
698
+ `--state must be active, billing_suspended, disabled, or all; received ${options.state}.`
699
+ );
700
+ }
701
+ if (options.compact) {
702
+ process.stderr.write(
703
+ "`--compact` is deprecated and now does nothing; returning the complete monitor records.\n"
704
+ );
705
+ }
706
+ const payload = await new (0, _chunk2S5Y3TZPjs.DeeplineClient)().monitors.list({
707
+ ...state ? { state } : {},
708
+ ...options.status ? { status: options.status } : {},
709
+ ...options.limit ? { limit: options.limit } : {},
710
+ ...options.cursor ? { cursor: options.cursor } : {},
711
+ ...options.includeConsumers ? { includeConsumers: true } : {}
712
+ });
713
+ _chunkF35VOIQLjs.printCommandEnvelope.call(void 0, payload, {
714
+ json: options.json,
715
+ text: renderDeployedListText(
716
+ payload,
717
+ _nullishCoalesce(options.state, () => ( options.status)),
718
+ options.state !== void 0 ? "state" : "status"
719
+ )
720
+ });
721
+ }
722
+ async function handleMonitorsCheck(definition, options) {
723
+ const body = resolveMonitorJsonBody({
724
+ positional: definition,
725
+ file: options.file,
726
+ argLabel: "<definition>",
727
+ command: "deepline monitors check"
728
+ });
729
+ const payload = await new (0, _chunk2S5Y3TZPjs.DeeplineClient)().monitors.check(
730
+ body
731
+ );
732
+ _chunkF35VOIQLjs.printCommandEnvelope.call(void 0, payload, { json: options.json });
733
+ }
734
+ async function handleMonitorsDeploy(definition, options) {
735
+ const body = resolveMonitorJsonBody({
736
+ positional: definition,
737
+ file: options.file,
738
+ argLabel: "<definition>",
739
+ command: "deepline monitors deploy"
740
+ });
741
+ const client = new (0, _chunk2S5Y3TZPjs.DeeplineClient)();
742
+ const definitionArg = body;
743
+ if (options.dryRun) {
744
+ const payload2 = await client.monitors.deploy(definitionArg, {
745
+ dryRun: true
746
+ });
747
+ const valid = payload2.valid !== false;
748
+ const hasIdentityConflict = Boolean(_optionalChain([asRecord, 'call', _21 => _21(payload2), 'optionalAccess', _22 => _22.identity_conflict]));
749
+ _chunkF35VOIQLjs.printCommandEnvelope.call(void 0,
750
+ { dry_run: true, ...payload2 },
751
+ { json: options.json, text: renderMonitorDeployPlan(payload2) }
752
+ );
753
+ if (!valid || hasIdentityConflict) {
754
+ process.exitCode = 7;
755
+ }
756
+ return;
757
+ }
758
+ const payload = await client.monitors.deploy(definitionArg);
759
+ _chunkF35VOIQLjs.printCommandEnvelope.call(void 0, payload, {
760
+ json: options.json,
761
+ text: renderMonitorDeployCompletion(payload)
762
+ });
763
+ }
764
+ async function handleMonitorsSync(definition, options) {
765
+ const body = resolveMonitorJsonBody({
766
+ positional: definition,
767
+ file: options.file,
768
+ argLabel: "<definition>",
769
+ command: "deepline monitors sync"
770
+ });
771
+ const payload = await new (0, _chunk2S5Y3TZPjs.DeeplineClient)().monitors.sync(body, {
772
+ ...options.dryRun ? { dryRun: true } : {},
773
+ idempotencyKey: _nullishCoalesce(options.idempotencyKey, () => ( monitorJobIdempotencyKey("scalar-sync", void 0)))
774
+ });
775
+ if (options.dryRun) {
776
+ const plan = payload;
777
+ _chunkF35VOIQLjs.printCommandEnvelope.call(void 0,
778
+ { dry_run: true, ...plan },
779
+ { json: options.json, text: renderMonitorDeployPlan(plan) }
780
+ );
781
+ return;
782
+ }
783
+ _chunkF35VOIQLjs.printCommandEnvelope.call(void 0, payload, {
784
+ json: options.json,
785
+ text: renderMonitorJob(payload)
786
+ });
787
+ }
788
+ async function handleScalarMonitorLifecycle(action, key, options) {
789
+ const payload = await new (0, _chunk2S5Y3TZPjs.DeeplineClient)().monitors[action](key, {
790
+ ...options.dryRun ? { dryRun: true } : {},
791
+ idempotencyKey: _nullishCoalesce(options.idempotencyKey, () => ( monitorJobIdempotencyKey(`${action}-${key}`, void 0)))
792
+ });
793
+ _chunkF35VOIQLjs.printCommandEnvelope.call(void 0, payload, {
794
+ json: options.json,
795
+ text: options.dryRun ? void 0 : renderMonitorJob(payload)
796
+ });
797
+ }
798
+ function fleetIntegerOption(raw, flag) {
799
+ if (raw === void 0) return void 0;
800
+ const value = Number(raw);
801
+ if (!Number.isSafeInteger(value) || value < 0) {
802
+ throw new MonitorsUsageError(`${flag} must be a non-negative integer.`);
803
+ }
804
+ return value;
805
+ }
806
+ function fleetIdempotencyKey(operation, supplied) {
807
+ const normalized = _optionalChain([supplied, 'optionalAccess', _23 => _23.trim, 'call', _24 => _24()]);
808
+ if (supplied !== void 0 && !normalized) {
809
+ throw new MonitorsUsageError("--idempotency-key must not be empty.");
810
+ }
811
+ return _nullishCoalesce(normalized, () => ( `monitor-fleet-${operation}-${_crypto.randomUUID.call(void 0, )}`));
812
+ }
813
+ function monitorJobIdempotencyKey(operation, supplied) {
814
+ const normalized = _optionalChain([supplied, 'optionalAccess', _25 => _25.trim, 'call', _26 => _26()]);
815
+ if (supplied !== void 0 && !normalized) {
816
+ throw new MonitorsUsageError("--idempotency-key must not be empty.");
817
+ }
818
+ return _nullishCoalesce(normalized, () => ( `monitor-job-${operation}-${_crypto.randomUUID.call(void 0, )}`));
819
+ }
820
+ function readMonitorDefinitionsJsonFile(file) {
821
+ let raw;
822
+ try {
823
+ raw = file === "-" ? _fs.readFileSync.call(void 0, 0, "utf8") : _fs.readFileSync.call(void 0, file, "utf8");
824
+ } catch (error) {
825
+ throw new MonitorsUsageError(
826
+ `Could not read --file ${file}: ${error instanceof Error ? error.message : String(error)}`
827
+ );
828
+ }
829
+ try {
830
+ return JSON.parse(raw);
831
+ } catch (error) {
832
+ throw new MonitorsUsageError(
833
+ `Monitor definitions must be valid JSON. ${error instanceof Error ? error.message : String(error)}`
834
+ );
835
+ }
836
+ }
837
+ function renderMonitorJob(payload) {
838
+ const job = asRecord(payload.job);
839
+ if (!job) return void 0;
840
+ const id = _nullishCoalesce(asString(job.id), () => ( "<unknown>"));
841
+ const state = _nullishCoalesce(asString(job.state), () => ( "unknown"));
842
+ const outcome = asString(job.outcome);
843
+ const phase = asString(job.phase);
844
+ const counts = asRecord(job.counts);
845
+ const reconciliation = asRecord(job.reconciliation);
846
+ const lines = [
847
+ `Monitor job: ${id}`,
848
+ `State: ${state}${phase ? ` (${phase})` : ""}`
849
+ ];
850
+ if (outcome) lines.push(`Outcome: ${outcome}`);
851
+ const operationId = asString(job.operation_id);
852
+ if (operationId) lines.push(`Operation: ${operationId}`);
853
+ if (counts) {
854
+ lines.push(
855
+ `Counts: requested ${_nullishCoalesce(asFiniteNumber(counts.requested), () => ( 0))}, created ${_nullishCoalesce(asFiniteNumber(counts.created), () => ( 0))}, updated ${_nullishCoalesce(asFiniteNumber(counts.updated), () => ( 0))}, removed ${_nullishCoalesce(asFiniteNumber(counts.removed), () => ( 0))}, unchanged ${_nullishCoalesce(asFiniteNumber(counts.unchanged), () => ( 0))}, verified ${_nullishCoalesce(asFiniteNumber(counts.verified), () => ( 0))}, failed ${_nullishCoalesce(asFiniteNumber(counts.failed), () => ( 0))}`
856
+ );
857
+ }
858
+ if (reconciliation) {
859
+ lines.push(
860
+ `Reconciliation: ${_nullishCoalesce(asString(reconciliation.state), () => ( "pending"))} (${_nullishCoalesce(asFiniteNumber(reconciliation.observed_bindings), () => ( 0))}/${_nullishCoalesce(asFiniteNumber(reconciliation.expected_bindings), () => ( 0))} bindings observed)`
861
+ );
862
+ }
863
+ const next = asString(payload.next);
864
+ if (next) lines.push(`Next: ${next}`);
865
+ return `${lines.join("\n")}
866
+ `;
867
+ }
868
+ async function handleMonitorJobBatchDeploy(options, idempotencyKey) {
869
+ if (!options.file) {
870
+ throw new MonitorsUsageError(
871
+ "A Batch file is required. Pass --file batch.json (or --file - for stdin)."
872
+ );
873
+ }
874
+ const lint = _chunkWOHBA5PVjs.lintMonitorBatchInput.call(void 0,
875
+ readMonitorDefinitionsJsonFile(options.file)
876
+ );
877
+ if (!lint.normalized) {
878
+ throw new MonitorsUsageError(
879
+ lint.issues.filter((issue) => issue.severity === "error").map((issue) => `${issue.path || "batch"}: ${issue.message}`).join("; ")
880
+ );
881
+ }
882
+ const payload = await new (0, _chunk2S5Y3TZPjs.DeeplineClient)().monitors.batch.deploy(
883
+ lint.normalized.monitors,
884
+ { idempotencyKey }
885
+ );
886
+ _chunkF35VOIQLjs.printCommandEnvelope.call(void 0,
887
+ {
888
+ ...payload,
889
+ idempotency_key: idempotencyKey,
890
+ ...lint.issues.length ? { lint: { issues: lint.issues } } : {}
891
+ },
892
+ { json: options.json, text: renderMonitorJob(payload) }
893
+ );
894
+ }
895
+ function namedBatchIdempotencyKey(batchId, intent, supplied) {
896
+ return _optionalChain([supplied, 'optionalAccess', _27 => _27.trim, 'call', _28 => _28()]) || `monitor-batch-${intent}-${batchId}-${_crypto.randomUUID.call(void 0, )}`;
897
+ }
898
+ async function handleNamedMonitorBatchSync(batchId, options) {
899
+ if (!options.file) {
900
+ throw new MonitorsUsageError(
901
+ "monitors batches sync requires --file <batch.json>."
902
+ );
903
+ }
904
+ const lint = _chunkWOHBA5PVjs.lintMonitorBatchInput.call(void 0,
905
+ readMonitorDefinitionsJsonFile(options.file)
906
+ );
907
+ if (!lint.normalized) {
908
+ throw new MonitorsUsageError(
909
+ lint.issues.filter((issue) => issue.severity === "error").map((issue) => `${issue.path || "batch"}: ${issue.message}`).join("; ")
910
+ );
911
+ }
912
+ const parsedGeneration = options.expectedGeneration === void 0 ? void 0 : Number(options.expectedGeneration);
913
+ if (parsedGeneration !== void 0 && (!Number.isSafeInteger(parsedGeneration) || parsedGeneration < 0)) {
914
+ throw new MonitorsUsageError(
915
+ "--expected-generation must be a non-negative integer."
916
+ );
917
+ }
918
+ if (options.dryRun) {
919
+ _chunkF35VOIQLjs.printCommandEnvelope.call(void 0,
920
+ {
921
+ ok: true,
922
+ dry_run: true,
923
+ batch: { id: batchId, desired_count: lint.normalized.monitors.length },
924
+ issues: lint.issues,
925
+ next: `deepline monitors batches sync ${batchId} --file ${options.file} --idempotency-key <stable-key> --json`
926
+ },
927
+ { json: options.json }
928
+ );
929
+ return;
930
+ }
931
+ const idempotencyKey = namedBatchIdempotencyKey(
932
+ batchId,
933
+ "sync",
934
+ options.idempotencyKey
935
+ );
936
+ const payload = await new (0, _chunk2S5Y3TZPjs.DeeplineClient)().monitors.batches.sync(
937
+ batchId,
938
+ lint.normalized.monitors,
939
+ {
940
+ idempotencyKey,
941
+ ...parsedGeneration === void 0 ? {} : { expectedGeneration: parsedGeneration }
942
+ }
943
+ );
944
+ _chunkF35VOIQLjs.printCommandEnvelope.call(void 0,
945
+ { ...payload, idempotency_key: idempotencyKey },
946
+ { json: options.json, text: renderMonitorJob(payload) }
947
+ );
948
+ }
949
+ async function handleNamedMonitorBatchLifecycle(batchId, intent, options) {
950
+ if (options.dryRun) {
951
+ _chunkF35VOIQLjs.printCommandEnvelope.call(void 0,
952
+ {
953
+ ok: true,
954
+ dry_run: true,
955
+ batch: { id: batchId, intent },
956
+ next: `deepline monitors batches ${intent} ${batchId} --idempotency-key <stable-key> --json`
957
+ },
958
+ { json: options.json }
959
+ );
960
+ return;
961
+ }
962
+ const idempotencyKey = namedBatchIdempotencyKey(
963
+ batchId,
964
+ intent,
965
+ options.idempotencyKey
966
+ );
967
+ const payload = await new (0, _chunk2S5Y3TZPjs.DeeplineClient)().monitors.batches[intent](batchId, {
968
+ idempotencyKey
969
+ });
970
+ _chunkF35VOIQLjs.printCommandEnvelope.call(void 0,
971
+ { ...payload, idempotency_key: idempotencyKey },
972
+ { json: options.json, text: renderMonitorJob(payload) }
973
+ );
974
+ }
975
+ async function handleNamedMonitorBatchGet(batchId, options) {
976
+ const payload = await new (0, _chunk2S5Y3TZPjs.DeeplineClient)().monitors.batches.get(batchId);
977
+ _chunkF35VOIQLjs.printCommandEnvelope.call(void 0, payload, {
978
+ json: options.json,
979
+ text: renderMonitorJob(payload)
980
+ });
981
+ }
982
+ async function handleMonitorBatchLint(options) {
983
+ if (!options.file) {
984
+ throw new MonitorsUsageError(
985
+ "monitors batch lint requires --file <batch.json>."
986
+ );
987
+ }
988
+ const result = _chunkWOHBA5PVjs.lintMonitorBatchInput.call(void 0,
989
+ readMonitorDefinitionsJsonFile(options.file)
990
+ );
991
+ _chunkF35VOIQLjs.printCommandEnvelope.call(void 0,
992
+ {
993
+ ok: !result.issues.some((issue) => issue.severity === "error"),
994
+ ...result.normalized ? { normalized: result.normalized } : {},
995
+ issues: result.issues
996
+ },
997
+ { json: options.json }
998
+ );
999
+ if (result.issues.some((issue) => issue.severity === "error"))
1000
+ process.exitCode = 2;
1001
+ }
1002
+ async function handleMonitorFleetLint(options) {
1003
+ if (!options.file) {
1004
+ throw new MonitorsUsageError(
1005
+ "monitors fleets lint requires --file <fleet.json>."
1006
+ );
1007
+ }
1008
+ const result = _chunkJ5NA2TTXjs.lintMonitorFleetInput.call(void 0,
1009
+ readMonitorDefinitionsJsonFile(options.file)
1010
+ );
1011
+ _chunkF35VOIQLjs.printCommandEnvelope.call(void 0,
1012
+ {
1013
+ ok: !result.issues.some((issue) => issue.severity === "error"),
1014
+ ...result.normalized ? { normalized: result.normalized } : {},
1015
+ issues: result.issues
1016
+ },
1017
+ { json: options.json }
1018
+ );
1019
+ if (result.issues.some((issue) => issue.severity === "error"))
1020
+ process.exitCode = 2;
1021
+ }
1022
+ async function handleMonitorJobGet(jobId, options) {
1023
+ const payload = await new (0, _chunk2S5Y3TZPjs.DeeplineClient)().monitors.jobs.get(jobId);
1024
+ _chunkF35VOIQLjs.printCommandEnvelope.call(void 0, payload, {
1025
+ json: options.json,
1026
+ text: renderMonitorJob(payload)
1027
+ });
1028
+ }
1029
+ async function handleMonitorJobWait(jobId, options) {
1030
+ const payload = await new (0, _chunk2S5Y3TZPjs.DeeplineClient)().monitors.jobs.wait(jobId, {
1031
+ timeoutMs: fleetTimeoutMs(options.timeout),
1032
+ pollIntervalMs: FLEET_POLL_INTERVAL_MS
1033
+ });
1034
+ _chunkF35VOIQLjs.printCommandEnvelope.call(void 0, payload, {
1035
+ json: options.json,
1036
+ text: renderMonitorJob(payload)
1037
+ });
1038
+ }
1039
+ async function handleMonitorJobLogs(jobId, options) {
1040
+ const limit = options.limit ? fleetIntegerOption(options.limit, "--limit") : void 0;
1041
+ const payload = await new (0, _chunk2S5Y3TZPjs.DeeplineClient)().monitors.jobs.logs(jobId, {
1042
+ ...limit === void 0 ? {} : { limit }
1043
+ });
1044
+ _chunkF35VOIQLjs.printCommandEnvelope.call(void 0, payload, { json: options.json });
1045
+ }
1046
+ async function handleMonitorJobCancel(jobId, options) {
1047
+ const payload = await new (0, _chunk2S5Y3TZPjs.DeeplineClient)().monitors.jobs.cancel(jobId);
1048
+ _chunkF35VOIQLjs.printCommandEnvelope.call(void 0, payload, {
1049
+ json: options.json,
1050
+ text: renderMonitorJob(payload)
1051
+ });
1052
+ }
1053
+ var FLEET_COUNT_KEYS = [
1054
+ "pending",
1055
+ "submitting",
1056
+ "rate_limited",
1057
+ "settled",
1058
+ "blocked",
1059
+ "failed"
1060
+ ];
1061
+ var FLEET_DEFAULT_WAIT_MS = 10 * 6e4;
1062
+ var FLEET_POLL_INTERVAL_MS = 2e3;
1063
+ var FLEET_PLAIN_PROGRESS_INTERVAL_MS = 15e3;
1064
+ var FLEET_RETRY_SAFE_NOTE = "Safe to retry \u2014 every fleet command is idempotent.";
1065
+ var MONITOR_FLEET_LIFECYCLE = [
1066
+ {
1067
+ step: 1,
1068
+ what: "Write a definition file you can read and edit.",
1069
+ command: "deepline monitors fleets init <fleet-id> --source public.accounts --key account_id --tool <tool> --payload '<json>' --out fleet.json"
1070
+ },
1071
+ {
1072
+ step: 2,
1073
+ what: "See the plan and the credits before anything changes.",
1074
+ command: "deepline monitors fleets deploy --file fleet.json --dry-run"
1075
+ },
1076
+ {
1077
+ step: 3,
1078
+ what: "Apply it and wait for the server to call it converged.",
1079
+ command: "deepline monitors fleets deploy --file fleet.json --wait"
1080
+ },
1081
+ {
1082
+ step: 4,
1083
+ what: "Read live state; add --drift to see what has not settled.",
1084
+ command: "deepline monitors fleets get <fleet-id>"
1085
+ }
1086
+ ];
1087
+ var MONITOR_FLEET_COMMANDS = [
1088
+ {
1089
+ name: "deploy",
1090
+ summary: "Create or update one table-backed Fleet from Customer DB rows."
1091
+ },
1092
+ { name: "lint", summary: "Validate and normalize Fleet JSON locally." },
1093
+ { name: "init", summary: "Write a Fleet definition JSON file." },
1094
+ {
1095
+ name: "sync",
1096
+ summary: "Create or re-plan a fleet from a definition file or its stored config."
1097
+ },
1098
+ {
1099
+ name: "get",
1100
+ summary: "Read one fleet, list every fleet, or inspect drift."
1101
+ },
1102
+ {
1103
+ name: "deactivate",
1104
+ summary: "Deactivate a fleet and the monitors it owns."
1105
+ },
1106
+ {
1107
+ name: "reactivate",
1108
+ summary: "Explicitly recreate a fleet after a credit-triggered suspension."
1109
+ }
1110
+ ];
1111
+ var MONITOR_FLEET_AGENT_NOTES = [
1112
+ "Add --json for stable output; stdout is always exactly one JSON object.",
1113
+ "Every error includes a runnable `next` command \u2014 run it, do not guess.",
1114
+ "Exit 5 = retry the same command; 6 = inspect counts with `get --drift`; 7 = change the request."
1115
+ ];
1116
+ var MONITOR_FLEET_HELP_EPILOG = `
1117
+ Agent notes:
1118
+ ${MONITOR_FLEET_AGENT_NOTES.join("\n ")}
1119
+ `;
1120
+ var MonitorFleetStateError = class extends Error {
1121
+
1122
+
1123
+ constructor(input) {
1124
+ super(input.message);
1125
+ this.name = "MonitorFleetStateError";
1126
+ this.code = input.code;
1127
+ this.next = input.next;
1128
+ }
1129
+ };
1130
+ function fleetCounts(payload) {
1131
+ const raw = _nullishCoalesce(asRecord(payload.counts), () => ( {}));
1132
+ const counts = {};
1133
+ for (const key of FLEET_COUNT_KEYS) {
1134
+ counts[key] = _nullishCoalesce(asFiniteNumber(raw[key]), () => ( 0));
1135
+ }
1136
+ return counts;
1137
+ }
1138
+ function fleetShellArg(value) {
1139
+ return /^[A-Za-z0-9._/@:=-]+$/.test(value) ? value : `'${value.replaceAll("'", `'\\''`)}'`;
1140
+ }
1141
+ function fleetJsonFlag(options) {
1142
+ return options.json ? ["--json"] : [];
1143
+ }
1144
+ function fleetTimeoutMs(raw) {
1145
+ if (raw === void 0) return FLEET_DEFAULT_WAIT_MS;
1146
+ const match = /^(\d+)(ms|s|m|h)?$/.exec(raw.trim());
1147
+ if (!match) {
1148
+ throw new MonitorsUsageError(
1149
+ "--timeout must be a duration like 500ms, 90s, 10m, or 1h (a bare number is seconds)."
1150
+ );
1151
+ }
1152
+ const value = Number(match[1]);
1153
+ if (!value) {
1154
+ throw new MonitorsUsageError("--timeout must be greater than zero.");
1155
+ }
1156
+ const unit = _nullishCoalesce(match[2], () => ( "s"));
1157
+ const factor = unit === "ms" ? 1 : unit === "s" ? 1e3 : unit === "m" ? 6e4 : 36e5;
1158
+ return value * factor;
1159
+ }
1160
+ function fleetServerNext(payload) {
1161
+ return _nullishCoalesce(asString(payload.next), () => ( asString(payload.next_action)));
1162
+ }
1163
+ function fleetStatus(payload) {
1164
+ return asString(payload.status);
1165
+ }
1166
+ function fleetProgressReporter() {
1167
+ const interactive = process.stderr.isTTY === true;
1168
+ let wrote = false;
1169
+ let lastPlainAt = 0;
1170
+ return {
1171
+ report: (payload) => {
1172
+ const counts = fleetCounts(payload);
1173
+ const expected = _nullishCoalesce(asFiniteNumber(payload.expected), () => ( FLEET_COUNT_KEYS.reduce((sum, key) => sum + counts[key], 0)));
1174
+ const line = `settled ${counts.settled}/${expected} \xB7 rate_limited ${counts.rate_limited} \xB7 blocked ${counts.blocked}`;
1175
+ if (interactive) {
1176
+ process.stderr.write(`\r\x1B[2K${line}`);
1177
+ wrote = true;
1178
+ return;
1179
+ }
1180
+ const now = Date.now();
1181
+ if (wrote && now - lastPlainAt < FLEET_PLAIN_PROGRESS_INTERVAL_MS) return;
1182
+ lastPlainAt = now;
1183
+ wrote = true;
1184
+ process.stderr.write(`${line}
1185
+ `);
1186
+ },
1187
+ finish: () => {
1188
+ if (interactive && wrote) process.stderr.write("\n");
1189
+ }
1190
+ };
1191
+ }
1192
+ function fleetPlanLine(payload) {
1193
+ const plan = _nullishCoalesce(asRecord(payload.plan), () => ( {}));
1194
+ const blocked = _nullishCoalesce(asRecord(plan.blocked), () => ( {}));
1195
+ const entries = Object.entries(blocked).flatMap(([limitId, raw]) => {
1196
+ const count = asFiniteNumber(raw);
1197
+ return count === void 0 ? [] : [[limitId, count]];
1198
+ }).sort(([left], [right]) => left.localeCompare(right));
1199
+ const blockedTotal = entries.reduce((sum, [, count]) => sum + count, 0);
1200
+ const detail = entries.length === 0 ? "" : entries.length === 1 ? ` (${entries[0][0]})` : ` (${entries.map(([id, count]) => `${id}: ${count}`).join(", ")})`;
1201
+ return [
1202
+ `creates ${_nullishCoalesce(asFiniteNumber(plan.creates), () => ( 0))}`,
1203
+ `updates ${_nullishCoalesce(asFiniteNumber(plan.updates), () => ( 0))}`,
1204
+ `removes ${_nullishCoalesce(asFiniteNumber(plan.removes), () => ( 0))}`,
1205
+ `blocked ${blockedTotal}${detail}`
1206
+ ].join(" \xB7 ");
1207
+ }
1208
+ function fleetCountsLine(payload) {
1209
+ const counts = fleetCounts(payload);
1210
+ return FLEET_COUNT_KEYS.map((key) => `${key} ${counts[key]}`).join(" \xB7 ");
1211
+ }
1212
+ function renderFleetSync(payload, input) {
1213
+ const lines = [
1214
+ input.dryRun ? `Fleet ${input.fleetId} \u2014 plan only, nothing changed` : `Fleet ${input.fleetId} \u2014 accepted`,
1215
+ ` plan ${fleetPlanLine(payload)}`
1216
+ ];
1217
+ const credits = asFiniteNumber(payload.credits_due_now);
1218
+ lines.push(` credits due now ${_nullishCoalesce(credits, () => ( 0))}`);
1219
+ lines.push(
1220
+ ` generation ${_nullishCoalesce(asFiniteNumber(payload.generation), () => ( "unknown"))} \xB7 replayed ${yesNo(
1221
+ payload.replayed
1222
+ )} \xB7 idempotency key ${input.idempotencyKey}`
1223
+ );
1224
+ const next = fleetServerNext(payload);
1225
+ if (next) lines.push(`Next: ${next}`);
1226
+ return `${lines.join("\n")}
1227
+ `;
1228
+ }
1229
+ function renderFleetGet(payload) {
1230
+ const id = _nullishCoalesce(asString(payload.id), () => ( "unknown"));
1231
+ const state = _nullishCoalesce(readMonitorState(payload), () => ( "unknown"));
1232
+ const status = fleetStatus(payload);
1233
+ const lines = [
1234
+ `Fleet ${id} \u2014 state ${state}`,
1235
+ ` monitors ${_nullishCoalesce(asFiniteNumber(payload.live), () => ( 0))} live / ${_nullishCoalesce(asFiniteNumber(payload.expected), () => ( 0))} expected`,
1236
+ ` counts ${fleetCountsLine(payload)}`,
1237
+ ` generation ${_nullishCoalesce(asFiniteNumber(payload.generation), () => ( "unknown"))} \xB7 converged generation ${_nullishCoalesce(asFiniteNumber(payload.converged_generation), () => ( "none"))}`
1238
+ ];
1239
+ const boundPlays = Array.isArray(payload.bound_plays) ? payload.bound_plays.flatMap((value) => {
1240
+ const play = asRecord(value);
1241
+ return play ? [play] : [];
1242
+ }) : [];
1243
+ lines.push("", `Observed Play bindings (${boundPlays.length}):`);
1244
+ if (boundPlays.length === 0) {
1245
+ lines.push(" none");
1246
+ } else {
1247
+ for (const play of boundPlays) {
1248
+ const name = _nullishCoalesce(asString(play.name), () => ( "unnamed Play"));
1249
+ const listeners = _nullishCoalesce(asFiniteNumber(play.listener_count), () => ( 0));
1250
+ const status2 = asString(play.status);
1251
+ lines.push(
1252
+ ` ${name}${listeners ? ` (${listeners} listener${listeners === 1 ? "" : "s"})` : ""}${status2 ? ` \u2014 ${status2}` : ""}`
1253
+ );
1254
+ }
1255
+ }
1256
+ lines.push(
1257
+ " Read-only observation. Define or change bindings in the Play with sqlListeners."
1258
+ );
1259
+ lines.push(...renderFleetDriftRows(payload));
1260
+ const next = _nullishCoalesce(fleetServerNext(payload), () => ( (status === "degraded" ? `deepline monitors fleets get ${fleetShellArg(id)} --drift` : void 0)));
1261
+ if (next) lines.push(`Next: ${next}`);
1262
+ return `${lines.join("\n")}
1263
+ `;
1264
+ }
1265
+ function renderFleetDriftRows(payload) {
1266
+ const drift = Array.isArray(payload.drift) ? payload.drift : void 0;
1267
+ if (!drift) return [];
1268
+ const rows = drift.flatMap((raw) => {
1269
+ const row = asRecord(raw);
1270
+ return row ? [row] : [];
1271
+ }).map((row) => ({
1272
+ monitorKey: _nullishCoalesce(asString(row.monitor_key), () => ( "-")),
1273
+ entityKey: _nullishCoalesce(asString(row.entity_key), () => ( "-")),
1274
+ convergence: _nullishCoalesce(asString(row.convergence), () => ( "-")),
1275
+ since: _nullishCoalesce(asString(row.since), () => ( "-")),
1276
+ detail: _nullishCoalesce(asString(row.error), () => ( (asString(row.blocked_by) ? `blocked_by ${asString(row.blocked_by)}` : asString(row.next_attempt_at) ? `next_attempt_at ${asString(row.next_attempt_at)}` : "")))
1277
+ })).sort(
1278
+ (left, right) => left.monitorKey.localeCompare(right.monitorKey) || left.entityKey.localeCompare(right.entityKey)
1279
+ );
1280
+ if (rows.length === 0) {
1281
+ return [` drift none${payload.truncated === true ? " (truncated)" : ""}`];
1282
+ }
1283
+ const width = (values) => values.reduce((max, value) => Math.max(max, value.length), 0);
1284
+ const monitorWidth = width(rows.map((row) => row.monitorKey));
1285
+ const entityWidth = width(rows.map((row) => row.entityKey));
1286
+ const convergenceWidth = width(rows.map((row) => row.convergence));
1287
+ const lines = [
1288
+ ` drift (${rows.length}${payload.truncated === true ? ", truncated" : ""})`
1289
+ ];
1290
+ for (const row of rows) {
1291
+ lines.push(
1292
+ ` ${row.monitorKey.padEnd(monitorWidth)} ${row.entityKey.padEnd(
1293
+ entityWidth
1294
+ )} ${row.convergence.padEnd(convergenceWidth)} ${row.since}${row.detail ? ` ${row.detail}` : ""}`
1295
+ );
1296
+ }
1297
+ return lines;
1298
+ }
1299
+ function renderFleetList(payload) {
1300
+ const fleets = (Array.isArray(payload.fleets) ? payload.fleets : []).flatMap((raw) => {
1301
+ const fleet = asRecord(raw);
1302
+ return fleet ? [fleet] : [];
1303
+ }).sort(
1304
+ (left, right) => (_nullishCoalesce(asString(left.id), () => ( ""))).localeCompare(_nullishCoalesce(asString(right.id), () => ( "")))
1305
+ );
1306
+ if (fleets.length === 0) {
1307
+ return "No Monitor Fleets in this workspace.\nNext: deepline monitors fleets init <fleet-id> --help\n";
1308
+ }
1309
+ const idWidth = fleets.reduce(
1310
+ (max, fleet) => Math.max(max, (_nullishCoalesce(asString(fleet.id), () => ( ""))).length),
1311
+ 0
1312
+ );
1313
+ const stateWidth = fleets.reduce(
1314
+ (max, fleet) => Math.max(max, (_nullishCoalesce(readMonitorState(fleet), () => ( "unknown"))).length),
1315
+ 0
1316
+ );
1317
+ const lines = [`Fleets (${fleets.length})`];
1318
+ for (const fleet of fleets) {
1319
+ const counts = fleetCounts(fleet);
1320
+ const trouble = [
1321
+ counts.blocked ? `blocked ${counts.blocked}` : "",
1322
+ counts.failed ? `failed ${counts.failed}` : ""
1323
+ ].filter(Boolean);
1324
+ lines.push(
1325
+ ` ${(_nullishCoalesce(asString(fleet.id), () => ( "-"))).padEnd(idWidth)} ${(_nullishCoalesce(readMonitorState(fleet), () => ( "unknown"))).padEnd(stateWidth)} ${_nullishCoalesce(asFiniteNumber(fleet.live), () => ( 0))}/${_nullishCoalesce(asFiniteNumber(fleet.expected), () => ( 0))}${trouble.length ? ` ${trouble.join(" \xB7 ")}` : ""}`
1326
+ );
1327
+ }
1328
+ return `${lines.join("\n")}
1329
+ `;
1330
+ }
1331
+ function renderFleetDeactivatePlan(payload, fleetId) {
1332
+ const radius = _nullishCoalesce(asRecord(payload.would_deactivate), () => ( {}));
1333
+ const lines = [
1334
+ `Deactivate fleet ${fleetId} \u2014 plan only, nothing changed`,
1335
+ ` would deactivate ${_nullishCoalesce(asFiniteNumber(radius.monitors), () => ( 0))} monitors \xB7 ${_nullishCoalesce(asFiniteNumber(radius.accounts), () => ( 0))} accounts`
1336
+ ];
1337
+ const note = asString(payload.note);
1338
+ if (note) lines.push(` ${note}`);
1339
+ lines.push(
1340
+ `Next: ${_nullishCoalesce(fleetServerNext(payload), () => ( `deepline monitors fleets deactivate ${fleetShellArg(fleetId)} --yes`))}`
1341
+ );
1342
+ return `${lines.join("\n")}
1343
+ `;
1344
+ }
1345
+ function reportFleetState(payload, error, options) {
1346
+ _chunkF35VOIQLjs.printCommandEnvelope.call(void 0,
1347
+ {
1348
+ ...payload,
1349
+ code: error.code,
1350
+ message: error.message,
1351
+ next: error.next
1352
+ },
1353
+ {
1354
+ json: options.json,
1355
+ text: `${options.text}${error.message}
1356
+ Next: ${error.next}
1357
+ `
1358
+ }
1359
+ );
1360
+ process.exitCode = monitorsErrorExitCode(error);
1361
+ }
1362
+ function fleetSourceTable(value) {
1363
+ const [schema, table, extra] = _nullishCoalesce(_optionalChain([value, 'optionalAccess', _29 => _29.trim, 'call', _30 => _30(), 'access', _31 => _31.split, 'call', _32 => _32(".")]), () => ( []));
1364
+ if (!schema || !table || extra || !/^[A-Za-z_][A-Za-z0-9_]*$/.test(schema) || !/^[A-Za-z_][A-Za-z0-9_]*$/.test(table)) {
1365
+ throw new MonitorsUsageError(
1366
+ "--source must be a Customer DB table in schema.table form."
1367
+ );
1368
+ }
1369
+ return { schema, table };
1370
+ }
1371
+ function fleetColumnName(value, flag) {
1372
+ const name = _optionalChain([value, 'optionalAccess', _33 => _33.trim, 'call', _34 => _34()]);
1373
+ if (!name || !/^[A-Za-z_][A-Za-z0-9_]*$/.test(name)) {
1374
+ throw new MonitorsUsageError(`${flag} must be a SQL column identifier.`);
1375
+ }
1376
+ return name;
1377
+ }
1378
+ function fleetMemberLimit(value) {
1379
+ if (value === void 0) return 1e3;
1380
+ const limit = fleetIntegerOption(value, "--limit");
1381
+ if (!limit || limit > 1e3) {
1382
+ throw new MonitorsUsageError("--limit must be between 1 and 1,000.");
1383
+ }
1384
+ return limit;
1385
+ }
1386
+ function fleetOrderBy(values, sourceKey) {
1387
+ const parsed = (_nullishCoalesce(values, () => ( []))).map((value) => {
1388
+ const match = /^([A-Za-z_][A-Za-z0-9_]*):(asc|desc)$/.exec(value.trim());
1389
+ if (!match) {
1390
+ throw new MonitorsUsageError(
1391
+ "--order-by must use column:asc or column:desc."
1392
+ );
1393
+ }
1394
+ return { column: match[1], direction: match[2] };
1395
+ });
1396
+ const seen = /* @__PURE__ */ new Set();
1397
+ for (const order of parsed) {
1398
+ if (seen.has(order.column)) {
1399
+ throw new MonitorsUsageError(
1400
+ `--order-by repeats '${order.column}'. Each column may appear once.`
1401
+ );
1402
+ }
1403
+ seen.add(order.column);
1404
+ }
1405
+ const sourceOrder = parsed.find((order) => order.column === sourceKey);
1406
+ return [
1407
+ ...parsed.filter((order) => order.column !== sourceKey),
1408
+ _nullishCoalesce(sourceOrder, () => ( { column: sourceKey, direction: "asc" }))
1409
+ ];
1410
+ }
1411
+ async function handleMonitorFleetsInit(fleetId, options) {
1412
+ if (!/^[a-z][a-z0-9-]{0,199}$/.test(fleetId)) {
1413
+ throw new MonitorsUsageError("<fleet-id> must be lowercase kebab-case.");
1414
+ }
1415
+ const source = fleetSourceTable(options.source);
1416
+ const key = fleetColumnName(options.key, "--key");
1417
+ const keyType = _nullishCoalesce(_optionalChain([options, 'access', _35 => _35.keyType, 'optionalAccess', _36 => _36.trim, 'call', _37 => _37()]), () => ( "text"));
1418
+ if (!["text", "uuid", "int4", "int8"].includes(keyType)) {
1419
+ throw new MonitorsUsageError(
1420
+ "--key-type must be text, uuid, int4, or int8."
1421
+ );
1422
+ }
1423
+ const tool = _optionalChain([options, 'access', _38 => _38.tool, 'optionalAccess', _39 => _39.trim, 'call', _40 => _40()]);
1424
+ if (!tool) throw new MonitorsUsageError("--tool is required.");
1425
+ if (!options.payload) {
1426
+ throw new MonitorsUsageError(
1427
+ "--payload is required and must be the monitor payload JSON for --tool."
1428
+ );
1429
+ }
1430
+ const payload = parseJsonObjectArg(options.payload, "--payload");
1431
+ const where = options.where ? parseJsonObjectArg(options.where, "--where") : void 0;
1432
+ const out = _optionalChain([options, 'access', _41 => _41.out, 'optionalAccess', _42 => _42.trim, 'call', _43 => _43()]);
1433
+ if (!out) throw new MonitorsUsageError("--out is required.");
1434
+ const authoredDefinition = {
1435
+ version: 2,
1436
+ kind: "fleet",
1437
+ id: fleetId,
1438
+ source: {
1439
+ kind: "customer_db_table",
1440
+ schema: source.schema,
1441
+ table: source.table,
1442
+ key: { column: key, type: keyType },
1443
+ ...where ? { where } : {}
1444
+ },
1445
+ monitor: {
1446
+ tool,
1447
+ key: `${fleetId}-{{${key}}}`,
1448
+ payload
1449
+ },
1450
+ selection: {
1451
+ limit: fleetMemberLimit(options.limit),
1452
+ orderBy: fleetOrderBy(options.orderBy, key),
1453
+ membership: "sticky"
1454
+ }
1455
+ };
1456
+ const definition = requireCompiledFleetDefinition(authoredDefinition);
1457
+ const file = _path.resolve.call(void 0, out);
1458
+ _fs.writeFileSync.call(void 0, file, `${JSON.stringify(definition, null, 2)}
1459
+ `, "utf8");
1460
+ const next = `deepline monitors fleets deploy --file ${fleetShellArg(file)} --dry-run --json`;
1461
+ _chunkF35VOIQLjs.printCommandEnvelope.call(void 0,
1462
+ { schemaVersion: 2, file, definition, next },
1463
+ {
1464
+ json: options.json,
1465
+ text: `Wrote ${file}
1466
+ Next: ${next}
1467
+ `
1468
+ }
1469
+ );
1470
+ }
1471
+ function requireCompiledFleetDefinition(definition) {
1472
+ const result = _chunkJ5NA2TTXjs.lintMonitorFleetInput.call(void 0, definition);
1473
+ if (result.normalized) return result.normalized;
1474
+ const messages = result.issues.map((issue) => `${issue.path || "definition"}: ${issue.message}`).join("; ");
1475
+ throw new MonitorsUsageError(
1476
+ `Monitor Fleet definition failed local contract check. ${messages}
1477
+ Fix the file, then re-run: deepline monitors fleets sync --file <fleet.json> --dry-run`
1478
+ );
1479
+ }
1480
+ function fleetSyncCommandLine(target, options) {
1481
+ const parts = ["deepline monitors fleets sync"];
1482
+ if (options.file) parts.push(`--file ${fleetShellArg(options.file)}`);
1483
+ else if (target) parts.push(fleetShellArg(target));
1484
+ if (options.dryRun) parts.push("--dry-run");
1485
+ if (options.wait) parts.push("--wait");
1486
+ if (options.timeout)
1487
+ parts.push(`--timeout ${fleetShellArg(options.timeout)}`);
1488
+ if (options.expectedGeneration !== void 0) {
1489
+ parts.push(
1490
+ `--expected-generation ${fleetShellArg(options.expectedGeneration)}`
1491
+ );
1492
+ }
1493
+ if (options.idempotencyKey) {
1494
+ parts.push(`--idempotency-key ${fleetShellArg(options.idempotencyKey)}`);
1495
+ }
1496
+ parts.push(...fleetJsonFlag(options));
1497
+ return parts.join(" ");
1498
+ }
1499
+ async function handleMonitorFleetsSync(target, options, idempotencyKey) {
1500
+ const fileDefinitions = options.file ? readMonitorDefinitionsJsonFile(options.file) : void 0;
1501
+ const usesDefinition = options.file !== void 0 || _optionalChain([target, 'optionalAccess', _44 => _44.trim, 'call', _45 => _45(), 'access', _46 => _46.startsWith, 'call', _47 => _47("{")]) === true;
1502
+ if (!usesDefinition && !_optionalChain([target, 'optionalAccess', _48 => _48.trim, 'call', _49 => _49()])) {
1503
+ throw new MonitorsUsageError(
1504
+ "sync needs a fleet: pass --file fleet.json to apply a definition, or <fleet-id> to re-plan the stored one.\n deepline monitors fleets sync --file fleet.json --dry-run\n deepline monitors fleets sync <fleet-id> --dry-run"
1505
+ );
1506
+ }
1507
+ const definition = usesDefinition ? requireCompiledFleetDefinition(
1508
+ _nullishCoalesce(asRecord(
1509
+ _nullishCoalesce(fileDefinitions, () => ( resolveMonitorJsonBody({
1510
+ positional: target,
1511
+ file: options.file,
1512
+ argLabel: "<definition>",
1513
+ command: "deepline monitors fleets sync"
1514
+ })))
1515
+ ), () => ( {}))
1516
+ ) : void 0;
1517
+ const fleetId = definition ? _nullishCoalesce(asString(definition.id), () => ( "")) : target.trim();
1518
+ if (!fleetId) {
1519
+ throw new MonitorsUsageError(
1520
+ 'The Fleet definition has no id. Add a top-level "id" and re-run.'
1521
+ );
1522
+ }
1523
+ const client = new (0, _chunk2S5Y3TZPjs.DeeplineClient)();
1524
+ const payload = await client.monitors.fleets.sync(
1525
+ _nullishCoalesce(definition, () => ( fleetId)),
1526
+ {
1527
+ ...options.dryRun ? { dryRun: true } : {},
1528
+ ...options.expectedGeneration !== void 0 ? {
1529
+ expectedGeneration: fleetIntegerOption(
1530
+ options.expectedGeneration,
1531
+ "--expected-generation"
1532
+ )
1533
+ } : {},
1534
+ idempotencyKey
1535
+ }
1536
+ );
1537
+ if (options.dryRun) {
1538
+ assertMonitorDryRunAcknowledged(payload, {
1539
+ command: "deepline monitors fleets sync",
1540
+ mutation: "fleet sync"
1541
+ });
1542
+ }
1543
+ const accepted = { ...payload, idempotency_key: idempotencyKey };
1544
+ if (!options.wait || options.dryRun) {
1545
+ _chunkF35VOIQLjs.printCommandEnvelope.call(void 0, accepted, {
1546
+ json: options.json,
1547
+ text: renderFleetSync(payload, {
1548
+ fleetId,
1549
+ dryRun: options.dryRun === true,
1550
+ idempotencyKey
1551
+ })
1552
+ });
1553
+ return;
1554
+ }
1555
+ const timeoutMs = fleetTimeoutMs(options.timeout);
1556
+ const progress = fleetProgressReporter();
1557
+ let final;
1558
+ try {
1559
+ final = await client.monitors.fleets.waitForConvergence(fleetId, {
1560
+ timeoutMs,
1561
+ pollIntervalMs: FLEET_POLL_INTERVAL_MS,
1562
+ onProgress: progress.report
1563
+ });
1564
+ } finally {
1565
+ progress.finish();
1566
+ }
1567
+ const envelope = { ...accepted, ...final };
1568
+ const status = fleetStatus(final);
1569
+ const summary = renderFleetGet(final);
1570
+ if (status === "converged") {
1571
+ _chunkF35VOIQLjs.printCommandEnvelope.call(void 0, envelope, { json: options.json, text: summary });
1572
+ return;
1573
+ }
1574
+ const driftCommand = `deepline monitors fleets get ${fleetShellArg(fleetId)} --drift --json`;
1575
+ if (status === "degraded") {
1576
+ reportFleetState(
1577
+ envelope,
1578
+ new MonitorFleetStateError({
1579
+ code: "MONITOR_FLEET_DEGRADED",
1580
+ message: `Fleet ${fleetId} is degraded: some members will not converge without a change. Retrying sync will not fix it.`,
1581
+ next: _nullishCoalesce(fleetServerNext(final), () => ( driftCommand))
1582
+ }),
1583
+ { json: options.json, text: summary }
1584
+ );
1585
+ return;
1586
+ }
1587
+ reportFleetState(
1588
+ envelope,
1589
+ new MonitorFleetStateError({
1590
+ code: "MONITOR_FLEET_WAIT_TIMEOUT",
1591
+ message: `Stopped waiting after ${timeoutMs}ms. Nothing is broken and nothing was lost \u2014 fleet ${fleetId} is still ${_nullishCoalesce(status, () => ( "working"))} on the server.`,
1592
+ next: _nullishCoalesce(fleetServerNext(final), () => ( driftCommand))
1593
+ }),
1594
+ { json: options.json, text: summary }
1595
+ );
1596
+ }
1597
+ async function handleMonitorFleetsGet(fleetId, options) {
1598
+ if (options.drift && !fleetId) {
1599
+ throw new MonitorsUsageError(
1600
+ "--drift needs a fleet id: deepline monitors fleets get <fleet-id> --drift"
1601
+ );
1602
+ }
1603
+ const limit = options.limit === void 0 ? void 0 : fleetIntegerOption(options.limit, "--limit");
1604
+ const client = new (0, _chunk2S5Y3TZPjs.DeeplineClient)();
1605
+ const payload = await client.monitors.fleets.get(fleetId, {
1606
+ ...options.drift ? { drift: true } : {},
1607
+ ...limit !== void 0 ? { limit } : {}
1608
+ });
1609
+ const text = fleetId ? renderFleetGet(payload) : renderFleetList(payload);
1610
+ if (!options.check) {
1611
+ _chunkF35VOIQLjs.printCommandEnvelope.call(void 0, payload, { json: options.json, text });
1612
+ return;
1613
+ }
1614
+ const statuses = fleetId ? [fleetStatus(payload)] : (Array.isArray(payload.fleets) ? payload.fleets : []).map(
1615
+ (raw) => fleetStatus(_nullishCoalesce(asRecord(raw), () => ( {})))
1616
+ );
1617
+ const unconverged = statuses.filter((status) => status !== "converged");
1618
+ if (unconverged.length === 0) {
1619
+ _chunkF35VOIQLjs.printCommandEnvelope.call(void 0, payload, { json: options.json, text });
1620
+ return;
1621
+ }
1622
+ const target = _nullishCoalesce(fleetId, () => ( "<fleet-id>"));
1623
+ const degraded = unconverged.includes("degraded");
1624
+ reportFleetState(
1625
+ payload,
1626
+ new MonitorFleetStateError({
1627
+ code: degraded ? "MONITOR_FLEET_DEGRADED" : "MONITOR_FLEET_NOT_CONVERGED",
1628
+ message: degraded ? `Fleet ${target} is degraded: members are stuck and retrying will not move them.` : `Fleet ${target} has not converged yet.`,
1629
+ next: _nullishCoalesce(fleetServerNext(payload), () => ( `deepline monitors fleets get ${fleetShellArg(target)} --drift --json`))
1630
+ }),
1631
+ { json: options.json, text }
1632
+ );
1633
+ }
1634
+ function fleetReactivateCommandLine(fleetId, options) {
1635
+ const parts = [
1636
+ "deepline",
1637
+ "monitors",
1638
+ "fleets",
1639
+ "reactivate",
1640
+ fleetShellArg(fleetId),
1641
+ "--yes"
1642
+ ];
1643
+ if (options.wait) parts.push("--wait");
1644
+ if (options.timeout)
1645
+ parts.push(`--timeout ${fleetShellArg(options.timeout)}`);
1646
+ if (options.idempotencyKey)
1647
+ parts.push(`--idempotency-key ${fleetShellArg(options.idempotencyKey)}`);
1648
+ parts.push(...fleetJsonFlag(options));
1649
+ return parts.join(" ");
1650
+ }
1651
+ async function handleMonitorFleetsReactivate(fleetId, options, idempotencyKey) {
1652
+ if (!options.yes) {
1653
+ throw new MonitorsUsageError(
1654
+ `reactivate can recreate every suspended provider monitor and restart lifecycle billing. Confirm with --yes:
1655
+ ${fleetReactivateCommandLine(fleetId, options)}`
1656
+ );
1657
+ }
1658
+ const client = new (0, _chunk2S5Y3TZPjs.DeeplineClient)();
1659
+ const payload = await client.monitors.fleets.reactivate(fleetId, {
1660
+ idempotencyKey
1661
+ });
1662
+ const accepted = { ...payload, idempotency_key: idempotencyKey };
1663
+ if (!options.wait) {
1664
+ _chunkF35VOIQLjs.printCommandEnvelope.call(void 0, accepted, {
1665
+ json: options.json,
1666
+ text: `Fleet ${fleetId} \u2014 ${readMonitorState(payload) ? `state ${readMonitorState(payload)}` : "reactivation accepted"}
1667
+ idempotency key ${idempotencyKey}
1668
+ `
1669
+ });
1670
+ return;
1671
+ }
1672
+ const timeoutMs = fleetTimeoutMs(options.timeout);
1673
+ const progress = fleetProgressReporter();
1674
+ let final;
1675
+ try {
1676
+ final = await client.monitors.fleets.waitForConvergence(fleetId, {
1677
+ timeoutMs,
1678
+ pollIntervalMs: FLEET_POLL_INTERVAL_MS,
1679
+ onProgress: progress.report
1680
+ });
1681
+ } finally {
1682
+ progress.finish();
1683
+ }
1684
+ const envelope = { ...accepted, ...final };
1685
+ const text = renderFleetGet(final);
1686
+ if (fleetStatus(final) === "converged") {
1687
+ _chunkF35VOIQLjs.printCommandEnvelope.call(void 0, envelope, { json: options.json, text });
1688
+ return;
1689
+ }
1690
+ reportFleetState(
1691
+ envelope,
1692
+ new MonitorFleetStateError({
1693
+ code: "MONITOR_FLEET_WAIT_TIMEOUT",
1694
+ message: `Stopped waiting after ${timeoutMs}ms. Fleet ${fleetId} recovery is still in progress on the server.`,
1695
+ next: _nullishCoalesce(fleetServerNext(final), () => ( `deepline monitors fleets get ${fleetShellArg(fleetId)} --json`))
1696
+ }),
1697
+ { json: options.json, text }
1698
+ );
1699
+ }
1700
+ function fleetDeactivateCommandLine(fleetId, options) {
1701
+ const parts = [
1702
+ "deepline monitors fleets deactivate",
1703
+ fleetShellArg(fleetId),
1704
+ "--yes"
1705
+ ];
1706
+ if (options.dryRun) parts.push("--dry-run");
1707
+ if (options.wait) parts.push("--wait");
1708
+ if (options.timeout)
1709
+ parts.push(`--timeout ${fleetShellArg(options.timeout)}`);
1710
+ if (options.idempotencyKey) {
1711
+ parts.push(`--idempotency-key ${fleetShellArg(options.idempotencyKey)}`);
1712
+ }
1713
+ parts.push(...fleetJsonFlag(options));
1714
+ return parts.join(" ");
1715
+ }
1716
+ async function confirmFleetDeactivate(fleetId, plan) {
1717
+ process.stderr.write(renderFleetDeactivatePlan(plan, fleetId));
1718
+ const rl = _promises.createInterface.call(void 0, { input: process.stdin, output: process.stderr });
1719
+ try {
1720
+ const answer = await rl.question(
1721
+ `Deactivate fleet "${fleetId}" and the monitors it owns? [y/N] `
1722
+ );
1723
+ return /^y(es)?$/i.test(answer.trim());
1724
+ } finally {
1725
+ rl.close();
1726
+ }
1727
+ }
1728
+ async function handleMonitorFleetsDeactivate(fleetId, options, idempotencyKey) {
1729
+ const client = new (0, _chunk2S5Y3TZPjs.DeeplineClient)();
1730
+ if (options.dryRun) {
1731
+ const plan = await client.monitors.fleets.deactivate(fleetId, {
1732
+ dryRun: true,
1733
+ idempotencyKey
1734
+ });
1735
+ assertMonitorDryRunAcknowledged(plan, {
1736
+ command: "deepline monitors fleets deactivate",
1737
+ mutation: "fleet deactivate"
1738
+ });
1739
+ _chunkF35VOIQLjs.printCommandEnvelope.call(void 0, plan, {
1740
+ json: options.json,
1741
+ text: renderFleetDeactivatePlan(plan, fleetId)
1742
+ });
1743
+ return;
1744
+ }
1745
+ if (!options.yes) {
1746
+ const interactive = process.stdout.isTTY === true && process.stdin.isTTY === true;
1747
+ if (!interactive) {
1748
+ throw new MonitorsUsageError(
1749
+ `deactivate is destructive: it deactivates fleet "${fleetId}" and every monitor it owns. Non-interactive runs must confirm with --yes:
1750
+ ${fleetDeactivateCommandLine(fleetId, options)}
1751
+ Preview the blast radius first:
1752
+ deepline monitors fleets deactivate ${fleetShellArg(fleetId)} --dry-run`
1753
+ );
1754
+ }
1755
+ const plan = await client.monitors.fleets.deactivate(fleetId, {
1756
+ dryRun: true,
1757
+ idempotencyKey: `${idempotencyKey}-plan`
1758
+ });
1759
+ assertMonitorDryRunAcknowledged(plan, {
1760
+ command: "deepline monitors fleets deactivate",
1761
+ mutation: "fleet deactivate"
1762
+ });
1763
+ if (!await confirmFleetDeactivate(fleetId, plan)) {
1764
+ process.stderr.write(
1765
+ `Aborted. Fleet "${fleetId}" was not deactivated.
1766
+ `
1767
+ );
1768
+ process.exitCode = 2;
1769
+ return;
1770
+ }
1771
+ }
1772
+ const payload = await client.monitors.fleets.deactivate(fleetId, {
1773
+ idempotencyKey
1774
+ });
1775
+ const accepted = { ...payload, idempotency_key: idempotencyKey };
1776
+ if (payload.already === true) {
1777
+ _chunkF35VOIQLjs.printCommandEnvelope.call(void 0, accepted, {
1778
+ json: options.json,
1779
+ text: `Fleet ${fleetId} is already deactivated.
1780
+ `
1781
+ });
1782
+ return;
1783
+ }
1784
+ const acceptedText = `Fleet ${fleetId} \u2014 ${readMonitorState(payload) ? `state ${readMonitorState(payload)}` : "deactivation accepted"}
1785
+ idempotency key ${idempotencyKey}
1786
+ ` + (fleetServerNext(payload) ? `Next: ${fleetServerNext(payload)}
1787
+ ` : "");
1788
+ if (!options.wait) {
1789
+ _chunkF35VOIQLjs.printCommandEnvelope.call(void 0, accepted, {
1790
+ json: options.json,
1791
+ text: acceptedText
1792
+ });
1793
+ return;
1794
+ }
1795
+ const timeoutMs = fleetTimeoutMs(options.timeout);
1796
+ const progress = fleetProgressReporter();
1797
+ let final;
1798
+ try {
1799
+ final = await client.monitors.fleets.waitForConvergence(fleetId, {
1800
+ timeoutMs,
1801
+ pollIntervalMs: FLEET_POLL_INTERVAL_MS,
1802
+ onProgress: progress.report,
1803
+ until: "deactivated"
1804
+ });
1805
+ } finally {
1806
+ progress.finish();
1807
+ }
1808
+ const envelope = { ...accepted, ...final };
1809
+ const summary = renderFleetGet(final);
1810
+ if (fleetStatus(final) === "deactivated") {
1811
+ _chunkF35VOIQLjs.printCommandEnvelope.call(void 0, envelope, { json: options.json, text: summary });
1812
+ return;
1813
+ }
1814
+ reportFleetState(
1815
+ envelope,
1816
+ new MonitorFleetStateError({
1817
+ code: "MONITOR_FLEET_WAIT_TIMEOUT",
1818
+ message: `Stopped waiting after ${timeoutMs}ms. Deactivation of fleet ${fleetId} is still in progress on the server; nothing was lost.`,
1819
+ next: _nullishCoalesce(fleetServerNext(final), () => ( `deepline monitors fleets get ${fleetShellArg(fleetId)} --json`))
1820
+ }),
1821
+ { json: options.json, text: summary }
1822
+ );
1823
+ }
1824
+ function handleMonitorFleetsOverview(options) {
1825
+ const lines = [
1826
+ "Monitor Fleets \u2014 one Customer DB table row, one ordinary monitor.",
1827
+ "",
1828
+ "Lifecycle:",
1829
+ ...MONITOR_FLEET_LIFECYCLE.flatMap((entry) => [
1830
+ ` ${entry.step}. ${entry.what}`,
1831
+ ` ${entry.command}`
1832
+ ]),
1833
+ "",
1834
+ "Commands:",
1835
+ ...MONITOR_FLEET_COMMANDS.map(
1836
+ (command) => ` ${command.name.padEnd(12)}${command.summary}`
1837
+ ),
1838
+ "",
1839
+ "Agent notes:",
1840
+ ...MONITOR_FLEET_AGENT_NOTES.map((note) => ` ${note}`)
1841
+ ];
1842
+ _chunkF35VOIQLjs.printCommandEnvelope.call(void 0,
1843
+ {
1844
+ schemaVersion: 1,
1845
+ lifecycle: MONITOR_FLEET_LIFECYCLE,
1846
+ commands: MONITOR_FLEET_COMMANDS,
1847
+ agent_notes: MONITOR_FLEET_AGENT_NOTES,
1848
+ next: MONITOR_FLEET_LIFECYCLE[0].command
1849
+ },
1850
+ { json: options.json, text: `${lines.join("\n")}
1851
+ ` }
1852
+ );
1853
+ }
1854
+ function renderMonitorGet(payload) {
1855
+ const key = asString(payload.key);
1856
+ const tool = asString(payload.tool);
1857
+ if (!key || !tool) return void 0;
1858
+ const state = readMonitorState(payload);
1859
+ const monitorType = asString(payload.type);
1860
+ const hasLastReceivedEvent = "last_received_event" in payload;
1861
+ const lastReceivedEvent = asString(payload.last_received_event);
1862
+ const definition = asRecord(payload.definition);
1863
+ const pricingLine = monitorPricingLine(payload.pricing);
1864
+ const billing = asRecord(payload.billing);
1865
+ const nextRenewalAt = billing ? asString(billing.next_renewal_at) : void 0;
1866
+ const dependents = asRecord(payload.dependents);
1867
+ const webhook = asRecord(payload.webhook);
1868
+ const guidance = asRecord(payload.setup_guidance);
1869
+ const plays = dependents && Array.isArray(dependents.plays) ? dependents.plays : [];
1870
+ const boundPlays = Array.isArray(payload.bound_plays) ? payload.bound_plays.flatMap((value) => {
1871
+ const play = asRecord(value);
1872
+ return play ? [play] : [];
1873
+ }) : [];
1874
+ const lines = [
1875
+ `Monitor: ${key}`,
1876
+ `Tool: ${tool}`,
1877
+ ...monitorType ? [`Type: ${monitorType}`] : [],
1878
+ ...state ? [`Status: ${state}`] : [],
1879
+ ...hasLastReceivedEvent ? [`Latest inbound event: ${_nullishCoalesce(lastReceivedEvent, () => ( "never"))}`] : [],
1880
+ ...pricingLine ? [`Pricing: ${pricingLine}`] : [],
1881
+ ...nextRenewalAt ? [`Next renewal: ${nextRenewalAt}`] : []
1882
+ ];
1883
+ if (definition) {
1884
+ lines.push("", "Current definition:", ` ${JSON.stringify(definition)}`);
1885
+ }
1886
+ if (webhook) {
1887
+ lines.push("", `Webhook: ${_nullishCoalesce(asString(webhook.state), () => ( "unknown"))}`);
1888
+ const callbackUrl = asString(webhook.callback_url);
1889
+ if (callbackUrl) lines.push(` Callback URL (sensitive): ${callbackUrl}`);
1890
+ }
1891
+ if (guidance) {
1892
+ lines.push("", _nullishCoalesce(asString(guidance.title), () => ( "Provider setup:")));
1893
+ for (const step of Array.isArray(guidance.steps) ? guidance.steps : []) {
1894
+ const text = asString(step);
1895
+ if (text) lines.push(` \u2022 ${text}`);
1896
+ }
1897
+ for (const raw of Array.isArray(guidance.documentation) ? guidance.documentation : []) {
1898
+ const doc = asRecord(raw);
1899
+ const label = asString(_optionalChain([doc, 'optionalAccess', _50 => _50.label]));
1900
+ const url = asString(_optionalChain([doc, 'optionalAccess', _51 => _51.url]));
1901
+ if (label && url) lines.push(` Docs: ${label} \u2014 ${url}`);
1902
+ }
1903
+ const payloadExample = asRecord(guidance.payload_example);
1904
+ if (payloadExample) {
1905
+ lines.push(` Payload example: ${JSON.stringify(payloadExample)}`);
1906
+ }
1907
+ }
1908
+ const samplePayload = asRecord(payload.sample_payload);
1909
+ if (samplePayload) {
1910
+ lines.push(
1911
+ "",
1912
+ `Sample test payload: ${JSON.stringify(samplePayload)}`,
1913
+ ` deepline monitors test ${key} '${JSON.stringify(samplePayload)}' --json`
1914
+ );
1915
+ }
1916
+ const monitorSpec = asRecord(payload.monitor_spec);
1917
+ if (_optionalChain([monitorSpec, 'optionalAccess', _52 => _52.available]) === false) {
1918
+ lines.push(
1919
+ "",
1920
+ `Monitor spec: unavailable \u2014 ${_nullishCoalesce(asString(monitorSpec.message), () => ( "use the stored definition and check before an update."))}`
1921
+ );
1922
+ }
1923
+ const specFields = Array.isArray(_optionalChain([monitorSpec, 'optionalAccess', _53 => _53.fields])) ? monitorSpec.fields.flatMap((value) => {
1924
+ const field = asRecord(value);
1925
+ const path = asString(_optionalChain([field, 'optionalAccess', _54 => _54.path]));
1926
+ const description = asString(_optionalChain([field, 'optionalAccess', _55 => _55.description]));
1927
+ const semantics = asString(_optionalChain([field, 'optionalAccess', _56 => _56.semantics]));
1928
+ const applicability = asString(_optionalChain([field, 'optionalAccess', _57 => _57.applicability]));
1929
+ const grammar = asRecord(_optionalChain([field, 'optionalAccess', _58 => _58.grammar]));
1930
+ const grammarSyntax = asString(_optionalChain([grammar, 'optionalAccess', _59 => _59.syntax]));
1931
+ return path ? [
1932
+ {
1933
+ path,
1934
+ description,
1935
+ semantics,
1936
+ applicability,
1937
+ grammarSyntax
1938
+ }
1939
+ ] : [];
1940
+ }) : [];
1941
+ if (specFields.length > 0) {
1942
+ lines.push("", "Monitor spec:");
1943
+ for (const field of specFields) {
1944
+ lines.push(
1945
+ ` ${field.path}${field.description ? ` \u2014 ${field.description}` : ""}`
1946
+ );
1947
+ if (field.semantics && field.semantics !== field.description) {
1948
+ lines.push(` Behavior: ${field.semantics}`);
1949
+ }
1950
+ if (field.applicability) {
1951
+ lines.push(` Applies to: ${field.applicability}`);
1952
+ }
1953
+ if (field.grammarSyntax) {
1954
+ lines.push(` Format: ${field.grammarSyntax}`);
1955
+ }
1956
+ }
1957
+ }
1958
+ lines.push("", `Current SQL listener consumers (${boundPlays.length}):`);
1959
+ if (boundPlays.length === 0) {
1960
+ lines.push(" none");
1961
+ } else {
1962
+ for (const play of boundPlays) {
1963
+ const name = _nullishCoalesce(asString(play.name), () => ( "unnamed Play"));
1964
+ const listener = asString(play.listener_key);
1965
+ const health = asRecord(play.consumer_health);
1966
+ const runStatus = asString(_optionalChain([health, 'optionalAccess', _60 => _60.last_run_status]));
1967
+ const lastDelivery = asFiniteNumber(_optionalChain([health, 'optionalAccess', _61 => _61.last_delivery_at]));
1968
+ const runId = asString(_optionalChain([health, 'optionalAccess', _62 => _62.last_run_id]));
1969
+ const error = asString(_optionalChain([health, 'optionalAccess', _63 => _63.last_error]));
1970
+ lines.push(` ${name}${listener ? ` (listener: ${listener})` : ""}:`);
1971
+ lines.push(
1972
+ ` Latest delivered event: ${lastDelivery !== void 0 ? new Date(lastDelivery).toISOString() : "never"}`,
1973
+ ` Latest consumer run: ${_nullishCoalesce(runId, () => ( "never"))}${runStatus ? ` (${runStatus})` : ""}`
1974
+ );
1975
+ if (error) lines.push(` error: ${error}`);
1976
+ }
1977
+ }
1978
+ if (payload.consumer_health_truncated === true) {
1979
+ lines.push(" Results are truncated; use --json for the returned detail.");
1980
+ }
1981
+ lines.push("", `Dependent published plays (${plays.length}):`);
1982
+ if (plays.length === 0) {
1983
+ lines.push(" none");
1984
+ } else {
1985
+ for (const raw of plays) {
1986
+ const play = asRecord(raw);
1987
+ const name = play ? asString(play.name) : void 0;
1988
+ if (!play || !name) continue;
1989
+ const listener = asString(play.listener_key);
1990
+ const output = asString(play.output_key);
1991
+ lines.push(
1992
+ ` ${name}${listener ? ` (listener: ${listener})` : ""}${output ? ` \u2014 stream: ${output}` : ""}`
1993
+ );
1994
+ }
1995
+ }
1996
+ if (_optionalChain([dependents, 'optionalAccess', _64 => _64.truncated]) === true) {
1997
+ lines.push(" Results are truncated; use --json for the returned detail.");
1998
+ }
1999
+ return `${lines.join("\n")}
2000
+ `;
2001
+ }
2002
+ async function handleMonitorsGet(key, options) {
2003
+ const client = new (0, _chunk2S5Y3TZPjs.DeeplineClient)();
2004
+ const payload = await client.monitors.get(key);
2005
+ const boundPlays = Array.isArray(payload.bound_plays) ? payload.bound_plays : null;
2006
+ const dependents = boundPlays ? {
2007
+ plays: boundPlays,
2008
+ truncated: payload.consumer_health_truncated === true
2009
+ } : await client.monitors.dependents(key);
2010
+ const detail = { ...payload, dependents };
2011
+ _chunkF35VOIQLjs.printCommandEnvelope.call(void 0, detail, {
2012
+ json: options.json,
2013
+ text: renderMonitorGet(detail)
2014
+ });
2015
+ }
2016
+ async function handleMonitorsTest(key, payload, options) {
2017
+ const explicitPayload = parseJsonObjectArg(payload, "<payload>");
2018
+ const result = await new (0, _chunk2S5Y3TZPjs.DeeplineClient)().monitors.test(key, explicitPayload);
2019
+ const text = `Monitor diagnostic for ${key}: ${result.accepted === true ? "accepted" : "rejected"}
2020
+ mode: validation_only (no rows written, credits spent, or Plays dispatched)
2021
+ persisted rows: ${_nullishCoalesce(asFiniteNumber(result.persisted_rows), () => ( 0))}
2022
+ dispatched bound Plays: ${_nullishCoalesce(asFiniteNumber(result.dispatched_bound_plays), () => ( 0))}
2023
+ `;
2024
+ _chunkF35VOIQLjs.printCommandEnvelope.call(void 0, result, { json: options.json, text });
2025
+ }
2026
+ async function handleMonitorsValidate(key, options) {
2027
+ const result = await new (0, _chunk2S5Y3TZPjs.DeeplineClient)().monitors.validate(key);
2028
+ _chunkF35VOIQLjs.printCommandEnvelope.call(void 0, result, { json: options.json });
2029
+ if (result.valid === false) process.exitCode = 7;
2030
+ }
2031
+ async function confirmMonitorDelete(key) {
2032
+ const rl = _promises.createInterface.call(void 0, {
2033
+ input: process.stdin,
2034
+ output: process.stderr
2035
+ });
2036
+ try {
2037
+ const answer = await rl.question(
2038
+ `Delete monitor "${key}"? This deprovisions the upstream provider resource. [y/N] `
2039
+ );
2040
+ return /^y(es)?$/i.test(answer.trim());
2041
+ } finally {
2042
+ rl.close();
2043
+ }
2044
+ }
2045
+ async function handleMonitorsDelete(key, options) {
2046
+ const client = new (0, _chunk2S5Y3TZPjs.DeeplineClient)();
2047
+ if (options.dryRun) {
2048
+ const payload2 = await client.monitors.delete(key, { dryRun: true });
2049
+ assertMonitorDryRunAcknowledged(payload2, {
2050
+ command: "deepline monitors delete",
2051
+ mutation: "delete"
2052
+ });
2053
+ _chunkF35VOIQLjs.printCommandEnvelope.call(void 0, payload2, {
2054
+ json: options.json,
2055
+ text: renderMonitorDeletePlan(payload2, key)
2056
+ });
2057
+ return;
2058
+ }
2059
+ if (!options.yes) {
2060
+ const interactive = process.stdout.isTTY === true && process.stdin.isTTY === true;
2061
+ if (!interactive) {
2062
+ throw monitorDeleteRequiresYesError(key);
2063
+ }
2064
+ const confirmed = await confirmMonitorDelete(key);
2065
+ if (!confirmed) {
2066
+ process.stderr.write(`Aborted. Monitor "${key}" was not deleted.
2067
+ `);
2068
+ process.exitCode = 2;
2069
+ return;
2070
+ }
2071
+ }
2072
+ const payload = await client.monitors.delete(key);
2073
+ _chunkF35VOIQLjs.printCommandEnvelope.call(void 0, payload, { json: options.json });
2074
+ }
2075
+ async function handleMonitorsUpdate(key, patch, options) {
2076
+ const body = resolveMonitorJsonBody({
2077
+ positional: patch,
2078
+ file: options.file,
2079
+ argLabel: "<patch>",
2080
+ command: `deepline monitors update ${key}`
2081
+ });
2082
+ const payload = await new (0, _chunk2S5Y3TZPjs.DeeplineClient)().monitors.update(key, body);
2083
+ _chunkF35VOIQLjs.printCommandEnvelope.call(void 0, payload, { json: options.json });
2084
+ }
2085
+ async function handleMonitorsReactivate(key, options) {
2086
+ const client = new (0, _chunk2S5Y3TZPjs.DeeplineClient)();
2087
+ if (options.dryRun) {
2088
+ const payload2 = await client.monitors.reactivate(key, { dryRun: true });
2089
+ assertMonitorDryRunAcknowledged(payload2, {
2090
+ command: "deepline monitors reactivate",
2091
+ mutation: "reactivate"
2092
+ });
2093
+ _chunkF35VOIQLjs.printCommandEnvelope.call(void 0, payload2, {
2094
+ json: options.json,
2095
+ text: renderMonitorReactivatePlan(payload2, key)
2096
+ });
2097
+ return;
2098
+ }
2099
+ const payload = await client.monitors.reactivate(key);
2100
+ _chunkF35VOIQLjs.printCommandEnvelope.call(void 0, payload, { json: options.json });
2101
+ }
2102
+ var MONITOR_VERB_POLL_INTERVAL_MS = 2e3;
2103
+ function monitorHealthLine(health) {
2104
+ if (_optionalChain([health, 'access', _65 => _65.refresh, 'optionalAccess', _66 => _66.state]) === "running") {
2105
+ return `refreshing whole scope \xB7 scanned ${health.scanned} so far`;
2106
+ }
2107
+ const alignmentRequired = _nullishCoalesce(health.alignment_required, () => ( 0));
2108
+ return [
2109
+ `converged ${health.converged}/${health.scanned}`,
2110
+ `needs_repair ${health.needs_repair}`,
2111
+ `missing ${health.observed.missing}`,
2112
+ `unaudited ${health.observed.unknown + health.observed.unset}`,
2113
+ ...alignmentRequired > 0 ? [`needs_alignment ${alignmentRequired}`] : [],
2114
+ `silent ${health.silent}`
2115
+ ].join(" \xB7 ");
2116
+ }
2117
+ function monitorVerbProgressReporter() {
2118
+ const interactive = process.stderr.isTTY === true;
2119
+ let wrote = false;
2120
+ let lastPlainAt = 0;
2121
+ return {
2122
+ report: (health) => {
2123
+ const line = monitorHealthLine(health);
2124
+ if (interactive) {
2125
+ process.stderr.write(`\r\x1B[2K${line}`);
2126
+ wrote = true;
2127
+ return;
2128
+ }
2129
+ const now = Date.now();
2130
+ if (wrote && now - lastPlainAt < FLEET_PLAIN_PROGRESS_INTERVAL_MS) return;
2131
+ lastPlainAt = now;
2132
+ wrote = true;
2133
+ process.stderr.write(`${line}
2134
+ `);
2135
+ },
2136
+ finish: () => {
2137
+ if (interactive && wrote) process.stderr.write("\n");
2138
+ }
2139
+ };
2140
+ }
2141
+ async function watchMonitorHealth(input) {
2142
+ const deadlineAt = Date.now() + input.timeoutMs;
2143
+ const scope = input.fleetId ? { fleetId: input.fleetId } : {};
2144
+ let last = await input.client.monitors.health(scope);
2145
+ input.onProgress(last);
2146
+ while (Date.now() < deadlineAt) {
2147
+ const unresolved = last.observed.unknown + last.observed.unset;
2148
+ const alignmentRequired = _nullishCoalesce(last.alignment_required, () => ( 0));
2149
+ if (_optionalChain([last, 'access', _67 => _67.refresh, 'optionalAccess', _68 => _68.state]) !== "running" && !last.truncated && last.needs_repair === 0 && (unresolved === 0 || alignmentRequired === unresolved)) {
2150
+ return last;
2151
+ }
2152
+ await new Promise(
2153
+ (resolve2) => setTimeout(resolve2, MONITOR_VERB_POLL_INTERVAL_MS)
2154
+ );
2155
+ last = await input.client.monitors.health(scope);
2156
+ input.onProgress(last);
2157
+ }
2158
+ return last;
2159
+ }
2160
+ function monitorHealthText(health) {
2161
+ const partial = _optionalChain([health, 'access', _69 => _69.refresh, 'optionalAccess', _70 => _70.state]) === "running" ? " (refreshing \u2014 counts below are not final)" : health.truncated ? " (partial \u2014 scope larger than one read)" : "";
2162
+ const unauditedMonitors = _nullishCoalesce(health.unaudited_monitors, () => ( []));
2163
+ const lines = [
2164
+ `scope: ${_nullishCoalesce(health.scope.fleet_id, () => ( "workspace"))}${partial}`,
2165
+ monitorHealthLine(health)
2166
+ ];
2167
+ if ((_nullishCoalesce(_optionalChain([health, 'access', _71 => _71.batch_operations, 'optionalAccess', _72 => _72.length]), () => ( 0))) > 0) {
2168
+ lines.push("");
2169
+ lines.push("batch work in progress:");
2170
+ for (const operation of _nullishCoalesce(health.batch_operations, () => ( []))) {
2171
+ const retry = operation.next_attempt_at === void 0 ? "" : ` \xB7 next ${new Date(operation.next_attempt_at).toISOString()}`;
2172
+ lines.push(
2173
+ ` ${operation.kind} ${operation.run_id} \xB7 ${operation.state}${retry}`
2174
+ );
2175
+ }
2176
+ }
2177
+ if (health.deactivation_reasons.length > 0) {
2178
+ lines.push("");
2179
+ lines.push("deactivated by Deepline:");
2180
+ for (const entry of health.deactivation_reasons) {
2181
+ const how = entry.resolution ? ` \u2014 ${entry.resolution}` : "";
2182
+ lines.push(` ${entry.reason} (${entry.count})${how}`);
2183
+ }
2184
+ }
2185
+ if (unauditedMonitors.length > 0) {
2186
+ const reason = {
2187
+ not_yet_audited: "has not been observed yet",
2188
+ missing_provider_resource_id: "has no stored upstream resource id",
2189
+ provider_observation_unknown: "the provider observation is still unknown"
2190
+ };
2191
+ lines.push("");
2192
+ lines.push("unresolved monitor observations:");
2193
+ for (const entry of unauditedMonitors) {
2194
+ lines.push(
2195
+ ` ${entry.monitor_key} ${entry.tool} \u2014 ${reason[entry.reason]}`
2196
+ );
2197
+ }
2198
+ }
2199
+ if ((_nullishCoalesce(health.alignment_required, () => ( 0))) > 0) {
2200
+ lines.push("");
2201
+ lines.push(
2202
+ `${health.alignment_required} monitor(s) need provider identity alignment; normal repair intentionally will not guess or create a paid replacement.`
2203
+ );
2204
+ lines.push(
2205
+ `Run the exact inventory audit, then review one safe adoption candidate: deepline-admin monitors reconcile ${health.scope.org_id} --monitor <monitor-key> --environment production --json`
2206
+ );
2207
+ }
2208
+ if (health.worst_offenders.length > 0) {
2209
+ lines.push("");
2210
+ lines.push(
2211
+ `silent longest (no delivery in ${health.silent_window_days}d):`
2212
+ );
2213
+ for (const entry of health.worst_offenders) {
2214
+ const when = entry.last_event_at === null ? "never" : new Date(entry.last_event_at).toISOString();
2215
+ lines.push(` ${entry.monitor_key} ${entry.tool} last event ${when}`);
2216
+ }
2217
+ }
2218
+ return `${lines.join("\n")}
2219
+ `;
2220
+ }
2221
+ async function handleMonitorsAudit(options) {
2222
+ const client = new (0, _chunk2S5Y3TZPjs.DeeplineClient)();
2223
+ const fleetId = _optionalChain([options, 'access', _73 => _73.fleet, 'optionalAccess', _74 => _74.trim, 'call', _75 => _75()]) || void 0;
2224
+ const scope = fleetId ? { fleetId } : {};
2225
+ let result = await client.monitors.audit(scope);
2226
+ const passes = [result.audit];
2227
+ while (result.audit.cursor !== null) {
2228
+ result = await client.monitors.audit({
2229
+ ...scope,
2230
+ cursor: result.audit.cursor
2231
+ });
2232
+ passes.push(result.audit);
2233
+ }
2234
+ const totals = passes.reduce(
2235
+ (sum, pass) => ({
2236
+ scanned: sum.scanned + pass.scanned,
2237
+ asked: sum.asked + pass.asked,
2238
+ stale: sum.stale + pass.stale,
2239
+ missing: sum.missing + pass.observed.missing
2240
+ }),
2241
+ { scanned: 0, asked: 0, stale: 0, missing: 0 }
2242
+ );
2243
+ let health = result.health;
2244
+ if (options.watch) {
2245
+ const progress = monitorVerbProgressReporter();
2246
+ try {
2247
+ health = await watchMonitorHealth({
2248
+ client,
2249
+ ...scope,
2250
+ timeoutMs: fleetTimeoutMs(options.timeout),
2251
+ onProgress: progress.report
2252
+ });
2253
+ } finally {
2254
+ progress.finish();
2255
+ }
2256
+ }
2257
+ const unauditable = result.audit.unauditable_capabilities;
2258
+ const overtaken = totals.stale > 0 ? ` \xB7 ${totals.stale} observations overtaken by a concurrent settle` : "";
2259
+ const text = [
2260
+ `audited ${totals.scanned} monitors \xB7 asked the provider about ${totals.asked}`,
2261
+ `missing ${totals.missing}${overtaken}`,
2262
+ ...unauditable.length > 0 ? [`not auditable (no batch-read contract): ${unauditable.join(", ")}`] : [],
2263
+ "",
2264
+ monitorHealthText(health)
2265
+ ].join("\n");
2266
+ _chunkF35VOIQLjs.printCommandEnvelope.call(void 0,
2267
+ { ...result, audit: { ...result.audit, totals }, health },
2268
+ { json: options.json, text }
2269
+ );
2270
+ }
2271
+ async function handleMonitorsRepair(options) {
2272
+ return await handleMonitorBatch("repair", {
2273
+ ...options,
2274
+ ..._optionalChain([options, 'access', _76 => _76.fleet, 'optionalAccess', _77 => _77.trim, 'call', _78 => _78()]) ? {} : { target: "needs-repair" }
2275
+ });
2276
+ }
2277
+ async function handleMonitorsHealth(options) {
2278
+ const fleetId = _optionalChain([options, 'access', _79 => _79.fleet, 'optionalAccess', _80 => _80.trim, 'call', _81 => _81()]) || void 0;
2279
+ const health = await new (0, _chunk2S5Y3TZPjs.DeeplineClient)().monitors.health(
2280
+ fleetId ? { fleetId } : {}
2281
+ );
2282
+ _chunkF35VOIQLjs.printCommandEnvelope.call(void 0, health, {
2283
+ json: options.json,
2284
+ text: monitorHealthText(health)
2285
+ });
2286
+ }
2287
+ function monitorBatchScope(options, kind) {
2288
+ const selectors = [
2289
+ options.target ? "target" : null,
2290
+ _optionalChain([options, 'access', _82 => _82.fleet, 'optionalAccess', _83 => _83.trim, 'call', _84 => _84()]) ? "fleet" : null,
2291
+ _optionalChain([options, 'access', _85 => _85.keys, 'optionalAccess', _86 => _86.trim, 'call', _87 => _87()]) ? "keys" : null
2292
+ ].filter((value) => value !== null);
2293
+ if (selectors.length === 0 && kind === "audit") {
2294
+ return { kind: "target", target: "all" };
2295
+ }
2296
+ if (selectors.length !== 1) {
2297
+ throw new MonitorsUsageError(
2298
+ `monitors batch ${kind} needs exactly one selector: --target, --fleet, or --keys.`
2299
+ );
2300
+ }
2301
+ if (options.target) return { kind: "target", target: options.target };
2302
+ if (_optionalChain([options, 'access', _88 => _88.fleet, 'optionalAccess', _89 => _89.trim, 'call', _90 => _90()]))
2303
+ return { kind: "fleet", fleetId: options.fleet.trim() };
2304
+ const monitorKeys = (_nullishCoalesce(options.keys, () => ( ""))).split(",").map((key) => key.trim()).filter(Boolean);
2305
+ if (monitorKeys.length === 0) {
2306
+ throw new MonitorsUsageError(
2307
+ "--keys needs one or more comma-separated monitor keys."
2308
+ );
2309
+ }
2310
+ return { kind: "keys", monitorKeys };
2311
+ }
2312
+ function monitorBatchIdempotencyKey(kind, value) {
2313
+ return _optionalChain([value, 'optionalAccess', _91 => _91.trim, 'call', _92 => _92()]) || `monitor-batch-${kind}-${_crypto.randomUUID.call(void 0, )}`;
2314
+ }
2315
+ function isCanonicalBatchJsonDocument(raw) {
2316
+ try {
2317
+ const parsed = JSON.parse(raw);
2318
+ if (Array.isArray(parsed)) return true;
2319
+ const input = asRecord(parsed);
2320
+ return input !== null && (input.kind === "batch" || Object.prototype.hasOwnProperty.call(input, "monitors") || Object.prototype.hasOwnProperty.call(input, "version"));
2321
+ } catch (e) {
2322
+ return false;
2323
+ }
2324
+ }
2325
+ async function handleMonitorBatchDeploy(options) {
2326
+ if (!_optionalChain([options, 'access', _93 => _93.file, 'optionalAccess', _94 => _94.trim, 'call', _95 => _95()])) {
2327
+ throw new MonitorsUsageError(
2328
+ "monitors batch deploy requires --file <monitors.ndjson>."
2329
+ );
2330
+ }
2331
+ if (options.dryRun !== true && options.yes !== true) {
2332
+ throw new MonitorsUsageError(
2333
+ "monitors batch deploy changes provider monitors asynchronously. Preview with --dry-run, then confirm with --yes."
2334
+ );
2335
+ }
2336
+ let manifestNdjson;
2337
+ try {
2338
+ manifestNdjson = _fs.readFileSync.call(void 0, _path.resolve.call(void 0, options.file), "utf8");
2339
+ } catch (error) {
2340
+ throw new MonitorsUsageError(
2341
+ `Could not read monitor batch manifest '${options.file}': ${error instanceof Error ? error.message : String(error)}`
2342
+ );
2343
+ }
2344
+ if (!manifestNdjson.trim()) {
2345
+ throw new MonitorsUsageError("Monitor batch manifest is empty.");
2346
+ }
2347
+ if (isCanonicalBatchJsonDocument(manifestNdjson)) {
2348
+ throw new MonitorsUsageError(
2349
+ "Canonical Batch JSON cannot use --dry-run or --yes; those flags select the retained legacy NDJSON operation. Run `deepline monitors batch lint --file <batch.json> --json`, then submit the Monitor Job with `deepline monitors batch deploy --file <batch.json> --idempotency-key <key> --json`."
2350
+ );
2351
+ }
2352
+ const idempotencyKey = monitorBatchIdempotencyKey(
2353
+ "deploy",
2354
+ options.idempotencyKey
2355
+ );
2356
+ const result = await new (0, _chunk2S5Y3TZPjs.DeeplineClient)().monitors.batch.submit({
2357
+ kind: "deploy",
2358
+ manifestNdjson,
2359
+ dryRun: options.dryRun === true,
2360
+ idempotencyKey
2361
+ });
2362
+ const operation = result.operation;
2363
+ _chunkF35VOIQLjs.printCommandEnvelope.call(void 0,
2364
+ { ...result, idempotency_key: idempotencyKey },
2365
+ {
2366
+ json: options.json,
2367
+ text: [
2368
+ `${result.rejoined ? "rejoined" : "submitted"} deploy batch ${operation.runId}`,
2369
+ `state ${operation.state} \xB7 retry key ${idempotencyKey}`,
2370
+ `inspect: deepline monitors batch get ${operation.runId} --json`
2371
+ ].join("\n") + "\n"
2372
+ }
2373
+ );
2374
+ }
2375
+ async function handleMonitorBatch(kind, options) {
2376
+ if ((kind === "deactivate" || kind === "reactivate" || kind === "repair") && options.dryRun !== true && options.yes !== true) {
2377
+ throw new MonitorsUsageError(
2378
+ `monitors batch ${kind} changes provider monitors asynchronously. Preview with --dry-run, then confirm with --yes.`
2379
+ );
2380
+ }
2381
+ const scope = monitorBatchScope(options, kind);
2382
+ if (kind === "deactivate" && scope.kind === "target" && !_optionalChain([options, 'access', _96 => _96.reason, 'optionalAccess', _97 => _97.trim, 'call', _98 => _98()])) {
2383
+ throw new MonitorsUsageError(
2384
+ "monitors batch deactivate --target requires --reason (for example insufficient_balance or billing_failure). Omit --reason with --keys for a customer-requested teardown."
2385
+ );
2386
+ }
2387
+ const idempotencyKey = monitorBatchIdempotencyKey(
2388
+ kind,
2389
+ options.idempotencyKey
2390
+ );
2391
+ const result = await new (0, _chunk2S5Y3TZPjs.DeeplineClient)().monitors.batch.submit({
2392
+ kind,
2393
+ scope,
2394
+ dryRun: options.dryRun === true,
2395
+ ..._optionalChain([options, 'access', _99 => _99.reason, 'optionalAccess', _100 => _100.trim, 'call', _101 => _101()]) ? { deactivationReason: options.reason.trim() } : {},
2396
+ idempotencyKey
2397
+ });
2398
+ const operation = result.operation;
2399
+ const text = [
2400
+ `${result.rejoined ? "rejoined" : "submitted"} ${operation.kind} batch ${operation.runId}`,
2401
+ `state ${operation.state} \xB7 retry key ${idempotencyKey}`,
2402
+ `inspect: deepline monitors batch get ${operation.runId} --json`
2403
+ ].join("\n");
2404
+ _chunkF35VOIQLjs.printCommandEnvelope.call(void 0,
2405
+ { ...result, idempotency_key: idempotencyKey },
2406
+ { json: options.json, text: `${text}
2407
+ ` }
2408
+ );
2409
+ }
2410
+ async function handleMonitorBatchGet(operationId, options) {
2411
+ const result = await new (0, _chunk2S5Y3TZPjs.DeeplineClient)().monitors.batch.get(operationId, {
2412
+ ...options.cursor ? { cursor: options.cursor } : {}
2413
+ });
2414
+ const summary = _nullishCoalesce(result.operation.summary, () => ( {}));
2415
+ const text = [
2416
+ `${result.operation.kind} batch ${result.operation.runId}`,
2417
+ `state ${result.operation.state}`,
2418
+ `progress ${JSON.stringify(summary)}`,
2419
+ ...result.results ? [
2420
+ `results ${result.results.page.length}${result.results.isDone ? "" : " (more; pass --cursor)"}`
2421
+ ] : []
2422
+ ].join("\n");
2423
+ _chunkF35VOIQLjs.printCommandEnvelope.call(void 0, result, { json: options.json, text: `${text}
2424
+ ` });
2425
+ }
2426
+ function registerMonitorsCommands(program) {
2427
+ const monitors = program.command("monitors").description("Discover, deploy, and manage Deepline monitors.").showSuggestionAfterError(true).addHelpText(
2428
+ "after",
2429
+ `
2430
+ Notes:
2431
+ Deepline monitors are Deepline-native signal feeds: a monitor writes events
2432
+ into a Customer DB table; a play reacts to each new row via a
2433
+ sqlListeners trigger \u2014 see \`deepline plays bootstrap monitor-triggered\`.
2434
+ Monitor JSON declares only what to watch (key, tool, optional name, payload).
2435
+ Play bindings belong in the Play; monitor deployment never changes them.
2436
+ The Monitors rollout controls access to the live provider catalog; use
2437
+ \`deepline tools list --categories monitors\` for the exact tool ids available to you.
2438
+ Contact the Deepline team to request access; until access is enabled, these
2439
+ commands return a clear monitor_access_required error.
2440
+
2441
+ Exit codes:
2442
+ 0 success; 2 usage/local input; 3 auth or permission; 4 not found;
2443
+ 5 server failure (retry the same command); 6 not at the desired state
2444
+ (fleets: degraded, or --wait/--check stopped while healthy \u2014 retrying
2445
+ changes nothing); 7 refused, change the request.
2446
+ \`monitors status\` exits 1 when you lack monitor access (documented contract).
2447
+
2448
+ Examples:
2449
+ deepline monitors status --json
2450
+ deepline tools list --categories monitors --json
2451
+ deepline tools get deepline_native.company_radar --json
2452
+ deepline monitors check '{"key":"job-openings","tool":"deepline_native.company_radar","payload":{"domain":"stripe.com","radar_type":"company_job_openings"}}'
2453
+ deepline monitors deploy --dry-run --file monitor.json
2454
+ deepline monitors deploy --file monitor.json
2455
+ deepline monitors list --status all --json
2456
+ deepline monitors get my-monitor --json
2457
+ deepline monitors update my-monitor '{"name":"Interested replies"}' --json
2458
+ deepline monitors delete my-monitor --dry-run
2459
+ deepline monitors reactivate my-monitor --dry-run
2460
+ `
2461
+ );
2462
+ withJsonOption(
2463
+ monitors.command("audit").description(
2464
+ "Re-read what the provider actually holds for your monitors."
2465
+ ).option("--fleet <fleet-id>", "Audit one fleet instead of every monitor").option("--watch", "Keep polling health until the scope settles").option(
2466
+ "--timeout <duration>",
2467
+ "How long --watch waits, e.g. 90s, 5m, 1h (default 10m)"
2468
+ ).addHelpText(
2469
+ "after",
2470
+ `
2471
+ Notes:
2472
+ Asks the provider, by resource id, what it still holds, and records the answer
2473
+ on each monitor. It changes nothing upstream: no creates, no deletes, no
2474
+ intent. Safe to run at any time, as often as you like \u2014 running it twice is
2475
+ running it once, twice.
2476
+
2477
+ A monitor the provider does not return is recorded "missing". Use
2478
+ 'deepline monitors repair' to act on that.
2479
+
2480
+ Examples:
2481
+ deepline monitors audit
2482
+ deepline monitors audit --fleet accounts-eu --json
2483
+ deepline monitors audit --fleet accounts-eu --watch --timeout 5m
2484
+ `
2485
+ )
2486
+ ).action(monitorsAction(handleMonitorsAudit));
2487
+ withJsonOption(
2488
+ monitors.command("repair").description(
2489
+ "Converge the monitors whose desired and observed states disagree."
2490
+ ).option("--fleet <fleet-id>", "Repair one fleet instead of every monitor").option(
2491
+ "--dry-run",
2492
+ "Record the bounded repair plan without provider changes"
2493
+ ).option("--yes", "Confirm the asynchronous provider repair").option(
2494
+ "--idempotency-key <key>",
2495
+ "Stable retry key (generated when omitted)"
2496
+ ).addHelpText(
2497
+ "after",
2498
+ `
2499
+ Notes:
2500
+ This is the short spelling of 'monitors batch repair --target needs-repair'.
2501
+ It handles both direct monitors and Fleet members through one durable
2502
+ service-account worker. An active historical monitor without an upstream id
2503
+ is selected for repair; current Convex writes cannot create that state.
2504
+
2505
+ It returns a run id immediately. Inspect retained results with
2506
+ 'deepline monitors batch get <run-id> --json'. Reuse --idempotency-key after
2507
+ a lost response to rejoin the exact run without another provider request.
2508
+
2509
+ Examples:
2510
+ deepline monitors repair --dry-run
2511
+ deepline monitors repair --yes
2512
+ deepline monitors repair --fleet accounts-eu --yes --idempotency-key repair-eu-2026-09-09
2513
+ `
2514
+ )
2515
+ ).action(monitorsAction(handleMonitorsRepair));
2516
+ withJsonOption(
2517
+ monitors.command("health").description("Delivery and convergence health for your monitors.").option(
2518
+ "--fleet <fleet-id>",
2519
+ "Report on one fleet instead of every monitor"
2520
+ ).addHelpText(
2521
+ "after",
2522
+ `
2523
+ Notes:
2524
+ Read-only. Reports how many monitors the provider holds as asked, how many
2525
+ disagree, how many Deepline deactivated and why, and how many are "silent" \u2014
2526
+ the provider holds them but nothing has been delivered recently. The worst
2527
+ offenders are listed longest-quiet first.
2528
+
2529
+ Examples:
2530
+ deepline monitors health
2531
+ deepline monitors health --fleet accounts-eu --json
2532
+ `
2533
+ )
2534
+ ).action(monitorsAction(handleMonitorsHealth));
2535
+ const batch = monitors.command("batch").description("Submit or inspect durable bulk monitor operations.");
2536
+ const batchSelectorOptions = (command) => command.option(
2537
+ "--target <target>",
2538
+ "One of: all, all-active, billing-suspended, needs-repair"
2539
+ ).option("--fleet <fleet-id>", "Select one Fleet").option("--keys <keys>", "Up to 100 comma-separated monitor keys").option(
2540
+ "--dry-run",
2541
+ "Record the same bounded plan without provider changes"
2542
+ ).option(
2543
+ "--idempotency-key <key>",
2544
+ "Stable retry key (generated when omitted)"
2545
+ );
2546
+ withJsonOption(
2547
+ batch.command("deploy").description(
2548
+ "Create a Monitor Job from canonical Batch JSON; legacy NDJSON remains available with --yes or --dry-run."
2549
+ ).requiredOption(
2550
+ "--file <path>",
2551
+ 'Batch JSON ({"version":1,"kind":"batch","monitors":[...]}), or legacy NDJSON with --yes/--dry-run'
2552
+ ).option("--dry-run", "Preview a retained legacy NDJSON batch operation").option("--yes", "Confirm a retained legacy NDJSON batch operation").option(
2553
+ "--idempotency-key <key>",
2554
+ "Stable retry key (generated when omitted)"
2555
+ )
2556
+ ).action(
2557
+ monitorsAction(async (options) => {
2558
+ if (options.dryRun === true || options.yes === true) {
2559
+ return await handleMonitorBatchDeploy(options);
2560
+ }
2561
+ const idempotencyKey = monitorJobIdempotencyKey(
2562
+ "batch-deploy",
2563
+ options.idempotencyKey
2564
+ );
2565
+ return await handleMonitorJobBatchDeploy(options, idempotencyKey);
2566
+ })
2567
+ );
2568
+ withJsonOption(
2569
+ batch.command("lint").description(
2570
+ "Validate and normalize Batch JSON without network or provider work."
2571
+ ).requiredOption("--file <path>", "Batch JSON file, or - for stdin")
2572
+ ).action(monitorsAction(handleMonitorBatchLint));
2573
+ withJsonOption(
2574
+ batchSelectorOptions(
2575
+ batch.command("audit").description("Durably audit a selection; defaults to --target all.")
2576
+ )
2577
+ ).action(
2578
+ monitorsAction(
2579
+ (options) => handleMonitorBatch("audit", options)
2580
+ )
2581
+ );
2582
+ withJsonOption(
2583
+ batchSelectorOptions(
2584
+ batch.command("repair").description(
2585
+ "Durably re-audit and converge a selection through the existing lifecycle fences."
2586
+ )
2587
+ ).option("--yes", "Confirm the asynchronous provider repair")
2588
+ ).action(
2589
+ monitorsAction(
2590
+ (options) => handleMonitorBatch("repair", options)
2591
+ )
2592
+ );
2593
+ withJsonOption(
2594
+ batchSelectorOptions(
2595
+ batch.command("deactivate").description(
2596
+ "Durably deactivate a selection through provider batch deletes."
2597
+ )
2598
+ ).option(
2599
+ "--reason <reason>",
2600
+ "Declared policy reason; required with --target and omitted for a customer-requested --keys teardown"
2601
+ ).option("--yes", "Confirm the asynchronous provider deactivation")
2602
+ ).action(
2603
+ monitorsAction(
2604
+ (options) => handleMonitorBatch("deactivate", options)
2605
+ )
2606
+ );
2607
+ withJsonOption(
2608
+ batchSelectorOptions(
2609
+ batch.command("reactivate").description("Durably reactivate a selection after a suspension.")
2610
+ ).option("--yes", "Confirm provider reactivation and possible billing")
2611
+ ).action(
2612
+ monitorsAction(
2613
+ (options) => handleMonitorBatch("reactivate", options)
2614
+ )
2615
+ );
2616
+ withJsonOption(
2617
+ batch.command("get <operation-id>").description("Read batch progress and one bounded evidence page.").option("--cursor <cursor>", "Read the next retained evidence page")
2618
+ ).action(monitorsAction(handleMonitorBatchGet));
2619
+ const namedBatches = monitors.command("batches").description(
2620
+ "Manage stable named Batches whose omitted members are stopped."
2621
+ );
2622
+ withJsonOption(namedBatches);
2623
+ withJsonOption(
2624
+ namedBatches.command("sync <batch-id>").description(
2625
+ "Publish the complete desired member set and return one Monitor Job."
2626
+ ).requiredOption(
2627
+ "--file <path>",
2628
+ "Canonical Batch JSON file, or - for stdin"
2629
+ ).option(
2630
+ "--dry-run",
2631
+ "Validate and show the desired count without publishing"
2632
+ ).option("--expected-generation <n>", "Reject a stale concurrent update").option("--idempotency-key <key>", "Stable retry key")
2633
+ ).action(monitorsAction(handleNamedMonitorBatchSync));
2634
+ withJsonOption(
2635
+ namedBatches.command("start <batch-id>").description("Reapply the retained member set through one Monitor Job.").option(
2636
+ "--dry-run",
2637
+ "Show the retained-intent operation without publishing"
2638
+ ).option("--idempotency-key <key>", "Stable retry key")
2639
+ ).action(
2640
+ monitorsAction(
2641
+ (batchId, options) => handleNamedMonitorBatchLifecycle(batchId, "start", options)
2642
+ )
2643
+ );
2644
+ withJsonOption(
2645
+ namedBatches.command("stop <batch-id>").description(
2646
+ "Publish an empty desired set while retaining members for start."
2647
+ ).option(
2648
+ "--dry-run",
2649
+ "Show the retained-intent operation without publishing"
2650
+ ).option("--idempotency-key <key>", "Stable retry key")
2651
+ ).action(
2652
+ monitorsAction(
2653
+ (batchId, options) => handleNamedMonitorBatchLifecycle(batchId, "stop", options)
2654
+ )
2655
+ );
2656
+ withJsonOption(
2657
+ namedBatches.command("get <batch-id>").description("Read named Batch intent and its latest Monitor Job.")
2658
+ ).action(monitorsAction(handleNamedMonitorBatchGet));
2659
+ withJsonOption(
2660
+ monitors.command("status").description("Check whether you have access to Deepline monitors.").addHelpText(
2661
+ "after",
2662
+ `
2663
+ Notes:
2664
+ Read-only access check. Requires authentication but NOT monitor access, so it
2665
+ is safe to run first to confirm whether you can use the monitor commands. Exits
2666
+ 0 when you have access and 1 when you do not, so agents can branch on it (this
2667
+ exit-1 denial contract predates the typed monitor exit codes and is kept).
2668
+
2669
+ Examples:
2670
+ deepline monitors status
2671
+ deepline monitors status --json
2672
+ `
2673
+ )
2674
+ ).action(monitorsAction(handleMonitorsStatus));
2675
+ withJsonOption(
2676
+ monitors.command("available [tool-id]", { hidden: true }).alias("tools").description(
2677
+ "List the monitor types you can deploy, or describe one by tool id."
2678
+ ).addHelpText(
2679
+ "after",
2680
+ `
2681
+ Notes:
2682
+ Read-only catalog of deployable monitor types. Pass a tool id positionally to
2683
+ describe one (payload schema + output streams). Filter the list with
2684
+ --provider, --search, or --limit. List entries include how many monitors you
2685
+ already have deployed on each tool ("deployed: N") when the server reports it.
2686
+ The list is compact by default (id + name + deployed count); pass --full to
2687
+ get the complete catalog (payload schemas + output streams for every tool).
2688
+ Describing a single tool by id always returns the full contract.
2689
+
2690
+ Examples:
2691
+ deepline monitors available
2692
+ deepline monitors available --full --json
2693
+ deepline monitors available --provider deepline_native --json
2694
+ deepline monitors available deepline_native.company_radar --json
2695
+ deepline monitors available --search jobs --json
2696
+ `
2697
+ ).option("--provider <provider>", "Filter by provider").option(
2698
+ "--tool <tool>",
2699
+ "Describe a single monitor tool by id (same as the positional tool-id)"
2700
+ ).option("--search <query>", "Search monitor tools by text").option("--limit <n>", "Limit the number of monitor tools returned").option(
2701
+ "--full",
2702
+ "Return the complete monitor catalog (payload schemas + output streams). The list is compact by default."
2703
+ ).option("--compact", COMPACT_OPTION_DESCRIPTION)
2704
+ ).action(monitorsAction(handleMonitorsAvailable));
2705
+ withJsonOption(
2706
+ monitors.command("list").description("List the monitors you have deployed.").addHelpText(
2707
+ "after",
2708
+ `
2709
+ Notes:
2710
+ Read-only. A monitor has one of three customer states: active,
2711
+ billing_suspended, or disabled. Provisioning, cleanup, retries, and failures
2712
+ are reported by Monitor Jobs; provider disagreement is reported separately by
2713
+ audit/health. The output echoes the canonical state filter that was applied.
2714
+ The legacy --status flag remains accepted for installed clients. The response reports
2715
+ total (the true registry count, not the page size), returned, has_more, and
2716
+ next_cursor. When has_more is true, page with --cursor <next_cursor> until it
2717
+ is false \u2014 a "no matching
2718
+ monitor" reuse conclusion off a truncated page deploys a duplicate paid feed.
2719
+ The default list stays cheap: it includes the current downstream Play binding
2720
+ metadata but does not resolve per-monitor delivery/run health. Pass
2721
+ --include-consumers with --limit 20 or fewer to include the current
2722
+ SQL-listener delivery/run health for each returned monitor.
2723
+
2724
+ Examples:
2725
+ deepline monitors list
2726
+ deepline monitors list --state billing_suspended --json
2727
+ deepline monitors list --state all --json
2728
+ deepline monitors list --status all --json
2729
+ deepline monitors list --status all --cursor <next_cursor> --json
2730
+ deepline monitors list --include-consumers --limit 20 --json
2731
+ `
2732
+ ).option(
2733
+ "--state <state>",
2734
+ "Filter by customer state: active (default), billing_suspended, disabled, or all"
2735
+ ).option(
2736
+ "--status <status>",
2737
+ "Deprecated compatibility filter; use --state (active, billing_suspended, disabled, or all)"
2738
+ ).option("--limit <n>", "Limit the number of deployed monitors returned").option(
2739
+ "--cursor <cursor>",
2740
+ "Page past a truncated result using the next_cursor from a prior list response"
2741
+ ).option(
2742
+ "--compact",
2743
+ "Deprecated no-op; complete records are always returned"
2744
+ ).option(
2745
+ "--include-consumers",
2746
+ "Include current SQL-listener consumer health (requires --limit 20 or fewer)"
2747
+ )
2748
+ ).action(monitorsAction(handleMonitorsList));
2749
+ withJsonOption(
2750
+ monitors.command("get <key>").description("Show a single deployed monitor by its public key.").addHelpText(
2751
+ "after",
2752
+ `
2753
+ Notes:
2754
+ Read-only. Returns the exact editable definition, selected Deepline pricing,
2755
+ billing state, output streams, dependent published plays, and monitor_spec.
2756
+ When monitor_spec.available is true, its fields describe the deployed type's
2757
+ editable fields, constraints, and provider-specific behavior. For TAMRadar,
2758
+ this includes the effective updates_since precision and engagement timing
2759
+ rules. Otherwise use the stored definition and check before proposing an
2760
+ update so scope and downstream effects are visible.
2761
+
2762
+ Examples:
2763
+ deepline monitors get my-monitor --json
2764
+ `
2765
+ )
2766
+ ).action(monitorsAction(handleMonitorsGet));
2767
+ withJsonOption(
2768
+ monitors.command("test <key> <payload>").description(
2769
+ "Validate an explicit payload against a monitor\u2019s webhook contract."
2770
+ ).addHelpText(
2771
+ "after",
2772
+ `
2773
+ Notes:
2774
+ <payload> must be an explicit JSON object. The command uses the deployed
2775
+ monitor\u2019s real binding and payload validation, but is a side-effect-free
2776
+ diagnostic: it does not persist rows, spend credits, dispatch Plays, or alter
2777
+ monitor state. It does not synthesize a provider event or accept an omitted
2778
+ payload.
2779
+
2780
+ Examples:
2781
+ deepline monitors test rb2b-website-visitors '{"LinkedIn URL":"https://www.linkedin.com/in/example","Website":"https://example.com"}' --json
2782
+ `
2783
+ )
2784
+ ).action(monitorsAction(handleMonitorsTest));
2785
+ withJsonOption(
2786
+ monitors.command("validate <key>").description("Validate a deployed monitor\u2019s provider configuration.")
2787
+ ).action(monitorsAction(handleMonitorsValidate));
2788
+ withJsonOption(
2789
+ monitors.command("check [definition]").description("Validate a monitor definition without deploying it.").addHelpText(
2790
+ "after",
2791
+ `
2792
+ Notes:
2793
+ Read-only validation. <definition> is a JSON object with key, tool, optional
2794
+ name, and payload. Pass it positionally, via --file <path>, or
2795
+ from stdin with --file -. Does not deploy or spend credits.
2796
+ Check validates the local definition only. It does not contact an existing
2797
+ upstream resource, prove that future events will arrive, or verify downstream
2798
+ Play delivery. The JSON response reports this validation scope explicitly.
2799
+ Provider-specific grammar, precedence, enum applicability, examples, and
2800
+ update semantics are returned by the live monitor contract. Inspect it with
2801
+ \`deepline tools get deepline_native.company_radar --json\`.
2802
+ Operational controls are Deepline-managed. Bind downstream automation in a
2803
+ Play with sqlListeners; monitor definitions never name Plays.
2804
+
2805
+ Examples:
2806
+ deepline monitors check '{"key":"job-openings","tool":"deepline_native.company_radar","payload":{"domain":"stripe.com","radar_type":"company_job_openings"}}'
2807
+ deepline monitors check --file monitor.json
2808
+ cat monitor.json | deepline monitors check --file -
2809
+ `
2810
+ ).option(
2811
+ "-f, --file <path>",
2812
+ "Read the definition JSON from a file, or - for stdin"
2813
+ )
2814
+ ).action(monitorsAction(handleMonitorsCheck));
2815
+ withJsonOption(
2816
+ monitors.command("deploy [definition]").description("Deploy a monitor from a definition.").addHelpText(
2817
+ "after",
2818
+ `
2819
+ Notes:
2820
+ Mutates workspace state and may spend Deepline credits. <definition> is a JSON
2821
+ object with key, tool, optional name, and payload. Pass it positionally, via
2822
+ --file <path>, or from stdin with --file -.
2823
+ --dry-run validates the definition and shows the plan (deploy cost in Deepline
2824
+ credits when the server reports it, plus any existing monitors that may
2825
+ already cover this scope) WITHOUT deploying. Exits 0 when valid, 7 when not.
2826
+ Deploy is a full desired definition for its key: omitting a previously stored
2827
+ field removes it and can replace the upstream resource. Use \`monitors update\`
2828
+ for a patch-style change.
2829
+ Repeating the exact saved definition resumes an incomplete deploy cleanup:
2830
+ Deepline keeps the replacement, removes only the stored previous binding after
2831
+ provider confirmation, and never creates or charges another monitor. There is
2832
+ no separate repair command or retry queue: rerun the same deploy/update.
2833
+ Scheduled reconciliation can also finish that exact saved cleanup; it never
2834
+ creates another monitor.
2835
+ For TamRadar, deliberately changing payload.updates_since is an explicit
2836
+ historical replay request, including when redeploying a disabled monitor.
2837
+ Deepline preserves that selected boundary; filter-only deploys and ordinary
2838
+ reactivation start from a fresh future-only source boundary instead.
2839
+ Operational controls are Deepline-managed. A monitor writes rows; downstream
2840
+ automation belongs in a Play with sqlListeners.
2841
+
2842
+ Examples:
2843
+ deepline monitors deploy '{"key":"job-openings","tool":"deepline_native.company_radar","payload":{"domain":"stripe.com","radar_type":"company_job_openings"}}'
2844
+ deepline monitors deploy --dry-run --file monitor.json
2845
+ deepline monitors deploy --file monitor.json
2846
+ `
2847
+ ).option(
2848
+ "-f, --file <path>",
2849
+ "Read the definition JSON from a file, or - for stdin"
2850
+ ).option(
2851
+ "--dry-run",
2852
+ "Validate and show the deploy plan (cost, reuse candidates) without deploying"
2853
+ )
2854
+ ).action(monitorsAction(handleMonitorsDeploy));
2855
+ withJsonOption(
2856
+ monitors.command("sync [definition]").description(
2857
+ "Publish one complete desired monitor definition and return a Monitor Job."
2858
+ ).option(
2859
+ "-f, --file <path>",
2860
+ "Read definition JSON from a file, or - for stdin"
2861
+ ).option(
2862
+ "--dry-run",
2863
+ "Validate and show the deploy plan without publishing"
2864
+ ).option("--idempotency-key <key>", "Stable retry key")
2865
+ ).action(monitorsAction(handleMonitorsSync));
2866
+ withJsonOption(
2867
+ monitors.command("update <key> [patch]").description("Update a deployed monitor by its public key.").addHelpText(
2868
+ "after",
2869
+ `
2870
+ Notes:
2871
+ Mutates workspace state. <patch> is a JSON object of fields to update. Pass it
2872
+ positionally, via --file <path>, or from stdin with --file -.
2873
+
2874
+ When <patch> includes payload, its top-level fields are merged with the stored
2875
+ payload before validation. This lets you change one filter without resending
2876
+ domain or radar_type; nested values and arrays replace atomically.
2877
+ For TamRadar, changing payload.updates_since on an initial or active definition
2878
+ is an explicit historical replay request. Deepline passes that requested boundary upstream, but previously
2879
+ delivered canonical findings are deduplicated before dispatch and billing; only
2880
+ previously unseen historical findings are chargeable. Filter-only updates,
2881
+ repair, and reactivation instead use a fresh future-only source boundary.
2882
+
2883
+ Examples:
2884
+ deepline monitors update my-monitor '{"name":"Interested replies"}' --json
2885
+ deepline monitors update job-openings '{"payload":{"job_titles":"CEO OR CFO"}}' --json
2886
+ deepline monitors update my-monitor --file patch.json
2887
+ `
2888
+ ).option(
2889
+ "-f, --file <path>",
2890
+ "Read the patch JSON from a file, or - for stdin"
2891
+ )
2892
+ ).action(monitorsAction(handleMonitorsUpdate));
2893
+ withJsonOption(
2894
+ monitors.command("delete <key>").description("Delete a deployed monitor by its public key.").addHelpText(
2895
+ "after",
2896
+ `
2897
+ Notes:
2898
+ DESTRUCTIVE. Deprovisions the upstream provider resource and removes its
2899
+ Deepline-managed monitor. Retries are safe: a delete that already reached its requested terminal state
2900
+ returns already_deleted without making another upstream call.
2901
+ --dry-run shows the delete plan without deleting anything.
2902
+ Interactive terminals get a y/N confirmation; non-interactive runs (agents,
2903
+ scripts, pipes) must pass --yes.
2904
+
2905
+ Examples:
2906
+ deepline monitors delete my-monitor --dry-run
2907
+ deepline monitors delete my-monitor --yes --json
2908
+ `
2909
+ ).option("--dry-run", "Show the delete plan without deleting anything").option(
2910
+ "--yes",
2911
+ "Skip the confirmation prompt (required non-interactively)"
2912
+ )
2913
+ ).action(monitorsAction(handleMonitorsDelete));
2914
+ withJsonOption(
2915
+ monitors.command("reactivate <key>").description("Reactivate a previously disabled deployed monitor.").addHelpText(
2916
+ "after",
2917
+ `
2918
+ Notes:
2919
+ Mutates workspace state and may spend Deepline credits.
2920
+ --dry-run shows the reactivation cost (in Deepline credits) without changing
2921
+ anything.
2922
+ Deepline Native radars create a replacement upstream radar from the saved
2923
+ filters. Reactivation always omits updates_since and starts at provider
2924
+ creation; a disabled monitor cannot stage an updates_since change. New Hire
2925
+ and Promotion source dates use calendar-month precision upstream, so
2926
+ current-month updates_since values are rejected for those radar types.
2927
+
2928
+ Examples:
2929
+ deepline monitors reactivate my-monitor --dry-run
2930
+ deepline monitors reactivate my-monitor --json
2931
+ `
2932
+ ).option("--dry-run", "Show the reactivation cost without reactivating")
2933
+ ).action(monitorsAction(handleMonitorsReactivate));
2934
+ withJsonOption(
2935
+ monitors.command("start <key>").description("Apply the retained definition for a stopped monitor.").option("--dry-run", "Show the start plan without changing anything").option("--idempotency-key <key>", "Stable retry key")
2936
+ ).action(
2937
+ monitorsAction(
2938
+ (key, options) => handleScalarMonitorLifecycle("start", key, options)
2939
+ )
2940
+ );
2941
+ withJsonOption(
2942
+ monitors.command("stop <key>").description(
2943
+ "Stop a monitor upstream while retaining its definition for `start`."
2944
+ ).option("--dry-run", "Show the stop plan without changing anything").option("--idempotency-key <key>", "Stable retry key")
2945
+ ).action(
2946
+ monitorsAction(
2947
+ (key, options) => handleScalarMonitorLifecycle("stop", key, options)
2948
+ )
2949
+ );
2950
+ const jobs = monitors.command("jobs").description("Read, wait for, inspect, or cancel Monitor Jobs.");
2951
+ withJsonOption(jobs);
2952
+ withJsonOption(
2953
+ jobs.command("get <job-id>").description("Read the durable Monitor Job state.")
2954
+ ).action(monitorsAction(handleMonitorJobGet));
2955
+ withJsonOption(
2956
+ jobs.command("wait <job-id>").description(
2957
+ "Wait for real provider reconciliation, not request acceptance."
2958
+ ).option("--timeout <duration>", "How long to wait (default 10m)")
2959
+ ).action(monitorsAction(handleMonitorJobWait));
2960
+ withJsonOption(
2961
+ jobs.command("logs <job-id>").description("Read bounded operator logs for one Monitor Job.").option("--limit <n>", "Maximum log entries (1..200)")
2962
+ ).action(monitorsAction(handleMonitorJobLogs));
2963
+ withJsonOption(
2964
+ jobs.command("cancel <job-id>").description("Stop unscheduled work and reconcile the partial result.")
2965
+ ).action(monitorsAction(handleMonitorJobCancel));
2966
+ const fleets = monitors.command("fleets").description("Manage table-backed Fleets.").addHelpText(
2967
+ "after",
2968
+ `
2969
+ Notes:
2970
+ A Monitor Fleet maps eligible rows in one Customer DB table to ordinary
2971
+ monitors. Fleet definitions are canonical JSON, and \`deploy\` applies one;
2972
+ \`sync\` remains its exact compatibility alias. Applying the same definition
2973
+ twice is the same operation,
2974
+ so the server answers \`replayed: true\` instead of building a second fleet.
2975
+ The fleet's status is computed by Deepline; this CLI reports it and never
2976
+ recomputes a verdict from the counts.
2977
+
2978
+ Exit codes:
2979
+ 0 converged or done; 2 usage or local validation; 3 auth; 4 not found;
2980
+ 5 server failure (retry the same command); 6 not at the desired state
2981
+ (degraded, or --wait/--check stopped while healthy); 7 refused (change the
2982
+ request).
2983
+
2984
+ Lifecycle:
2985
+ ${MONITOR_FLEET_LIFECYCLE.map(
2986
+ (entry) => ` ${entry.step}. ${entry.command}`
2987
+ ).join("\n")}
2988
+ ${MONITOR_FLEET_HELP_EPILOG}`
2989
+ ).action(
2990
+ monitorsAction(async (options) => {
2991
+ handleMonitorFleetsOverview(options);
2992
+ })
2993
+ );
2994
+ withJsonOption(fleets);
2995
+ withJsonOption(
2996
+ fleets.command("deploy [fleet-id]").description(
2997
+ "Apply a table-backed Fleet definition; sync remains an exact alias."
2998
+ ).option("-f, --file <path>", "Fleet JSON file, or - for stdin").option("--dry-run", "Show the table-backed convergence plan").option("--wait", "Wait for the current Fleet generation to converge").option("--timeout <duration>", "How long --wait may poll (default 10m)").option(
2999
+ "--expected-generation <generation>",
3000
+ "Optimistic generation fence"
3001
+ ).option("--idempotency-key <key>", "Stable retry key")
3002
+ ).action(
3003
+ monitorsAction(
3004
+ async (fleetId, options) => {
3005
+ const idempotencyKey = fleetIdempotencyKey(
3006
+ "deploy",
3007
+ options.idempotencyKey
3008
+ );
3009
+ await handleMonitorFleetsSync(fleetId, options, idempotencyKey);
3010
+ }
3011
+ )
3012
+ );
3013
+ withJsonOption(
3014
+ fleets.command("lint").description(
3015
+ "Validate and normalize Fleet JSON without network or provider work."
3016
+ ).requiredOption("--file <path>", "Fleet JSON file, or - for stdin")
3017
+ ).action(monitorsAction(handleMonitorFleetLint));
3018
+ withJsonOption(
3019
+ fleets.command("init <fleet-id>").description("Write an opinionated Fleet definition JSON file.").addHelpText(
3020
+ "after",
3021
+ `
3022
+ Creates a ready-to-review JSON definition. Fleets always sync ${_chunkJ5NA2TTXjs.MONITOR_FLEET_DOCUMENTATION.fixedPolicy.cadence} and retain
3023
+ a missing member for ${_chunkJ5NA2TTXjs.MONITOR_FLEET_DOCUMENTATION.fixedPolicy.removalGrace} before it is ${_chunkJ5NA2TTXjs.MONITOR_FLEET_DOCUMENTATION.fixedPolicy.onRemoved}d; those
3024
+ policies are not authored in the file. ${_chunkJ5NA2TTXjs.MONITOR_FLEET_DOCUMENTATION.stickyMembership} The payload remains the actual monitor payload for the chosen tool, so use
3025
+ \`deepline tools list --categories monitors\` to discover a tool first.
3026
+
3027
+ Example:
3028
+ deepline monitors fleets init account-job-openings \\
3029
+ --source public.accounts --key account_id --key-type uuid \\
3030
+ --tool deepline_native.company_radar \\
3031
+ --payload '{"domain":"{{domain}}","radar_type":"company_job_openings"}' \\
3032
+ --order-by intent_score:desc \\
3033
+ --out fleet.json
3034
+ `
3035
+ ).requiredOption("--source <schema.table>", "Customer DB source table").requiredOption("--key <column>", "Unique source-row key column").option("--key-type <type>", "text, uuid, int4, or int8 (default text)").requiredOption("--tool <tool>", "Monitor tool to create per source row").requiredOption(
3036
+ "--payload <json>",
3037
+ "Monitor payload JSON for --tool; use Handlebars fields such as {{domain}} for row values"
3038
+ ).option(
3039
+ "--where <json>",
3040
+ "Optional source-row equality filter JSON; not arbitrary SQL"
3041
+ ).option(
3042
+ "--order-by <column:direction>",
3043
+ "Rank candidates; repeatable, with the source key appended for stability",
3044
+ (value, previous = []) => [...previous, value],
3045
+ []
3046
+ ).option(
3047
+ "--limit <n>",
3048
+ "Maximum active members; ranking changes do not churn sticky members (default 1,000)"
3049
+ ).requiredOption("--out <path>", "Write the definition JSON to this path")
3050
+ ).action(monitorsAction(handleMonitorFleetsInit));
3051
+ withJsonOption(
3052
+ fleets.command("sync [fleet-id]").description(
3053
+ "Apply a Fleet definition, or re-plan an existing fleet from its stored one."
3054
+ ).addHelpText(
3055
+ "after",
3056
+ `
3057
+ Notes:
3058
+ --file (or an inline definition, or --file - for stdin) is compiled locally
3059
+ BEFORE any network call: a definition that fails the contract exits 2 and
3060
+ never becomes a request. A bare <fleet-id> re-plans the stored definition.
3061
+ The plan always shows blocked members; they are never hidden.
3062
+ --wait polls until Deepline reports a terminal status: converged exits 0,
3063
+ degraded exits 6, and a timeout exits 6 without implying anything broke.
3064
+ Progress goes to stderr, so stdout stays exactly one JSON object.
3065
+
3066
+ Examples:
3067
+ deepline monitors fleets sync --file fleet.json --dry-run
3068
+ deepline monitors fleets sync --file fleet.json --wait --timeout 20m
3069
+ deepline monitors fleets sync account-job-openings --wait --json
3070
+ cat fleet.json | deepline monitors fleets sync --file - --dry-run --json
3071
+ `
3072
+ ).option(
3073
+ "-f, --file <path>",
3074
+ "Apply definition JSON from a file, or - for stdin"
3075
+ ).option(
3076
+ "--dry-run",
3077
+ "Show the plan and the credits due without changing state"
3078
+ ).option("--wait", "Poll until the fleet reaches a terminal status").option(
3079
+ "--timeout <duration>",
3080
+ "How long --wait may poll: 500ms, 90s, 10m, 1h (default 10m)"
3081
+ ).option(
3082
+ "--expected-generation <generation>",
3083
+ "Refuse the write unless the fleet is at this generation"
3084
+ ).option(
3085
+ "--idempotency-key <key>",
3086
+ "Stable retry key (generated and returned when omitted)"
3087
+ )
3088
+ ).action(async (target, options) => {
3089
+ let retryCommand = fleetSyncCommandLine(target, options);
3090
+ try {
3091
+ const idempotencyKey = fleetIdempotencyKey(
3092
+ "sync",
3093
+ options.idempotencyKey
3094
+ );
3095
+ retryCommand = fleetSyncCommandLine(target, {
3096
+ ...options,
3097
+ idempotencyKey
3098
+ });
3099
+ await handleMonitorFleetsSync(target, options, idempotencyKey);
3100
+ } catch (error) {
3101
+ reportMonitorsFailure(error, { retryCommand });
3102
+ }
3103
+ });
3104
+ withJsonOption(
3105
+ fleets.command("get [fleet-id]").description(
3106
+ "Read one fleet, or list every fleet when the id is omitted."
3107
+ ).addHelpText(
3108
+ "after",
3109
+ `
3110
+ Notes:
3111
+ Status is the server's verdict. --check turns it into an exit code so a
3112
+ script can branch without parsing output: 0 converged, 6 anything else.
3113
+ --drift lists the members that have not settled and why. The detail also
3114
+ shows the current Plays that observe this Fleet's output; those bindings are
3115
+ read-only here and are defined by each Play's sqlListeners.
3116
+
3117
+ Examples:
3118
+ deepline monitors fleets get --json
3119
+ deepline monitors fleets get account-job-openings --json
3120
+ deepline monitors fleets get account-job-openings --drift --limit 50 --json
3121
+ deepline monitors fleets get account-job-openings --check
3122
+ `
3123
+ ).option("--drift", "Include the members that have not settled, and why").option("--limit <n>", "Maximum drift rows to return").option(
3124
+ "--check",
3125
+ "Exit 0 when converged and 6 otherwise, for scripts and agents"
3126
+ )
3127
+ ).action(monitorsAction(handleMonitorFleetsGet));
3128
+ withJsonOption(
3129
+ fleets.command("deactivate <fleet-id>").alias("stop").description("Deactivate a fleet and the monitors it owns.").addHelpText(
3130
+ "after",
3131
+ `
3132
+ Notes:
3133
+ Destructive. --dry-run shows the blast radius without changing anything.
3134
+ An interactive terminal is shown that blast radius and asked to confirm;
3135
+ a non-interactive run must pass --yes. Re-running after a failure is safe.
3136
+
3137
+ Examples:
3138
+ deepline monitors fleets deactivate account-job-openings --dry-run
3139
+ deepline monitors fleets deactivate account-job-openings --yes --wait --json
3140
+ `
3141
+ ).option("--dry-run", "Show the blast radius without deactivating").option("--wait", "Poll until the fleet reports deactivated").option(
3142
+ "--timeout <duration>",
3143
+ "How long --wait may poll: 500ms, 90s, 10m, 1h (default 10m)"
3144
+ ).option(
3145
+ "--yes",
3146
+ "Skip the confirmation prompt (required non-interactively)"
3147
+ ).option(
3148
+ "--idempotency-key <key>",
3149
+ "Stable retry key (generated and returned when omitted)"
3150
+ )
3151
+ ).action(async (fleetId, options) => {
3152
+ let retryCommand = fleetDeactivateCommandLine(fleetId, options);
3153
+ try {
3154
+ const idempotencyKey = fleetIdempotencyKey(
3155
+ "deactivate",
3156
+ options.idempotencyKey
3157
+ );
3158
+ retryCommand = fleetDeactivateCommandLine(fleetId, {
3159
+ ...options,
3160
+ idempotencyKey
3161
+ });
3162
+ await handleMonitorFleetsDeactivate(fleetId, options, idempotencyKey);
3163
+ } catch (error) {
3164
+ reportMonitorsFailure(error, { retryCommand });
3165
+ }
3166
+ });
3167
+ withJsonOption(
3168
+ fleets.command("reactivate <fleet-id>").alias("start").description(
3169
+ "Explicitly recreate a fleet after a credit-triggered suspension."
3170
+ ).addHelpText(
3171
+ "after",
3172
+ `
3173
+ Notes:
3174
+ TAMRadar cannot reactivate a deleted radar. This command starts normal,
3175
+ fenced provider creates from the fleet's retained desired definitions and
3176
+ may restart lifecycle billing. A credit top-up alone never does this.
3177
+
3178
+ Example:
3179
+ deepline monitors fleets reactivate account-job-openings --yes --wait --json
3180
+ `
3181
+ ).option("--wait", "Poll until the fleet reports converged").option(
3182
+ "--timeout <duration>",
3183
+ "How long --wait may poll: 500ms, 90s, 10m, 1h (default 10m)"
3184
+ ).option("--yes", "Confirm recreating suspended provider monitors").option("--idempotency-key <key>", "Stable retry key")
3185
+ ).action(async (fleetId, options) => {
3186
+ let retryCommand = fleetReactivateCommandLine(fleetId, options);
3187
+ try {
3188
+ const idempotencyKey = fleetIdempotencyKey(
3189
+ "reactivate",
3190
+ options.idempotencyKey
3191
+ );
3192
+ retryCommand = fleetReactivateCommandLine(fleetId, {
3193
+ ...options,
3194
+ idempotencyKey
3195
+ });
3196
+ await handleMonitorFleetsReactivate(fleetId, options, idempotencyKey);
3197
+ } catch (error) {
3198
+ reportMonitorsFailure(error, { retryCommand });
3199
+ }
3200
+ });
3201
+ const deployed = withJsonOption(
3202
+ monitors.command("deployed", { hidden: true }).description("Alias of `monitors list` (plus get/update/delete aliases).").option(
3203
+ "--state <state>",
3204
+ "Filter by customer state: active (default), billing_suspended, disabled, or all"
3205
+ ).option(
3206
+ "--status <status>",
3207
+ "Deprecated compatibility filter; use --state (active, billing_suspended, disabled, or all)"
3208
+ ).option("--limit <n>", "Limit the number of deployed monitors returned").option(
3209
+ "--cursor <cursor>",
3210
+ "Page past a truncated result using the next_cursor from a prior list response"
3211
+ ).option(
3212
+ "--compact",
3213
+ "Deprecated no-op; complete records are always returned"
3214
+ ).option(
3215
+ "--include-consumers",
3216
+ "Include current SQL-listener consumer health (requires --limit 20 or fewer)"
3217
+ )
3218
+ ).action(monitorsAction(handleMonitorsList));
3219
+ withJsonOption(
3220
+ deployed.command("get <key>").description("Alias of `monitors get <key>`.")
3221
+ ).action(monitorsAction(handleMonitorsGet));
3222
+ withJsonOption(
3223
+ deployed.command("update <key> [patch]").description("Alias of `monitors update <key>`.").option(
3224
+ "-f, --file <path>",
3225
+ "Read the patch JSON from a file, or - for stdin"
3226
+ )
3227
+ ).action(monitorsAction(handleMonitorsUpdate));
3228
+ withJsonOption(
3229
+ deployed.command("delete <key>").description("Alias of `monitors delete <key>`.").option("--dry-run", "Show the delete plan without deleting anything").option(
3230
+ "--yes",
3231
+ "Skip the confirmation prompt (required non-interactively)"
3232
+ )
3233
+ ).action(monitorsAction(handleMonitorsDelete));
3234
+ }
3235
+
3236
+
3237
+
3238
+
3239
+
3240
+
3241
+
3242
+
3243
+
3244
+
3245
+
3246
+
3247
+
3248
+
3249
+
3250
+
3251
+ exports.MonitorDryRunUnsupportedError = MonitorDryRunUnsupportedError; exports.MonitorFleetStateError = MonitorFleetStateError; exports.MonitorsUsageError = MonitorsUsageError; exports.assertMonitorDryRunAcknowledged = assertMonitorDryRunAcknowledged; exports.monitorDeleteRequiresYesError = monitorDeleteRequiresYesError; exports.monitorsErrorExitCode = monitorsErrorExitCode; exports.registerMonitorsCommands = registerMonitorsCommands; exports.renderAvailableToolsText = renderAvailableToolsText; exports.renderDeployedListText = renderDeployedListText; exports.renderMonitorDeletePlan = renderMonitorDeletePlan; exports.renderMonitorDeployCompletion = renderMonitorDeployCompletion; exports.renderMonitorDeployPlan = renderMonitorDeployPlan; exports.renderMonitorGet = renderMonitorGet; exports.renderMonitorReactivatePlan = renderMonitorReactivatePlan; exports.resolveMonitorJsonBody = resolveMonitorJsonBody;