deepline 0.3.74 → 0.3.76

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 (34) hide show
  1. package/dist/bundling-sources/sdk/src/client.ts +279 -21
  2. package/dist/bundling-sources/sdk/src/config.ts +21 -3
  3. package/dist/bundling-sources/sdk/src/index.ts +1 -0
  4. package/dist/bundling-sources/sdk/src/play.ts +3 -6
  5. package/dist/bundling-sources/sdk/src/release.ts +1 -1
  6. package/dist/bundling-sources/sdk/src/types.ts +3 -2
  7. package/dist/bundling-sources/shared_libs/monitors/deactivation-reasons.ts +186 -0
  8. package/dist/bundling-sources/shared_libs/monitors/monitor-fleet-limits.ts +41 -0
  9. package/dist/bundling-sources/shared_libs/play-runtime/async-operation.ts +213 -55
  10. package/dist/bundling-sources/shared_libs/play-runtime/context.ts +172 -299
  11. package/dist/bundling-sources/shared_libs/play-runtime/ctx-types.ts +10 -0
  12. package/dist/bundling-sources/shared_libs/play-runtime/durable-call-cache.ts +13 -32
  13. package/dist/bundling-sources/shared_libs/play-runtime/governor/governor.ts +5 -1
  14. package/dist/bundling-sources/shared_libs/play-runtime/resource-governor.ts +7 -2
  15. package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-lifecycle.ts +11 -2
  16. package/dist/bundling-sources/shared_libs/play-runtime/runtime-incident-drills.ts +1 -1
  17. package/dist/bundling-sources/shared_libs/play-runtime/suspension.ts +16 -0
  18. package/dist/bundling-sources/shared_libs/play-runtime/tool-call/native-batch.ts +1 -0
  19. package/dist/bundling-sources/shared_libs/play-runtime/tool-call/testkit.ts +5 -4
  20. package/dist/bundling-sources/shared_libs/play-runtime/tool-execute-retry-policy.ts +12 -2
  21. package/dist/bundling-sources/shared_libs/plays/authoring-contract.ts +1 -1
  22. package/dist/bundling-sources/shared_libs/plays/deployment-status.ts +74 -0
  23. package/dist/cli/index.js +940 -181
  24. package/dist/cli/index.mjs +940 -181
  25. package/dist/{compiler-manifest-CMNgA_JQ.d.mts → compiler-manifest-Dbov16F7.d.mts} +1 -1
  26. package/dist/{compiler-manifest-CMNgA_JQ.d.ts → compiler-manifest-Dbov16F7.d.ts} +1 -1
  27. package/dist/index.d.mts +176 -23
  28. package/dist/index.d.ts +176 -23
  29. package/dist/index.js +109 -12
  30. package/dist/index.mjs +109 -12
  31. package/dist/install-integrity.json +4 -2
  32. package/dist/plays/bundle-play-file.d.mts +2 -2
  33. package/dist/plays/bundle-play-file.d.ts +2 -2
  34. package/package.json +1 -1
package/dist/cli/index.js CHANGED
@@ -905,6 +905,17 @@ function getResolvedProjectAuthSource(baseUrl, apiKey, startDir = process.cwd())
905
905
  return projectBaseUrl === normalizedBaseUrl && (env[API_KEY_ENV] ?? "").trim() === normalizedApiKey;
906
906
  }) ?? null;
907
907
  }
908
+ function resolveBaseUrlOnly(options) {
909
+ const baseUrl = normalizeBaseUrl(
910
+ options?.baseUrl?.trim() || autoDetectBaseUrl()
911
+ );
912
+ if (!baseUrl) {
913
+ throw new ConfigError(
914
+ `Invalid ${HOST_URL_ENV}. Expected an http(s) URL such as https://code.deepline.com.`
915
+ );
916
+ }
917
+ return baseUrl;
918
+ }
908
919
  function resolveConfig(options) {
909
920
  const baseUrl = normalizeBaseUrl(
910
921
  options?.baseUrl?.trim() || autoDetectBaseUrl()
@@ -1214,7 +1225,7 @@ var SDK_RELEASE = {
1214
1225
  // available at toolResponse.rawV2 while toolResponse.raw and all declared
1215
1226
  // getters keep their established compatibility behavior.
1216
1227
  // 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
1217
- version: "0.3.74",
1228
+ version: "0.3.76",
1218
1229
  updateSummary: "Automatic CLI updates are now enabled by default. To opt out, run `deepline settings autoupdate off`; use `deepline settings autoupdate on` to re-enable updates or `deepline settings autoupdate pin <version>` to hold an exact release. This release also adds raw-v2 tool responses at toolResponse.rawV2 while preserving existing toolResponse.raw and declared getters.",
1219
1230
  packageCapabilities: {
1220
1231
  updatePreferences: 1
@@ -1636,7 +1647,7 @@ var RUNTIME_INCIDENT_DRILL_CATALOG = [
1636
1647
  valueMeaning: "occurrence"
1637
1648
  },
1638
1649
  expected: {
1639
- outcome: "The same logical run completes through receipt replay; recovery remains bounded if the provider outcome must be retried.",
1650
+ outcome: "The same logical run completes through terminal-cache replay; any provider retry is governed by its separate operation policy.",
1640
1651
  safetyFacts: ["same_logical_run", "bounded_provider_execution"]
1641
1652
  },
1642
1653
  verification: {
@@ -4491,6 +4502,10 @@ var TERMINAL_PLAY_STATUSES = /* @__PURE__ */ new Set(["completed", "failed", "ca
4491
4502
  var INCLUDE_TOOL_METADATA_HEADER = "x-deepline-include-tool-metadata";
4492
4503
  var EXECUTE_RESPONSE_CONTRACT_HEADER = "x-deepline-execute-response-contract";
4493
4504
  var EXECUTE_RESPONSE_INTENT_HEADER = "x-deepline-execute-response-intent";
4505
+ var MONITOR_NON_RETRYABLE_MUTATION_OPTIONS = {
4506
+ maxRetries: 0,
4507
+ exactUrlOnly: true
4508
+ };
4494
4509
  var RAW_V2_EXECUTE_RESPONSE_CONTRACT = RAW_V2_TOOL_RESPONSE_CONTRACT;
4495
4510
  var COMPILE_MANIFEST_RETRY_DELAYS_MS = [250, 1e3];
4496
4511
  var REGISTER_PLAY_ARTIFACTS_COMPILE_CONCURRENCY = 3;
@@ -5049,11 +5064,15 @@ var DeeplineClient = class {
5049
5064
  update: (key, patch) => this.updateMonitor(key, patch),
5050
5065
  delete: (key, options2) => this.deleteMonitor(key, options2),
5051
5066
  reactivate: (key, options2) => this.reactivateMonitor(key, options2),
5067
+ audit: (options2) => this.auditMonitors(options2),
5068
+ repair: (options2) => this.repairMonitors(options2),
5069
+ health: (options2) => this.readMonitorsHealth(options2),
5052
5070
  fleets: {
5053
5071
  sync: (definitionOrId, options2) => this.syncMonitorFleet(definitionOrId, options2),
5054
5072
  get: (fleetId, options2) => fleetId === void 0 ? this.listMonitorFleets() : this.getMonitorFleet(fleetId, options2),
5055
5073
  list: () => this.listMonitorFleets(),
5056
5074
  deactivate: (fleetId, options2) => this.deactivateMonitorFleet(fleetId, options2),
5075
+ reactivate: (fleetId, options2) => this.reactivateMonitorFleet(fleetId, options2),
5057
5076
  waitForConvergence: (fleetId, options2) => this.waitForMonitorFleetConvergence(fleetId, options2)
5058
5077
  }
5059
5078
  };
@@ -6639,13 +6658,23 @@ var DeeplineClient = class {
6639
6658
  if (options?.grep?.trim()) {
6640
6659
  params.set("grep", options.grep.trim());
6641
6660
  params.set("grep_mode", options.grepMode ?? "all");
6661
+ params.set("grep_paginated", "1");
6642
6662
  params.set("limit", "60");
6643
6663
  }
6644
- const suffix = params.toString() ? `?${params.toString()}` : "";
6645
- const response = await this.http.get(
6646
- `/api/v2/plays${suffix}`
6647
- );
6648
- return response.plays ?? [];
6664
+ const plays = [];
6665
+ let cursor = null;
6666
+ let hasMore = true;
6667
+ do {
6668
+ if (cursor) params.set("cursor", cursor);
6669
+ const suffix = params.toString() ? `?${params.toString()}` : "";
6670
+ const response = await this.http.get(
6671
+ `/api/v2/plays${suffix}`
6672
+ );
6673
+ plays.push(...response.plays ?? []);
6674
+ cursor = response.pagination?.cursor ?? response.cursor ?? null;
6675
+ hasMore = Boolean(response.pagination?.hasMore ?? response.hasMore);
6676
+ } while (Boolean(options?.grep?.trim()) && hasMore && cursor);
6677
+ return plays;
6649
6678
  }
6650
6679
  /** Set whether an org-owned Play sorts before unpinned Plays. */
6651
6680
  async setPlayPinned(playName, pinned) {
@@ -7222,6 +7251,44 @@ var DeeplineClient = class {
7222
7251
  ...typeof payload.reason === "string" && payload.reason.trim() ? { reason: payload.reason.trim() } : {}
7223
7252
  };
7224
7253
  }
7254
+ /**
7255
+ * One bounded audit pass. Prefer `client.monitors.audit(...)`.
7256
+ *
7257
+ * Never auto-retried: it is idempotent, but a retry that races the caller's
7258
+ * own next pass would spend a provider slot to learn nothing new.
7259
+ */
7260
+ async auditMonitors(options) {
7261
+ return this.http.request("/api/v2/monitors/audit", {
7262
+ method: "POST",
7263
+ body: {
7264
+ ...options?.fleetId ? { fleet_id: options.fleetId } : {},
7265
+ ...options?.cursor ? { cursor: options.cursor } : {}
7266
+ },
7267
+ maxRetries: 0
7268
+ });
7269
+ }
7270
+ /** One repair pass or plan. Prefer `client.monitors.repair(...)`. */
7271
+ async repairMonitors(options) {
7272
+ return this.http.request("/api/v2/monitors/repair", {
7273
+ method: "POST",
7274
+ body: {
7275
+ ...options?.fleetId ? { fleet_id: options.fleetId } : {},
7276
+ ...options?.dryRun === void 0 ? {} : { dry_run: options.dryRun }
7277
+ },
7278
+ maxRetries: 0
7279
+ });
7280
+ }
7281
+ /** Delivery and convergence health. Prefer `client.monitors.health(...)`. */
7282
+ async readMonitorsHealth(options) {
7283
+ const params = new URLSearchParams();
7284
+ if (options?.fleetId) params.set("fleet_id", options.fleetId);
7285
+ const query = params.toString();
7286
+ const suffix = query ? `?${query}` : "";
7287
+ return this.http.request(
7288
+ `/api/v2/monitors/health${suffix}`,
7289
+ { method: "GET" }
7290
+ );
7291
+ }
7225
7292
  /**
7226
7293
  * The deployable monitor tools catalog. Pass a tool id (positional or
7227
7294
  * `{ tool }`) to describe one tool's full payload/stream contract, or no tool
@@ -7299,7 +7366,6 @@ var DeeplineClient = class {
7299
7366
  if (options?.limit !== void 0)
7300
7367
  params.set("limit", String(options.limit));
7301
7368
  if (options?.cursor) params.set("cursor", options.cursor);
7302
- if (options?.compact) params.set("compact", "true");
7303
7369
  if (options?.includeConsumers) params.set("include_consumers", "true");
7304
7370
  const query = params.toString();
7305
7371
  const suffix = query ? `?${query}` : "";
@@ -7316,13 +7382,22 @@ var DeeplineClient = class {
7316
7382
  );
7317
7383
  }
7318
7384
  async testMonitorWebhook(key, payload, options) {
7385
+ if (options?.dispatch === true || options?.validationOnly === false) {
7386
+ throw new DeeplineError(
7387
+ "Monitor tests are validation-only and cannot dispatch events.",
7388
+ void 0,
7389
+ "MONITOR_TEST_DISPATCH_NOT_SUPPORTED"
7390
+ );
7391
+ }
7319
7392
  return this.http.request(
7320
7393
  `/api/v2/monitors/deployed/${encodeURIComponent(key)}/test`,
7321
7394
  {
7322
7395
  method: "POST",
7323
7396
  body: {
7324
7397
  payload,
7325
- ...options?.validationOnly ? { mode: "validation_only" } : options?.dispatch ? { mode: "dispatch" } : {}
7398
+ // Send the legacy safe mode as well as accepting it server-side: an
7399
+ // upgraded SDK must be safe when it reaches a still-running server.
7400
+ mode: "validation_only"
7326
7401
  }
7327
7402
  }
7328
7403
  );
@@ -7350,7 +7425,14 @@ var DeeplineClient = class {
7350
7425
  async updateMonitor(key, patch) {
7351
7426
  return this.http.request(
7352
7427
  `/api/v2/monitors/deployed/${encodeURIComponent(key)}`,
7353
- { method: "PATCH", body: patch }
7428
+ {
7429
+ method: "PATCH",
7430
+ body: patch,
7431
+ // A monitor write may have reached the control plane before a network
7432
+ // failure reaches the caller. Do not turn that unknown outcome into a
7433
+ // second mutation with a fresh snapshot.
7434
+ ...MONITOR_NON_RETRYABLE_MUTATION_OPTIONS
7435
+ }
7354
7436
  );
7355
7437
  }
7356
7438
  /** Delete a deployed monitor and its upstream provider resource. `dryRun` returns the delete plan. Prefer `client.monitors.delete(...)`. */
@@ -7367,7 +7449,12 @@ var DeeplineClient = class {
7367
7449
  const query = params.toString();
7368
7450
  return this.http.request(
7369
7451
  `/api/v2/monitors/deployed/${encodeURIComponent(key)}${query ? `?${query}` : ""}`,
7370
- { method: "DELETE" }
7452
+ options?.dryRun ? { method: "DELETE" } : {
7453
+ method: "DELETE",
7454
+ // Deletion is a provider lifecycle operation. A timeout is an
7455
+ // unknown outcome, not authority to begin another delete attempt.
7456
+ ...MONITOR_NON_RETRYABLE_MUTATION_OPTIONS
7457
+ }
7371
7458
  );
7372
7459
  }
7373
7460
  /**
@@ -7378,7 +7465,13 @@ var DeeplineClient = class {
7378
7465
  const query = options?.dryRun ? "?dry_run=true" : "";
7379
7466
  return this.http.request(
7380
7467
  `/api/v2/monitors/deployed/${encodeURIComponent(key)}/reactivate${query}`,
7381
- { method: "POST", body: {} }
7468
+ options?.dryRun ? { method: "POST", body: {} } : {
7469
+ method: "POST",
7470
+ body: {},
7471
+ // Reactivation can create an upstream resource, so it must not use
7472
+ // the generic transport's automatic replay policy.
7473
+ ...MONITOR_NON_RETRYABLE_MUTATION_OPTIONS
7474
+ }
7382
7475
  );
7383
7476
  }
7384
7477
  // ——————————————————————————————————————————————————————————
@@ -7455,6 +7548,21 @@ var DeeplineClient = class {
7455
7548
  }
7456
7549
  );
7457
7550
  }
7551
+ async reactivateMonitorFleet(fleetId, options) {
7552
+ return this.http.request(
7553
+ `${this.monitorFleetPath(fleetId)}/reactivate`,
7554
+ {
7555
+ method: "POST",
7556
+ body: {},
7557
+ headers: this.monitorFleetHeaders(
7558
+ "reactivate",
7559
+ options?.idempotencyKey
7560
+ ),
7561
+ maxRetries: 0,
7562
+ exactUrlOnly: true
7563
+ }
7564
+ );
7565
+ }
7458
7566
  /**
7459
7567
  * Poll one fleet until the server reports a terminal status.
7460
7568
  *
@@ -8349,6 +8457,7 @@ function printCommandEnvelope(envelope, options = {}) {
8349
8457
  var EXIT_OK = 0;
8350
8458
  var EXIT_AUTH = 3;
8351
8459
  var EXIT_SERVER = 5;
8460
+ var AUTH_HTTP_TIMEOUT_MS = 1e4;
8352
8461
  function statusBannerLine(value) {
8353
8462
  if (!value || typeof value !== "object" || Array.isArray(value)) return null;
8354
8463
  const banner = value;
@@ -8515,30 +8624,37 @@ async function httpJson(method, url, apiKey, body) {
8515
8624
  if (apiKey) headers["Authorization"] = `Bearer ${apiKey}`;
8516
8625
  const bypassToken = process.env.VERCEL_PROTECTION_BYPASS_TOKEN?.trim();
8517
8626
  if (bypassToken) headers["x-vercel-protection-bypass"] = bypassToken;
8518
- let response = null;
8519
8627
  let lastError = null;
8520
8628
  for (const candidateUrl of buildCandidateUrls2(url)) {
8629
+ const controller = new AbortController();
8630
+ let requestTimedOut = false;
8631
+ const timeout = setTimeout(() => {
8632
+ requestTimedOut = true;
8633
+ controller.abort();
8634
+ }, AUTH_HTTP_TIMEOUT_MS);
8521
8635
  try {
8522
- response = await fetch(candidateUrl, {
8636
+ const response = await fetch(candidateUrl, {
8523
8637
  method,
8524
8638
  headers,
8525
- body: body !== void 0 ? JSON.stringify(body) : void 0
8639
+ body: body !== void 0 ? JSON.stringify(body) : void 0,
8640
+ signal: controller.signal
8526
8641
  });
8527
- break;
8642
+ let data;
8643
+ try {
8644
+ data = await response.json();
8645
+ } catch (error) {
8646
+ if (controller.signal.aborted) throw error;
8647
+ data = {};
8648
+ }
8649
+ return { status: response.status, data };
8528
8650
  } catch (error) {
8529
8651
  lastError = error;
8652
+ if (requestTimedOut && method !== "GET") break;
8653
+ } finally {
8654
+ clearTimeout(timeout);
8530
8655
  }
8531
8656
  }
8532
- if (!response) {
8533
- throw lastError instanceof Error ? lastError : new Error(String(lastError));
8534
- }
8535
- let data;
8536
- try {
8537
- data = await response.json();
8538
- } catch {
8539
- data = {};
8540
- }
8541
- return { status: response.status, data };
8657
+ throw lastError instanceof Error ? lastError : new Error(String(lastError));
8542
8658
  }
8543
8659
  async function reportSetupCompleted(input2) {
8544
8660
  const apiKey = input2.authScope === "folder" ? resolveProjectApiKeyForBaseUrl(input2.baseUrl) : resolveGlobalApiKeyForBaseUrl(input2.baseUrl);
@@ -9037,6 +9153,12 @@ async function handleStatus(args) {
9037
9153
  ...payload.workspace.name ? [`Workspace: ${payload.workspace.name}`] : [],
9038
9154
  ...payload.workspace.slug ? [`Workspace slug: ${payload.workspace.slug}`] : [],
9039
9155
  ...payload.workspace.id != null ? [`Org ID: ${payload.workspace.id}`] : [],
9156
+ // Switching orgs lives under `deepline org`, but this is where
9157
+ // people look when they discover they are in the wrong
9158
+ // workspace. Without the pointer the reasonable next move is
9159
+ // `deepline auth register`, which re-approves the same account
9160
+ // and leaves the active org unchanged.
9161
+ "Switch workspace: deepline org list, then deepline org set <org-id>",
9040
9162
  ...payload.user.id != null ? [`User ID: ${payload.user.id}`] : [],
9041
9163
  ...payload.examples.length > 0 ? [
9042
9164
  "Examples:",
@@ -9068,8 +9190,16 @@ Notes:
9068
9190
  opening the approval page in Cowork. Use --wait no in CI or agent runs, then
9069
9191
  finish with deepline auth wait.
9070
9192
  Auth status shows the target host and active workspace without printing secrets.
9193
+ Registering again re-approves the same account; it does not change the active
9194
+ workspace. To switch, use deepline org list and deepline org set <org-id>.
9071
9195
  `
9072
9196
  );
9197
+ auth.command("workspaces").description("Deprecated. Use deepline org list to see workspaces.").action(() => {
9198
+ console.error(
9199
+ "Workspaces live under `deepline org`.\n List: deepline org list\n Switch: deepline org set <org-id>\n`deepline auth register` re-approves this device; it does not change the active workspace."
9200
+ );
9201
+ process.exitCode = 1;
9202
+ });
9073
9203
  auth.command("register").description(
9074
9204
  "Register this device and open the approval page in your browser."
9075
9205
  ).addHelpText(
@@ -9314,6 +9444,18 @@ function billingTopUpFailureFromError(error, input2) {
9314
9444
  }
9315
9445
  return null;
9316
9446
  }
9447
+ function normalizeUnixMilliseconds(value) {
9448
+ const timestamp = Math.floor(value);
9449
+ return Number.isFinite(timestamp) && timestamp >= 0 && Number.isFinite(new Date(timestamp).getTime()) ? timestamp : null;
9450
+ }
9451
+ function parseSince(raw) {
9452
+ if (!raw?.trim()) return null;
9453
+ const numeric = Number(raw);
9454
+ const normalizedNumeric = normalizeUnixMilliseconds(numeric);
9455
+ if (normalizedNumeric !== null) return normalizedNumeric;
9456
+ const parsed = Date.parse(raw);
9457
+ return normalizeUnixMilliseconds(parsed);
9458
+ }
9317
9459
  function humanize(value) {
9318
9460
  return String(value || "").split("_").filter(Boolean).map((token) => token[0]?.toUpperCase() + token.slice(1)).join(" ") || "Unknown";
9319
9461
  }
@@ -9599,6 +9741,18 @@ async function handleHistory(options) {
9599
9741
  );
9600
9742
  }
9601
9743
  async function handleLedgerExportAll(options) {
9744
+ const sinceAt = parseSince(options.since);
9745
+ if (options.since && sinceAt === null) {
9746
+ reportBillingFailure(
9747
+ {
9748
+ exitCode: 2,
9749
+ code: "INVALID_SINCE",
9750
+ message: "--since must be an ISO-8601 timestamp or Unix milliseconds."
9751
+ },
9752
+ options
9753
+ );
9754
+ return;
9755
+ }
9602
9756
  const { http } = getAuthedHttpClient();
9603
9757
  const outputPath = options.output ? (0, import_node_path6.resolve)(String(options.output)) : defaultLedgerExportPath();
9604
9758
  let summary = { row_count: 0, net_delta_credits: 0 };
@@ -9608,6 +9762,8 @@ async function handleLedgerExportAll(options) {
9608
9762
  const params = new URLSearchParams({ limit: "5000" });
9609
9763
  if (cursor !== null) params.set("cursor", cursor);
9610
9764
  if (options.runId) params.set("run_id", options.runId);
9765
+ if (options.operation) params.set("operation", options.operation);
9766
+ if (sinceAt !== null) params.set("since_at", String(sinceAt));
9611
9767
  const payload = await http.get(
9612
9768
  `/api/v2/billing/ledger?${params.toString()}`
9613
9769
  );
@@ -9636,13 +9792,15 @@ async function handleLedgerExportAll(options) {
9636
9792
  net_delta_credits: summary.net_delta_credits,
9637
9793
  scope: "workspace",
9638
9794
  ...options.runId ? { run_id: options.runId } : {},
9795
+ ...options.operation ? { operation: options.operation } : {},
9796
+ ...sinceAt !== null ? { since_at: sinceAt } : {},
9639
9797
  render: {
9640
9798
  sections: [
9641
9799
  {
9642
9800
  title: "billing ledger",
9643
9801
  lines: [
9644
9802
  `Billing ledger written to ${outputPath}`,
9645
- `${summary.row_count} row(s) exported for the active workspace${options.runId ? ` and run ${options.runId}` : ""}.`,
9803
+ `${summary.row_count} row(s) exported for the active workspace${options.runId ? ` and run ${options.runId}` : ""}${options.operation ? ` and operation ${options.operation}` : ""}${sinceAt !== null ? ` since ${new Date(sinceAt).toISOString()}` : ""}.`,
9646
9804
  `Net ledger delta: ${summary.net_delta_credits} Deepline Credits`
9647
9805
  ]
9648
9806
  }
@@ -10339,6 +10497,7 @@ Examples:
10339
10497
  deepline billing ledger export all
10340
10498
  deepline billing ledger export all --output ./ledger.csv
10341
10499
  deepline billing ledger export all --run-id play/demo/run/abc123
10500
+ deepline billing ledger export all --operation limadata_find_audience_identifiers --since 2026-09-01T00:00:00Z
10342
10501
  deepline billing ledger export all --json
10343
10502
  `
10344
10503
  ).addCommand(
@@ -10360,7 +10519,10 @@ Examples:
10360
10519
  deepline billing ledger export all
10361
10520
  deepline billing ledger export all --json
10362
10521
  `
10363
- ).option("--output <path>", "Write CSV to an explicit path").option("--run-id <run_id>", "Export ledger rows for one play run.").option(
10522
+ ).option("--output <path>", "Write CSV to an explicit path").option("--run-id <run_id>", "Export ledger rows for one play run.").option("--operation <id>", "Export rows for one tool operation.").option(
10523
+ "--since <timestamp>",
10524
+ "Only export rows since ISO-8601 time or Unix milliseconds."
10525
+ ).option(
10364
10526
  "--json",
10365
10527
  "Emit JSON output. Also automatic when stdout is piped"
10366
10528
  ).action(handleLedgerExportAll)
@@ -16634,7 +16796,7 @@ async function traceCliSpan(phase, fields, run) {
16634
16796
  var EXTRACTED_GETTER_ERROR_HINT = "Deepline hint: extractedValues/extractedLists .get() only works for declared Deepline getters listed by `deepline tools describe <tool> --json`. Use `toolExecutionResult.toolResponse.raw` for provider/tool-specific scalar fields, and `toolExecutionResult.extractedLists.<name>.get()` for declared row/list outputs.";
16635
16797
  var DATASET_API_HINT = "Deepline hint: PlayDataset is lazy, durable, and async-only. Use `.count()`, `.first()`, `.at(index)`, `.peek(n)`, `.materialize(limit)`, or async iteration; do not use `.length`, numeric indexing, spread, synchronous iteration, `.rows`, or `.toArray()`.";
16636
16798
  var ROW_PROPERTY_HINT = "Deepline hint: this row type only contains fields produced by the CSV/schema and previous map steps. Check source column casing and the exact output field names from earlier steps before scaling.";
16637
- var TOOLS_EXECUTE_SIGNATURE_HINT = "Deepline hint: ctx.tools.execute requires a request object: `ctx.tools.execute({ id, tool, input, description })`. The stable `id` is required for logs, metadata, and receipt attachment; provider-call reuse is based on play, tool, semantic input, auth scope, provider action version, and cache policy.";
16799
+ var TOOLS_EXECUTE_SIGNATURE_HINT = "Deepline hint: ctx.tools.execute requires a request object: `ctx.tools.execute({ id, tool, input, description })`. The stable `id` is required for logs, metadata, and result-cache identity; terminal cache reuse is based on play, tool, semantic input, auth scope, provider action version, and cache policy.";
16638
16800
  var RUN_PLAY_SIGNATURE_HINT = "Deepline hint: ctx.runPlay uses a stable key plus a composable child play reference. Direct-run-only or dataset-backed batch plays must be run directly, exported, then consumed by a separate play.";
16639
16801
  var MAP_BACKED_CHILD_HINT = "Deepline hint: dataset-backed child plays own durable table state and cannot be called from another play. Run that play directly, export its dataset, then pass the CSV to the next play.";
16640
16802
  function sourceLineForError(sourceCode, error) {
@@ -32469,7 +32631,7 @@ function renderDeployedListText(payload, requestedStatus) {
32469
32631
  return status && count !== void 0 ? [`${status}: ${count}`] : [];
32470
32632
  }).join(" ") : "";
32471
32633
  if (summary) lines.push(`All lifecycle states: ${summary}`);
32472
- if (payload.is_truncated === true) {
32634
+ if (payload.has_more === true || payload.is_truncated === true) {
32473
32635
  const nextCursor = asString(payload.next_cursor);
32474
32636
  lines.push(
32475
32637
  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:',
@@ -32483,11 +32645,15 @@ function renderDeployedListText(payload, requestedStatus) {
32483
32645
  `;
32484
32646
  }
32485
32647
  async function handleMonitorsList(options) {
32648
+ if (options.compact) {
32649
+ process.stderr.write(
32650
+ "`--compact` is deprecated and now does nothing; returning the complete monitor records.\n"
32651
+ );
32652
+ }
32486
32653
  const payload = await new DeeplineClient().monitors.list({
32487
32654
  ...options.status ? { status: options.status } : {},
32488
32655
  ...options.limit ? { limit: options.limit } : {},
32489
32656
  ...options.cursor ? { cursor: options.cursor } : {},
32490
- ...options.compact ? { compact: true } : {},
32491
32657
  ...options.includeConsumers ? { includeConsumers: true } : {}
32492
32658
  });
32493
32659
  printCommandEnvelope(payload, {
@@ -32598,6 +32764,10 @@ var MONITOR_FLEET_COMMANDS = [
32598
32764
  {
32599
32765
  name: "deactivate",
32600
32766
  summary: "Deactivate a fleet and the monitors it owns."
32767
+ },
32768
+ {
32769
+ name: "reactivate",
32770
+ summary: "Explicitly recreate a fleet after a credit-triggered suspension."
32601
32771
  }
32602
32772
  ];
32603
32773
  var MONITOR_FLEET_AGENT_NOTES = [
@@ -33100,6 +33270,72 @@ async function handleMonitorFleetsGet(fleetId, options) {
33100
33270
  { json: options.json, text }
33101
33271
  );
33102
33272
  }
33273
+ function fleetReactivateCommandLine(fleetId, options) {
33274
+ const parts = [
33275
+ "deepline",
33276
+ "monitors",
33277
+ "fleets",
33278
+ "reactivate",
33279
+ fleetShellArg(fleetId),
33280
+ "--yes"
33281
+ ];
33282
+ if (options.wait) parts.push("--wait");
33283
+ if (options.timeout)
33284
+ parts.push(`--timeout ${fleetShellArg(options.timeout)}`);
33285
+ if (options.idempotencyKey)
33286
+ parts.push(`--idempotency-key ${fleetShellArg(options.idempotencyKey)}`);
33287
+ parts.push(...fleetJsonFlag(options));
33288
+ return parts.join(" ");
33289
+ }
33290
+ async function handleMonitorFleetsReactivate(fleetId, options, idempotencyKey) {
33291
+ if (!options.yes) {
33292
+ throw new MonitorsUsageError(
33293
+ `reactivate can recreate every suspended provider monitor and restart lifecycle billing. Confirm with --yes:
33294
+ ${fleetReactivateCommandLine(fleetId, options)}`
33295
+ );
33296
+ }
33297
+ const client2 = new DeeplineClient();
33298
+ const payload = await client2.monitors.fleets.reactivate(fleetId, {
33299
+ idempotencyKey
33300
+ });
33301
+ const accepted = { ...payload, idempotency_key: idempotencyKey };
33302
+ if (!options.wait) {
33303
+ printCommandEnvelope(accepted, {
33304
+ json: options.json,
33305
+ text: `Fleet ${fleetId} \u2014 ${asString(payload.status) ?? "billing_reactivating"}
33306
+ idempotency key ${idempotencyKey}
33307
+ `
33308
+ });
33309
+ return;
33310
+ }
33311
+ const timeoutMs = fleetTimeoutMs(options.timeout);
33312
+ const progress = fleetProgressReporter();
33313
+ let final;
33314
+ try {
33315
+ final = await client2.monitors.fleets.waitForConvergence(fleetId, {
33316
+ timeoutMs,
33317
+ pollIntervalMs: FLEET_POLL_INTERVAL_MS,
33318
+ onProgress: progress.report
33319
+ });
33320
+ } finally {
33321
+ progress.finish();
33322
+ }
33323
+ const envelope = { ...accepted, ...final };
33324
+ const text = renderFleetGet(final);
33325
+ if (fleetStatus(final) === "converged") {
33326
+ printCommandEnvelope(envelope, { json: options.json, text });
33327
+ return;
33328
+ }
33329
+ reportFleetState(
33330
+ envelope,
33331
+ new MonitorFleetStateError({
33332
+ code: "MONITOR_FLEET_WAIT_TIMEOUT",
33333
+ message: `Stopped waiting after ${timeoutMs}ms. Fleet ${fleetId} recovery is still in progress on the server.`,
33334
+ next: fleetServerNext(final) ?? `deepline monitors fleets get ${fleetShellArg(fleetId)} --json`
33335
+ }),
33336
+ { json: options.json, text }
33337
+ );
33338
+ }
33103
33339
  function fleetDeactivateCommandLine(fleetId, options) {
33104
33340
  const parts = [
33105
33341
  "deepline monitors fleets deactivate",
@@ -33397,18 +33633,11 @@ async function handleMonitorsGet(key, options) {
33397
33633
  }
33398
33634
  async function handleMonitorsTest(key, payload, options) {
33399
33635
  const explicitPayload = parseJsonObjectArg(payload, "<payload>");
33400
- const result = await new DeeplineClient().monitors.test(
33401
- key,
33402
- explicitPayload,
33403
- {
33404
- validationOnly: options.dispatch !== true,
33405
- dispatch: options.dispatch === true
33406
- }
33407
- );
33408
- const dispatch = options.dispatch === true;
33636
+ const result = await new DeeplineClient().monitors.test(key, explicitPayload);
33409
33637
  const text = `Monitor diagnostic for ${key}: ${result.accepted === true ? "accepted" : "rejected"}
33410
- ` + (dispatch ? " mode: dispatch (writes rows and may dispatch bound Plays)\n" : " mode: validation_only (no rows written, credits spent, or Plays dispatched)\n") + `${dispatch ? "persisted" : "would persist"} rows: ${asFiniteNumber(result.persisted_rows) ?? 0}
33411
- ${dispatch ? "dispatched" : "would dispatch"} bound Plays: ${asFiniteNumber(result.dispatched_bound_plays) ?? 0}
33638
+ mode: validation_only (no rows written, credits spent, or Plays dispatched)
33639
+ persisted rows: ${asFiniteNumber(result.persisted_rows) ?? 0}
33640
+ dispatched bound Plays: ${asFiniteNumber(result.dispatched_bound_plays) ?? 0}
33412
33641
  `;
33413
33642
  printCommandEnvelope(result, { json: options.json, text });
33414
33643
  }
@@ -33488,6 +33717,206 @@ async function handleMonitorsReactivate(key, options) {
33488
33717
  const payload = await client2.monitors.reactivate(key);
33489
33718
  printCommandEnvelope(payload, { json: options.json });
33490
33719
  }
33720
+ var MONITOR_VERB_POLL_INTERVAL_MS = 2e3;
33721
+ function monitorHealthLine(health) {
33722
+ return [
33723
+ `converged ${health.converged}/${health.scanned}`,
33724
+ `needs_repair ${health.needs_repair}`,
33725
+ `missing ${health.observed.missing}`,
33726
+ `unaudited ${health.observed.unknown + health.observed.unset}`,
33727
+ `silent ${health.silent}`
33728
+ ].join(" \xB7 ");
33729
+ }
33730
+ function monitorVerbProgressReporter() {
33731
+ const interactive = process.stderr.isTTY === true;
33732
+ let wrote = false;
33733
+ let lastPlainAt = 0;
33734
+ return {
33735
+ report: (health) => {
33736
+ const line = monitorHealthLine(health);
33737
+ if (interactive) {
33738
+ process.stderr.write(`\r\x1B[2K${line}`);
33739
+ wrote = true;
33740
+ return;
33741
+ }
33742
+ const now = Date.now();
33743
+ if (wrote && now - lastPlainAt < FLEET_PLAIN_PROGRESS_INTERVAL_MS) return;
33744
+ lastPlainAt = now;
33745
+ wrote = true;
33746
+ process.stderr.write(`${line}
33747
+ `);
33748
+ },
33749
+ finish: () => {
33750
+ if (interactive && wrote) process.stderr.write("\n");
33751
+ }
33752
+ };
33753
+ }
33754
+ async function watchMonitorHealth(input2) {
33755
+ const deadlineAt = Date.now() + input2.timeoutMs;
33756
+ const scope = input2.fleetId ? { fleetId: input2.fleetId } : {};
33757
+ let last = await input2.client.monitors.health(scope);
33758
+ input2.onProgress(last);
33759
+ while (Date.now() < deadlineAt) {
33760
+ if (last.needs_repair === 0 && last.observed.unknown === 0) return last;
33761
+ await new Promise(
33762
+ (resolve21) => setTimeout(resolve21, MONITOR_VERB_POLL_INTERVAL_MS)
33763
+ );
33764
+ last = await input2.client.monitors.health(scope);
33765
+ input2.onProgress(last);
33766
+ }
33767
+ return last;
33768
+ }
33769
+ function monitorHealthText(health) {
33770
+ const partial = health.truncated ? " (partial \u2014 scope larger than one read)" : "";
33771
+ const lines = [
33772
+ `scope: ${health.scope.fleet_id ?? "workspace"}${partial}`,
33773
+ monitorHealthLine(health)
33774
+ ];
33775
+ if (health.deactivation_reasons.length > 0) {
33776
+ lines.push("");
33777
+ lines.push("deactivated by Deepline:");
33778
+ for (const entry of health.deactivation_reasons) {
33779
+ const how = entry.resolution ? ` \u2014 ${entry.resolution}` : "";
33780
+ lines.push(` ${entry.reason} (${entry.count})${how}`);
33781
+ }
33782
+ }
33783
+ if (health.worst_offenders.length > 0) {
33784
+ lines.push("");
33785
+ lines.push(
33786
+ `silent longest (no delivery in ${health.silent_window_days}d):`
33787
+ );
33788
+ for (const entry of health.worst_offenders) {
33789
+ const when = entry.last_event_at === null ? "never" : new Date(entry.last_event_at).toISOString();
33790
+ lines.push(` ${entry.monitor_key} ${entry.tool} last event ${when}`);
33791
+ }
33792
+ }
33793
+ return `${lines.join("\n")}
33794
+ `;
33795
+ }
33796
+ async function handleMonitorsAudit(options) {
33797
+ const client2 = new DeeplineClient();
33798
+ const fleetId = options.fleet?.trim() || void 0;
33799
+ const scope = fleetId ? { fleetId } : {};
33800
+ let result = await client2.monitors.audit(scope);
33801
+ const passes = [result.audit];
33802
+ while (result.audit.cursor !== null) {
33803
+ result = await client2.monitors.audit({
33804
+ ...scope,
33805
+ cursor: result.audit.cursor
33806
+ });
33807
+ passes.push(result.audit);
33808
+ }
33809
+ const totals = passes.reduce(
33810
+ (sum, pass) => ({
33811
+ scanned: sum.scanned + pass.scanned,
33812
+ asked: sum.asked + pass.asked,
33813
+ stale: sum.stale + pass.stale,
33814
+ missing: sum.missing + pass.observed.missing
33815
+ }),
33816
+ { scanned: 0, asked: 0, stale: 0, missing: 0 }
33817
+ );
33818
+ let health = result.health;
33819
+ if (options.watch) {
33820
+ const progress = monitorVerbProgressReporter();
33821
+ try {
33822
+ health = await watchMonitorHealth({
33823
+ client: client2,
33824
+ ...scope,
33825
+ timeoutMs: fleetTimeoutMs(options.timeout),
33826
+ onProgress: progress.report
33827
+ });
33828
+ } finally {
33829
+ progress.finish();
33830
+ }
33831
+ }
33832
+ const unauditable = result.audit.unauditable_capabilities;
33833
+ const overtaken = totals.stale > 0 ? ` \xB7 ${totals.stale} observations overtaken by a concurrent settle` : "";
33834
+ const text = [
33835
+ `audited ${totals.scanned} monitors \xB7 asked the provider about ${totals.asked}`,
33836
+ `missing ${totals.missing}${overtaken}`,
33837
+ ...unauditable.length > 0 ? [`not auditable (no batch-read contract): ${unauditable.join(", ")}`] : [],
33838
+ "",
33839
+ monitorHealthText(health)
33840
+ ].join("\n");
33841
+ printCommandEnvelope(
33842
+ { ...result, audit: { ...result.audit, totals }, health },
33843
+ { json: options.json, text }
33844
+ );
33845
+ }
33846
+ async function handleMonitorsRepair(options) {
33847
+ const client2 = new DeeplineClient();
33848
+ const fleetId = options.fleet?.trim() || void 0;
33849
+ const scope = fleetId ? { fleetId } : {};
33850
+ const result = await client2.monitors.repair({
33851
+ ...scope,
33852
+ ...options.dryRun ? { dryRun: true } : {}
33853
+ });
33854
+ if (options.dryRun) {
33855
+ assertMonitorDryRunAcknowledged(
33856
+ result,
33857
+ { command: "monitors repair", mutation: "repair" }
33858
+ );
33859
+ }
33860
+ let health = result.health;
33861
+ if (options.watch && !options.dryRun) {
33862
+ const progress = monitorVerbProgressReporter();
33863
+ try {
33864
+ health = await watchMonitorHealth({
33865
+ client: client2,
33866
+ ...scope,
33867
+ timeoutMs: fleetTimeoutMs(options.timeout),
33868
+ onProgress: progress.report
33869
+ });
33870
+ } finally {
33871
+ progress.finish();
33872
+ }
33873
+ }
33874
+ const verb = options.dryRun ? "would queue" : "queued";
33875
+ const lines = [
33876
+ `${verb} ${result.repair.queued} of ${result.repair.scanned} monitors`
33877
+ ];
33878
+ for (const item of result.repair.plan.slice(0, REPAIR_PLAN_PREVIEW)) {
33879
+ const why = item.deactivation_reason ? ` \xB7 ${item.deactivation_reason}` : "";
33880
+ lines.push(
33881
+ ` ${item.action.padEnd(6)} ${item.monitor_key} desired ${item.desired} \xB7 observed ${item.observed}${why}`
33882
+ );
33883
+ }
33884
+ if (result.repair.plan.length > REPAIR_PLAN_PREVIEW) {
33885
+ lines.push(` \u2026 ${result.repair.plan.length - REPAIR_PLAN_PREVIEW} more`);
33886
+ }
33887
+ if (result.repair.unaudited.length > 0) {
33888
+ lines.push(
33889
+ `${result.repair.unaudited.length} monitors have never been observed \u2014 run 'deepline monitors audit' first.`
33890
+ );
33891
+ }
33892
+ if (result.repair.unowned.length > 0) {
33893
+ lines.push(
33894
+ `${result.repair.unowned.length} monitors disagree but no fleet owns them; repair those with 'deepline monitors deploy' or 'deepline monitors delete'.`
33895
+ );
33896
+ }
33897
+ if (result.repair.fenced.length > 0) {
33898
+ lines.push(
33899
+ `${result.repair.fenced.length} monitors have a provider operation in flight; Deepline is finishing those and repair left them alone.`
33900
+ );
33901
+ }
33902
+ lines.push("");
33903
+ lines.push(monitorHealthText(health));
33904
+ printCommandEnvelope(
33905
+ { ...result, health },
33906
+ { json: options.json, text: lines.join("\n") }
33907
+ );
33908
+ }
33909
+ var REPAIR_PLAN_PREVIEW = 20;
33910
+ async function handleMonitorsHealth(options) {
33911
+ const fleetId = options.fleet?.trim() || void 0;
33912
+ const health = await new DeeplineClient().monitors.health(
33913
+ fleetId ? { fleetId } : {}
33914
+ );
33915
+ printCommandEnvelope(health, {
33916
+ json: options.json,
33917
+ text: monitorHealthText(health)
33918
+ });
33919
+ }
33491
33920
  function registerMonitorsCommands(program) {
33492
33921
  const monitors = program.command("monitors").description("Discover, deploy, and manage Deepline monitors.").showSuggestionAfterError(true).addHelpText(
33493
33922
  "after",
@@ -33523,6 +33952,75 @@ Examples:
33523
33952
  deepline monitors reactivate my-monitor --dry-run
33524
33953
  `
33525
33954
  );
33955
+ withJsonOption(
33956
+ monitors.command("audit").description(
33957
+ "Re-read what the provider actually holds for your monitors."
33958
+ ).option("--fleet <fleet-id>", "Audit one fleet instead of every monitor").option("--watch", "Keep polling health until the scope settles").option(
33959
+ "--timeout <duration>",
33960
+ "How long --watch waits, e.g. 90s, 5m, 1h (default 10m)"
33961
+ ).addHelpText(
33962
+ "after",
33963
+ `
33964
+ Notes:
33965
+ Asks the provider, by resource id, what it still holds, and records the answer
33966
+ on each monitor. It changes nothing upstream: no creates, no deletes, no
33967
+ intent. Safe to run at any time, as often as you like \u2014 running it twice is
33968
+ running it once, twice.
33969
+
33970
+ A monitor the provider does not return is recorded "missing". Use
33971
+ 'deepline monitors repair' to act on that.
33972
+
33973
+ Examples:
33974
+ deepline monitors audit
33975
+ deepline monitors audit --fleet accounts-eu --json
33976
+ deepline monitors audit --fleet accounts-eu --watch --timeout 5m
33977
+ `
33978
+ )
33979
+ ).action(monitorsAction(handleMonitorsAudit));
33980
+ withJsonOption(
33981
+ monitors.command("repair").description(
33982
+ "Converge the monitors whose desired and observed states disagree."
33983
+ ).option("--fleet <fleet-id>", "Repair one fleet instead of every monitor").option("--dry-run", "Show what would be queued without queueing it").option("--watch", "Keep polling health until the scope settles").option(
33984
+ "--timeout <duration>",
33985
+ "How long --watch waits, e.g. 90s, 5m, 1h (default 10m)"
33986
+ ).addHelpText(
33987
+ "after",
33988
+ `
33989
+ Notes:
33990
+ Queues the monitors that disagree with the provider onto the same convergence
33991
+ loop a fleet sync uses; the provider work happens on Deepline's own schedule.
33992
+ Idempotent \u2014 the queue IS the disagreement, so a repeat run queues only what
33993
+ is still wrong.
33994
+
33995
+ Monitors nobody has observed are never repaired: run 'deepline monitors audit'
33996
+ first. Monitors no fleet owns are reported rather than queued; deploy or delete
33997
+ those directly.
33998
+
33999
+ Examples:
34000
+ deepline monitors repair --dry-run
34001
+ deepline monitors repair --fleet accounts-eu --watch
34002
+ `
34003
+ )
34004
+ ).action(monitorsAction(handleMonitorsRepair));
34005
+ withJsonOption(
34006
+ monitors.command("health").description("Delivery and convergence health for your monitors.").option(
34007
+ "--fleet <fleet-id>",
34008
+ "Report on one fleet instead of every monitor"
34009
+ ).addHelpText(
34010
+ "after",
34011
+ `
34012
+ Notes:
34013
+ Read-only. Reports how many monitors the provider holds as asked, how many
34014
+ disagree, how many Deepline deactivated and why, and how many are "silent" \u2014
34015
+ the provider holds them but nothing has been delivered recently. The worst
34016
+ offenders are listed longest-quiet first.
34017
+
34018
+ Examples:
34019
+ deepline monitors health
34020
+ deepline monitors health --fleet accounts-eu --json
34021
+ `
34022
+ )
34023
+ ).action(monitorsAction(handleMonitorsHealth));
33526
34024
  withJsonOption(
33527
34025
  monitors.command("status").description("Check whether you have access to Deepline monitors.").addHelpText(
33528
34026
  "after",
@@ -33575,10 +34073,10 @@ Examples:
33575
34073
  `
33576
34074
  Notes:
33577
34075
  Read-only. --status filters by monitor status: active (default), disabled, or
33578
- all. The output echoes the status filter that was applied. --compact returns
33579
- high-signal fields only. The response reports total (the true registry count,
33580
- not the page size), returned, is_truncated, and next_cursor. When is_truncated
33581
- is true, page with --cursor <next_cursor> until it is false \u2014 a "no matching
34076
+ all. The output echoes the status filter that was applied. The response reports
34077
+ total (the true registry count, not the page size), returned, has_more, and
34078
+ next_cursor. When has_more is true, page with --cursor <next_cursor> until it
34079
+ is false \u2014 a "no matching
33582
34080
  monitor" reuse conclusion off a truncated page deploys a duplicate paid feed.
33583
34081
  The default list stays cheap: it includes the current downstream Play binding
33584
34082
  metadata but does not resolve per-monitor delivery/run health. Pass
@@ -33589,7 +34087,6 @@ Examples:
33589
34087
  deepline monitors list
33590
34088
  deepline monitors list --status all --json
33591
34089
  deepline monitors list --status all --cursor <next_cursor> --json
33592
- deepline monitors list --compact --json
33593
34090
  deepline monitors list --include-consumers --limit 20 --json
33594
34091
  `
33595
34092
  ).option(
@@ -33598,7 +34095,10 @@ Examples:
33598
34095
  ).option("--limit <n>", "Limit the number of deployed monitors returned").option(
33599
34096
  "--cursor <cursor>",
33600
34097
  "Page past a truncated result using the next_cursor from a prior list response"
33601
- ).option("--compact", COMPACT_OPTION_DESCRIPTION).option(
34098
+ ).option(
34099
+ "--compact",
34100
+ "Deprecated no-op; complete records are always returned"
34101
+ ).option(
33602
34102
  "--include-consumers",
33603
34103
  "Include current SQL-listener consumer health (requires --limit 20 or fewer)"
33604
34104
  )
@@ -33621,10 +34121,7 @@ Examples:
33621
34121
  ).action(monitorsAction(handleMonitorsGet));
33622
34122
  withJsonOption(
33623
34123
  monitors.command("test <key> <payload>").description(
33624
- "Send an explicit payload through a monitor\u2019s webhook ingestion path."
33625
- ).option(
33626
- "--dispatch",
33627
- "Inject the test event through normal ingestion (writes rows and may dispatch bound Plays)"
34124
+ "Validate an explicit payload against a monitor\u2019s webhook contract."
33628
34125
  ).addHelpText(
33629
34126
  "after",
33630
34127
  `
@@ -33632,9 +34129,8 @@ Notes:
33632
34129
  <payload> must be an explicit JSON object. The command uses the deployed
33633
34130
  monitor\u2019s real binding and payload validation, but is a side-effect-free
33634
34131
  diagnostic: it does not persist rows, spend credits, dispatch Plays, or alter
33635
- monitor state. Pass --dispatch only when you deliberately need the historic
33636
- full-ingestion test event; it can write rows and trigger bound Plays. It does
33637
- not synthesize a provider event or accept an omitted payload.
34132
+ monitor state. It does not synthesize a provider event or accept an omitted
34133
+ payload.
33638
34134
 
33639
34135
  Examples:
33640
34136
  deepline monitors test rb2b-website-visitors '{"LinkedIn URL":"https://www.linkedin.com/in/example","Website":"https://example.com"}' --json
@@ -33951,6 +34447,40 @@ Examples:
33951
34447
  reportMonitorsFailure(error, { retryCommand });
33952
34448
  }
33953
34449
  });
34450
+ withJsonOption(
34451
+ fleets.command("reactivate <fleet-id>").description(
34452
+ "Explicitly recreate a fleet after a credit-triggered suspension."
34453
+ ).addHelpText(
34454
+ "after",
34455
+ `
34456
+ Notes:
34457
+ TAMRadar cannot reactivate a deleted radar. This command starts normal,
34458
+ fenced provider creates from the fleet's retained desired definitions and
34459
+ may restart lifecycle billing. A credit top-up alone never does this.
34460
+
34461
+ Example:
34462
+ deepline monitors fleets reactivate account-job-openings --yes --wait --json
34463
+ `
34464
+ ).option("--wait", "Poll until the fleet reports converged").option(
34465
+ "--timeout <duration>",
34466
+ "How long --wait may poll: 500ms, 90s, 10m, 1h (default 10m)"
34467
+ ).option("--yes", "Confirm recreating suspended provider monitors").option("--idempotency-key <key>", "Stable retry key")
34468
+ ).action(async (fleetId, options) => {
34469
+ let retryCommand = fleetReactivateCommandLine(fleetId, options);
34470
+ try {
34471
+ const idempotencyKey = fleetIdempotencyKey(
34472
+ "reactivate",
34473
+ options.idempotencyKey
34474
+ );
34475
+ retryCommand = fleetReactivateCommandLine(fleetId, {
34476
+ ...options,
34477
+ idempotencyKey
34478
+ });
34479
+ await handleMonitorFleetsReactivate(fleetId, options, idempotencyKey);
34480
+ } catch (error) {
34481
+ reportMonitorsFailure(error, { retryCommand });
34482
+ }
34483
+ });
33954
34484
  const deployed = withJsonOption(
33955
34485
  monitors.command("deployed", { hidden: true }).description("Alias of `monitors list` (plus get/update/delete aliases).").option(
33956
34486
  "--status <status>",
@@ -33958,7 +34488,10 @@ Examples:
33958
34488
  ).option("--limit <n>", "Limit the number of deployed monitors returned").option(
33959
34489
  "--cursor <cursor>",
33960
34490
  "Page past a truncated result using the next_cursor from a prior list response"
33961
- ).option("--compact", COMPACT_OPTION_DESCRIPTION).option(
34491
+ ).option(
34492
+ "--compact",
34493
+ "Deprecated no-op; complete records are always returned"
34494
+ ).option(
33962
34495
  "--include-consumers",
33963
34496
  "Include current SQL-listener consumer health (requires --limit 20 or fewer)"
33964
34497
  )
@@ -34280,11 +34813,13 @@ async function handleOrgStatus(options) {
34280
34813
  host_env_path: hostPath,
34281
34814
  folder_target: folderTargetPayload,
34282
34815
  project_pin: provenance.scope === "global" && provenance.project.state === "project" ? {
34283
- required: true,
34816
+ available: true,
34817
+ required: false,
34284
34818
  path: provenance.project.pinPath,
34285
- cloud_mutations_blocked: true,
34819
+ cloud_mutations_blocked: false,
34286
34820
  command: "deepline org set --auth-scope folder"
34287
34821
  } : {
34822
+ available: false,
34288
34823
  required: false,
34289
34824
  cloud_mutations_blocked: false
34290
34825
  },
@@ -34705,8 +35240,8 @@ Examples:
34705
35240
  Notes:
34706
35241
  Selection can be a list number, exact organization name, or organization id.
34707
35242
  Without a selection, prints choices. With --auth-scope folder while this
34708
- project is using global host auth, it pins the current target directly; this
34709
- is the fastest safe repair for a blocked cloud mutation.
35243
+ project is using global host auth, it pins the current target directly
35244
+ without an additional organization lookup.
34710
35245
 
34711
35246
  Mutates local auth state and asks Deepline for an org-scoped API key. It
34712
35247
  writes only the selected scope:
@@ -34723,7 +35258,9 @@ Notes:
34723
35258
 
34724
35259
  Prefer --auth-scope folder for a repository or customer workspace. Use
34725
35260
  --auth-scope global only for deliberate host-wide interactive defaults; it
34726
- is shared by every unpinned CLI on this machine. For automation, pass
35261
+ is shared by every unpinned CLI on this machine. Global auth remains
35262
+ supported in projects; use a folder pin when you want a project-specific
35263
+ default. For automation, pass
34727
35264
  DEEPLINE_API_KEY only to that invocation and confirm with org status --json.
34728
35265
 
34729
35266
  Use --json for stable fields including effective_auth_scope,
@@ -34766,6 +35303,318 @@ Examples:
34766
35303
  );
34767
35304
  }
34768
35305
 
35306
+ // src/cli/commands/git.ts
35307
+ function renderProject(project) {
35308
+ const root = project.rootDirectory ? ` (${project.rootDirectory})` : "";
35309
+ const flags = [
35310
+ project.disabled ? "unlinked" : "linked",
35311
+ `deploys ${project.productionBranch}`,
35312
+ project.checkOnPullRequest ? "PR checks on" : "PR checks off"
35313
+ ].join(", ");
35314
+ return `${project.id} ${project.repoFullName}${root} - ${flags}`;
35315
+ }
35316
+ function renderDeployment(deployment) {
35317
+ const ref = deployment.ref.replace("refs/heads/", "");
35318
+ const kind = deployment.isProduction ? "production" : deployment.trigger === "pull_request" ? `pr #${deployment.pullRequestNumber ?? "?"}` : deployment.trigger;
35319
+ const suffix = deployment.error ? ` - ${deployment.error.slice(0, 80)}` : "";
35320
+ return `${deployment.id} ${deployment.commitSha.slice(0, 10)} ${ref} (${kind}) - ${deployment.status}${suffix}`;
35321
+ }
35322
+ async function handleList(options) {
35323
+ const { http } = getAuthedHttpClient();
35324
+ const payload = await http.get(
35325
+ `/api/v2/play-projects${options.all ? "?includeDisabled=1" : ""}`
35326
+ );
35327
+ printCommandEnvelope(
35328
+ {
35329
+ projects: payload.projects,
35330
+ count: payload.projects.length,
35331
+ render: {
35332
+ sections: [
35333
+ {
35334
+ title: "linked repositories",
35335
+ lines: payload.projects.length ? payload.projects.map(renderProject) : [
35336
+ "No repositories are linked. Run `deepline git repos` to see what the GitHub installation can reach, then `deepline git link`."
35337
+ ]
35338
+ }
35339
+ ]
35340
+ }
35341
+ },
35342
+ { json: options.json }
35343
+ );
35344
+ }
35345
+ async function handleRepos(options) {
35346
+ const { http } = getAuthedHttpClient();
35347
+ const query = options.installation ? `?installationId=${encodeURIComponent(options.installation)}` : "";
35348
+ const payload = await http.get(`/api/v2/github/repos${query}`);
35349
+ printCommandEnvelope(
35350
+ {
35351
+ installation: payload.installation,
35352
+ repositories: payload.repositories,
35353
+ count: payload.repositories.length,
35354
+ render: {
35355
+ sections: [
35356
+ {
35357
+ title: `repos on installation @${payload.installation.accountLogin} (${payload.installation.repositorySelection})`,
35358
+ lines: payload.repositories.map(
35359
+ (repo) => `${repo.repoId} ${repo.fullName} (default: ${repo.defaultBranch}${repo.private ? ", private" : ""}${repo.fork ? ", fork" : ""})`
35360
+ )
35361
+ }
35362
+ ]
35363
+ }
35364
+ },
35365
+ { json: options.json }
35366
+ );
35367
+ }
35368
+ async function resolveRepoId(repo, installation) {
35369
+ if (/^\d+$/.test(repo)) return Number(repo);
35370
+ const { http } = getAuthedHttpClient();
35371
+ const query = installation ? `?installationId=${encodeURIComponent(installation)}` : "";
35372
+ const payload = await http.get(
35373
+ `/api/v2/github/repos${query}`
35374
+ );
35375
+ const match = payload.repositories.find(
35376
+ (entry) => entry.fullName.toLowerCase() === repo.toLowerCase()
35377
+ );
35378
+ if (!match) {
35379
+ throw new Error(
35380
+ `Repo "${repo}" is not accessible to the workspace's GitHub installation. Run \`deepline git repos\` to list what is.`
35381
+ );
35382
+ }
35383
+ return match.repoId;
35384
+ }
35385
+ async function handleLink(repo, options) {
35386
+ const repoId = await resolveRepoId(repo, options.installation);
35387
+ const { http } = getAuthedHttpClient();
35388
+ const payload = await http.post("/api/v2/play-projects", {
35389
+ repoId,
35390
+ ...options.installation !== void 0 ? { installationId: options.installation } : {},
35391
+ ...options.rootDir !== void 0 ? { rootDirectory: options.rootDir } : {},
35392
+ ...options.manifest !== void 0 ? { manifestPath: options.manifest } : {},
35393
+ ...options.branch !== void 0 ? { productionBranch: options.branch } : {},
35394
+ ...options.prChecks !== void 0 ? { checkOnPullRequest: options.prChecks } : {}
35395
+ });
35396
+ printCommandEnvelope(
35397
+ {
35398
+ project: payload.project,
35399
+ render: {
35400
+ sections: [
35401
+ {
35402
+ title: "linked",
35403
+ lines: [
35404
+ renderProject(payload.project),
35405
+ ...(payload.warnings ?? []).map(
35406
+ (warning) => `WARNING: ${warning}`
35407
+ ),
35408
+ "Pushes to the production branch now register and promote changed plays.",
35409
+ "Anyone who can push to this repo can change what runs in this workspace."
35410
+ ]
35411
+ }
35412
+ ]
35413
+ }
35414
+ },
35415
+ { json: options.json }
35416
+ );
35417
+ }
35418
+ async function handleGet(id, options) {
35419
+ const { http } = getAuthedHttpClient();
35420
+ const payload = await http.get(
35421
+ `/api/v2/play-projects/${encodeURIComponent(id)}`
35422
+ );
35423
+ printCommandEnvelope(
35424
+ {
35425
+ project: payload.project,
35426
+ render: {
35427
+ sections: [
35428
+ {
35429
+ title: "linked repository",
35430
+ lines: [renderProject(payload.project)]
35431
+ }
35432
+ ]
35433
+ }
35434
+ },
35435
+ { json: options.json }
35436
+ );
35437
+ }
35438
+ async function handleSet(id, options) {
35439
+ const { http } = getAuthedHttpClient();
35440
+ const payload = await http.patch(
35441
+ `/api/v2/play-projects/${encodeURIComponent(id)}`,
35442
+ {
35443
+ ...options.branch !== void 0 ? { productionBranch: options.branch } : {},
35444
+ ...options.rootDir !== void 0 ? { rootDirectory: options.rootDir } : {},
35445
+ ...options.manifest !== void 0 ? { manifestPath: options.manifest } : {},
35446
+ ...options.prChecks !== void 0 ? { checkOnPullRequest: options.prChecks } : {},
35447
+ ...options.disabled !== void 0 ? { disabled: options.disabled } : {}
35448
+ }
35449
+ );
35450
+ printCommandEnvelope(
35451
+ {
35452
+ project: payload.project,
35453
+ render: {
35454
+ sections: [
35455
+ { title: "updated", lines: [renderProject(payload.project)] }
35456
+ ]
35457
+ }
35458
+ },
35459
+ { json: options.json }
35460
+ );
35461
+ }
35462
+ async function handleUnlink(id, options) {
35463
+ const { http } = getAuthedHttpClient();
35464
+ await http.delete(`/api/v2/play-projects/${encodeURIComponent(id)}`);
35465
+ printCommandEnvelope(
35466
+ {
35467
+ ok: true,
35468
+ id,
35469
+ render: {
35470
+ sections: [
35471
+ {
35472
+ title: "unlinked",
35473
+ lines: [
35474
+ `Repository link ${id} removed. Deployments stop immediately and in-flight deploy credentials die; live plays keep running.`
35475
+ ]
35476
+ }
35477
+ ]
35478
+ }
35479
+ },
35480
+ { json: options.json }
35481
+ );
35482
+ }
35483
+ async function handleConnect(options) {
35484
+ const baseUrl = resolveBaseUrlOnly();
35485
+ const connectUrl = `${baseUrl.replace(/\/$/, "")}/api/v2/github/connect`;
35486
+ const opened = openInBrowser(connectUrl);
35487
+ printCommandEnvelope(
35488
+ {
35489
+ connectUrl,
35490
+ browser: opened,
35491
+ render: {
35492
+ sections: [
35493
+ {
35494
+ title: "connect GitHub",
35495
+ lines: [
35496
+ opened === "opened" ? `Opened ${connectUrl} in your browser.` : `Open ${connectUrl} in your browser.`,
35497
+ "Sign in as a workspace admin if prompted, approve the GitHub",
35498
+ "installation, then return here and run `deepline git repos`."
35499
+ ]
35500
+ }
35501
+ ]
35502
+ }
35503
+ },
35504
+ { json: options.json }
35505
+ );
35506
+ }
35507
+ async function handleDeploymentsList(options) {
35508
+ const { http } = getAuthedHttpClient();
35509
+ const query = new URLSearchParams();
35510
+ if (options.repo) query.set("projectId", options.repo);
35511
+ if (options.limit) query.set("limit", options.limit);
35512
+ const suffix = query.size > 0 ? `?${query.toString()}` : "";
35513
+ const payload = await http.get(
35514
+ `/api/v2/deployments${suffix}`
35515
+ );
35516
+ printCommandEnvelope(
35517
+ {
35518
+ deployments: payload.deployments,
35519
+ count: payload.deployments.length,
35520
+ render: {
35521
+ sections: [
35522
+ {
35523
+ title: "deployments",
35524
+ lines: payload.deployments.length ? payload.deployments.map(renderDeployment) : [
35525
+ "No deployments yet. Push to a linked repository to create one."
35526
+ ]
35527
+ }
35528
+ ]
35529
+ }
35530
+ },
35531
+ { json: options.json }
35532
+ );
35533
+ }
35534
+ async function handleDeploymentGet(id, options) {
35535
+ const { http } = getAuthedHttpClient();
35536
+ const payload = await http.get(`/api/v2/deployments/${encodeURIComponent(id)}`);
35537
+ const results = payload.deployment.results;
35538
+ const playLines = Array.isArray(results?.plays) ? results.plays.map(
35539
+ (play) => `${play.name ?? "?"} - ${play.status ?? "?"}${play.error ? `: ${play.error}` : ""}`
35540
+ ) : [];
35541
+ printCommandEnvelope(
35542
+ {
35543
+ deployment: payload.deployment,
35544
+ project: payload.project,
35545
+ render: {
35546
+ sections: [
35547
+ {
35548
+ title: `deployment ${payload.deployment.id}${payload.project ? ` (${payload.project.repoFullName})` : ""}`,
35549
+ lines: [renderDeployment(payload.deployment)]
35550
+ },
35551
+ ...playLines.length ? [{ title: "plays", lines: playLines }] : []
35552
+ ]
35553
+ }
35554
+ },
35555
+ { json: options.json }
35556
+ );
35557
+ }
35558
+ function registerGitCommands(program) {
35559
+ const git = program.command("git").alias("projects").description(
35560
+ "Git deploys: link repositories to this workspace and deploy plays on push."
35561
+ ).addHelpText(
35562
+ "after",
35563
+ `
35564
+ Examples:
35565
+ deepline git connect
35566
+ deepline git repos
35567
+ deepline git link acme/growth --branch main
35568
+ deepline git list
35569
+ deepline git set <id> --branch release
35570
+ deepline git unlink <id>
35571
+ deepline git deployments --repo <id>
35572
+ `
35573
+ );
35574
+ git.command("connect").description("Connect a GitHub installation (browser step).").option("--json", "Emit JSON output").action(async (options) => handleConnect(options));
35575
+ git.command("repos").description("List repos the workspace's GitHub installation can reach.").option(
35576
+ "--installation <id>",
35577
+ "GitHub installation id (required when several are connected)"
35578
+ ).option("--json", "Emit JSON output").action(
35579
+ async (options) => handleRepos(options)
35580
+ );
35581
+ git.command("list").description("List linked repositories.").option("--all", "Include unlinked repositories").option("--json", "Emit JSON output").action(
35582
+ async (options) => handleList(options)
35583
+ );
35584
+ git.command("link").description("Link a repository to this workspace for deploy-on-push.").argument("<repo>", "Repo full name (owner/name) or numeric repo id").option("--root-dir <path>", "Base path inside the repo for this link").option("--branch <name>", "Production branch (default: repo default)").option(
35585
+ "--manifest <file>",
35586
+ "Manifest file name under the base path (default: deepline.json)"
35587
+ ).option(
35588
+ "--installation <id>",
35589
+ "GitHub installation id (required when several are connected)"
35590
+ ).option("--no-pr-checks", "Skip Check Runs on pull requests").option("--json", "Emit JSON output").action(
35591
+ async (repo, options) => handleLink(repo, options)
35592
+ );
35593
+ git.command("get").description("Show one linked repository.").argument("<id>", "Repository link id").option("--json", "Emit JSON output").action(async (id, options) => handleGet(id, options));
35594
+ git.command("set").description("Update a linked repository.").argument("<id>", "Repository link id").option("--branch <name>", "Production branch").option("--root-dir <path>", "Base path inside the repo for this link").option(
35595
+ "--manifest <file>",
35596
+ "Manifest file name under the base path (default: deepline.json)"
35597
+ ).option("--pr-checks", "Enable Check Runs on pull requests").option("--no-pr-checks", "Disable Check Runs on pull requests").option("--disabled", "Pause deployments for this link").option("--enabled", "Resume deployments for this link").option("--json", "Emit JSON output").action(
35598
+ async (id, options) => handleSet(id, {
35599
+ ...options,
35600
+ disabled: options.enabled === true ? false : options.disabled === true ? true : void 0
35601
+ })
35602
+ );
35603
+ git.command("unlink").description("Unlink a repository (live plays keep running).").argument("<id>", "Repository link id").option("--json", "Emit JSON output").action(
35604
+ async (id, options) => handleUnlink(id, options)
35605
+ );
35606
+ git.command("deployments").description("Deployment history; pass an id for one deployment.").argument("[id]", "Deployment id (omit to list)").option("--repo <id>", "Filter to one repository link").option("--limit <n>", "Max rows (default 50)").option("--json", "Emit JSON output").action(
35607
+ async (id, options) => id ? handleDeploymentGet(id, options) : handleDeploymentsList(options)
35608
+ );
35609
+ const deployments = program.command("deployments", { hidden: true });
35610
+ deployments.command("list").option("--project <id>", "Filter to one repository link").option("--limit <n>", "Max rows (default 50)").option("--json", "Emit JSON output").action(
35611
+ async (options) => handleDeploymentsList({ ...options, repo: options.project })
35612
+ );
35613
+ deployments.command("get").argument("<id>", "Deployment id").option("--json", "Emit JSON output").action(
35614
+ async (id, options) => handleDeploymentGet(id, options)
35615
+ );
35616
+ }
35617
+
34769
35618
  // src/cli/getting-started.ts
34770
35619
  var DEEPLINE_GTM_SKILL = "/deepline-gtm";
34771
35620
  var DEEPLINE_GTM_STARTER_PROMPTS = [
@@ -35006,7 +35855,7 @@ function preventShellHistoryLeak(forbidden) {
35006
35855
  );
35007
35856
  }
35008
35857
  }
35009
- async function handleList(options) {
35858
+ async function handleList2(options) {
35010
35859
  const client2 = new DeeplineClient();
35011
35860
  const secrets = await client2.listSecrets();
35012
35861
  printCommandEnvelope(
@@ -35049,7 +35898,7 @@ async function handleCheck(nameInput, options) {
35049
35898
  );
35050
35899
  if (!secret) process.exitCode = 4;
35051
35900
  }
35052
- async function handleSet(nameInput, forbidden, options) {
35901
+ async function handleSet2(nameInput, forbidden, options) {
35053
35902
  preventShellHistoryLeak(forbidden);
35054
35903
  const name = normalizeSecretName(nameInput);
35055
35904
  const scope = options.scope === "play" ? "play" : "org";
@@ -35108,14 +35957,14 @@ Examples:
35108
35957
  `
35109
35958
  );
35110
35959
  secrets.command("list").description("List secret metadata only.").option("--json", "Emit JSON output").action(async (options) => {
35111
- await handleList(options);
35960
+ await handleList2(options);
35112
35961
  });
35113
35962
  secrets.command("check").description("Check whether a secret exists and is active.").argument("<name>", "Secret name").option("--json", "Emit JSON output").action(async (name, options) => {
35114
35963
  await handleCheck(name, options);
35115
35964
  });
35116
35965
  secrets.command("set").description("Set or rotate a secret without exposing its value in argv.").argument("<name>", "Secret name").argument("[forbidden...]", "Do not pass secret values here").option("--json", "Emit JSON output").option("--scope <scope>", "Secret scope: org or play", "org").option("--play <name>", "Play name for play-scoped secrets").option("--value-stdin", "Read the value from piped stdin").option("--from-env <name>", "Read the value from an environment variable").option("--from-file <path>", "Read the value from a file").action(
35117
35966
  async (name, forbidden, options) => {
35118
- await handleSet(name, forbidden ?? [], options);
35967
+ await handleSet2(name, forbidden ?? [], options);
35119
35968
  }
35120
35969
  );
35121
35970
  }
@@ -36746,7 +37595,7 @@ function failSetupPhase(phases, phase, code) {
36746
37595
  }
36747
37596
  function rollbackCommand(scope, root) {
36748
37597
  const prefix = scope === "local" && root ? ` --prefix ${JSON.stringify((0, import_node_path22.join)(root, ".deepline", "runtime"))}` : "";
36749
- return `npm install -g${prefix} --no-audit --no-fund --include=optional --allow-scripts=esbuild deepline@${SDK_VERSION}`;
37598
+ return `npm install -g${prefix} --no-audit --no-fund --include=optional deepline@${SDK_VERSION}`;
36750
37599
  }
36751
37600
  function setupResumeCommand(baseUrl, scope) {
36752
37601
  const hostPrefix = baseUrl === "https://code.deepline.com" ? "" : `DEEPLINE_HOST_URL=${JSON.stringify(baseUrl)} `;
@@ -37315,9 +38164,7 @@ async function runSetupCommand(options) {
37315
38164
  title: "setup",
37316
38165
  lines: [
37317
38166
  workspaceName ? `Deepline is installed and connected to ${workspaceName}.` : "Deepline is installed and connected.",
37318
- ...workspaceName ? [
37319
- "To link a different workspace, run: deepline auth register"
37320
- ] : [],
38167
+ ...workspaceName ? ["To link a different workspace, run: deepline auth register"] : [],
37321
38168
  `Use ${DEEPLINE_GTM_SKILL} in your agent.`,
37322
38169
  ...DEEPLINE_GTM_STARTER_PROMPTS.map(
37323
38170
  (example, index) => `${index + 1}. ${example.title}: ${example.prompt}`
@@ -37661,12 +38508,6 @@ var NPM_SDK_INSTALL_COMMON_FLAGS = [
37661
38508
  "--no-fund",
37662
38509
  "--include=optional"
37663
38510
  ];
37664
- var NPM_SDK_GLOBAL_INSTALL_FLAGS = [
37665
- "--no-audit",
37666
- "--no-fund",
37667
- "--include=optional",
37668
- "--allow-scripts=esbuild"
37669
- ];
37670
38511
  var NPM_SDK_SIDECAR_PACKAGE_JSON = `${JSON.stringify(
37671
38512
  {
37672
38513
  private: true,
@@ -37901,9 +38742,9 @@ function resolveUpdatePlan(options = {}) {
37901
38742
  "-g",
37902
38743
  "--prefix",
37903
38744
  installPrefix,
37904
- ...NPM_SDK_GLOBAL_INSTALL_FLAGS,
38745
+ ...NPM_SDK_INSTALL_COMMON_FLAGS,
37905
38746
  packageSpec
37906
- ] : ["install", "-g", ...NPM_SDK_GLOBAL_INSTALL_FLAGS, packageSpec];
38747
+ ] : ["install", "-g", ...NPM_SDK_INSTALL_COMMON_FLAGS, packageSpec];
37907
38748
  const fallbackRegistryUrl = options.npmFallbackRegistryUrl !== void 0 ? options.npmFallbackRegistryUrl : publicNpmFallbackRegistryUrl(
37908
38749
  env.DEEPLINE_HOST_URL?.trim() || autoDetectBaseUrl()
37909
38750
  );
@@ -39643,6 +40484,17 @@ function numberValue(value) {
39643
40484
  return typeof value === "number" && Number.isFinite(value) ? value : null;
39644
40485
  }
39645
40486
 
40487
+ // src/cli/tool-connection-status.ts
40488
+ function toolConnectionStatusMessage(input2) {
40489
+ if (input2.credentialStatus === "requires_connection") {
40490
+ return "requires your credentials \u2014 not connected (connect to use)";
40491
+ }
40492
+ if (input2.connected === false && input2.credentialStatus === "managed") {
40493
+ return "temporarily unavailable";
40494
+ }
40495
+ return null;
40496
+ }
40497
+
39646
40498
  // src/cli/commands/tools.ts
39647
40499
  var TOOL_COMMAND_TEMPLATES = {
39648
40500
  describe: "deepline tools describe <toolId>",
@@ -39767,10 +40619,11 @@ function notConnectedSuffix(tool) {
39767
40619
  const record2 = tool;
39768
40620
  const status = stringField2(record2, "credentialStatus", "credential_status");
39769
40621
  const connected = record2.connected;
39770
- if (status === "requires_connection" || connected === false) {
39771
- return " - \u26A0 requires your credentials \u2014 not connected (connect to use)";
39772
- }
39773
- return "";
40622
+ const message = toolConnectionStatusMessage({
40623
+ connected: connected === false ? false : void 0,
40624
+ credentialStatus: status || void 0
40625
+ });
40626
+ return message ? ` - \u26A0 ${message}` : "";
39774
40627
  }
39775
40628
  function shortPricingHint(tool) {
39776
40629
  const pricing = recordField2(
@@ -42320,14 +43173,14 @@ async function handleTransform(id, options) {
42320
43173
  );
42321
43174
  return outcomes.every((o) => o.ok) ? 0 : 1;
42322
43175
  }
42323
- async function handleList2(options) {
43176
+ async function handleList3(options) {
42324
43177
  const limit = options.limit ? Number(options.limit) : void 0;
42325
43178
  const result = await client().listWorkflows({
42326
43179
  limit: Number.isFinite(limit) ? limit : void 0
42327
43180
  });
42328
43181
  emitPassThrough("list", result, options);
42329
43182
  }
42330
- async function handleGet(id, options) {
43183
+ async function handleGet2(id, options) {
42331
43184
  emitPassThrough("get", await client().getWorkflow(id), options);
42332
43185
  }
42333
43186
  async function handleDelete(id, options) {
@@ -42446,12 +43299,12 @@ Notes:
42446
43299
  });
42447
43300
  withJsonOption2(
42448
43301
  workflows.command("list").description("List workspace workflows.").option("--limit <n>", "Max workflows to return")
42449
- ).action(handleList2);
43302
+ ).action(handleList3);
42450
43303
  withJsonOption2(
42451
43304
  workflows.command("get <id>").description(
42452
43305
  "Fetch a workflow, including its published-revision config."
42453
43306
  )
42454
- ).action(handleGet);
43307
+ ).action(handleGet2);
42455
43308
  withJsonOption2(
42456
43309
  workflows.command("disable <id>").description("Turn a workflow off.")
42457
43310
  ).action(handleDisable);
@@ -42504,6 +43357,7 @@ function registerDeeplineCommandGroups(program) {
42504
43357
  registerBillingCommands(program);
42505
43358
  registerMonitorsCommands(program);
42506
43359
  registerOrgCommands(program);
43360
+ registerGitCommands(program);
42507
43361
  registerEnrichCommand(program);
42508
43362
  registerCsvCommands(program);
42509
43363
  registerDbCommands(program);
@@ -42717,97 +43571,6 @@ What changed in ${response.update_summary.version}: ${response.update_summary.su
42717
43571
 
42718
43572
  // src/cli/index.ts
42719
43573
  var PREFLIGHT_TIMEOUT_MS = 3e3;
42720
- var ProjectOrgPinRequiredError = class extends Error {
42721
- code = "PROJECT_ORG_NOT_PINNED";
42722
- exitCode = 3;
42723
- payload;
42724
- constructor(input2) {
42725
- super("Cloud work is blocked because this project uses global host auth.");
42726
- this.name = "ProjectOrgPinRequiredError";
42727
- this.payload = {
42728
- ok: false,
42729
- exitCode: this.exitCode,
42730
- code: this.code,
42731
- message: this.message,
42732
- command: input2.command,
42733
- auth: { scope: "global", source: "host", projectPinned: false },
42734
- project: { dir: input2.projectDir, pinPath: input2.pinPath },
42735
- next: "deepline org set --auth-scope folder"
42736
- };
42737
- }
42738
- };
42739
- function commandUsesOnlyReadOrLocalOperations(command) {
42740
- const [group, action] = command.split(" ");
42741
- if ([
42742
- "auth",
42743
- "org",
42744
- "health",
42745
- "preflight",
42746
- "version",
42747
- "update",
42748
- "skills",
42749
- "doctor",
42750
- "quickstart"
42751
- ].includes(group ?? "")) {
42752
- return true;
42753
- }
42754
- if (group === "plays") {
42755
- return [
42756
- "check",
42757
- "get",
42758
- "list",
42759
- "search",
42760
- "grep",
42761
- "describe",
42762
- "versions"
42763
- ].includes(action ?? "");
42764
- }
42765
- if (group === "runs") {
42766
- return ["get", "list", "tail", "logs", "export"].includes(action ?? "");
42767
- }
42768
- if (group === "tools") {
42769
- return ["list", "search", "get", "describe"].includes(action ?? "");
42770
- }
42771
- if (group === "providers") return ["list", "get"].includes(action ?? "");
42772
- if (group === "secrets") return ["list", "check"].includes(action ?? "");
42773
- if (group === "billing")
42774
- return ["balance", "usage", "history"].includes(action ?? "");
42775
- return false;
42776
- }
42777
- function assertProjectCloudWorkIsPinned(command) {
42778
- if (process.argv.includes("--dry-run") || commandUsesOnlyReadOrLocalOperations(command)) {
42779
- return;
42780
- }
42781
- const config = resolveConfig();
42782
- const provenance = resolveCliAuthProvenance(config);
42783
- if (provenance.scope !== "global" || provenance.project.state !== "project") {
42784
- return;
42785
- }
42786
- throw new ProjectOrgPinRequiredError({
42787
- command,
42788
- projectDir: provenance.project.dir,
42789
- pinPath: provenance.project.pinPath
42790
- });
42791
- }
42792
- function printProjectOrgPinRequiredError(error) {
42793
- if (shouldEmitJson(process.argv.includes("--json"))) {
42794
- printJson(error.payload);
42795
- return;
42796
- }
42797
- const project = error.payload.project;
42798
- process.stderr.write(
42799
- [
42800
- "\u2717 Cloud work is blocked in this project",
42801
- "",
42802
- " Auth: global host default",
42803
- " This project is not pinned. Global auth is shared by every unpinned CLI on this machine.",
42804
- "",
42805
- " Pin this folder to the current target:",
42806
- " deepline org set --auth-scope folder",
42807
- ` This writes: ${project.pinPath}`
42808
- ].join("\n") + "\n"
42809
- );
42810
- }
42811
43574
  function asCommanderError(error) {
42812
43575
  if (!(error instanceof Error) || !("code" in error)) {
42813
43576
  return null;
@@ -43118,7 +43881,6 @@ Exit codes:
43118
43881
  return;
43119
43882
  }
43120
43883
  const compatibilityCommand = compatibilityCommandPath(actionCommand) || actionCommand.name();
43121
- assertProjectCloudWorkIsPinned(compatibilityCommand);
43122
43884
  if (printStartupPhase) {
43123
43885
  progress?.phase("checking sdk compatibility");
43124
43886
  }
@@ -43295,10 +44057,7 @@ Examples:
43295
44057
  });
43296
44058
  progress?.fail();
43297
44059
  const wantsJson = process.argv.includes("--json");
43298
- if (error instanceof ProjectOrgPinRequiredError) {
43299
- printProjectOrgPinRequiredError(error);
43300
- process.exitCode = error.exitCode;
43301
- } else if (commanderError) {
44060
+ if (commanderError) {
43302
44061
  if (commanderError.code === "commander.unknownCommand") {
43303
44062
  }
43304
44063
  process.exitCode = commanderError.code === "commander.unknownCommand" && !wantsJson ? 2 : commanderError.exitCode ?? 1;