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
@@ -890,6 +890,17 @@ function getResolvedProjectAuthSource(baseUrl, apiKey, startDir = process.cwd())
890
890
  return projectBaseUrl === normalizedBaseUrl && (env[API_KEY_ENV] ?? "").trim() === normalizedApiKey;
891
891
  }) ?? null;
892
892
  }
893
+ function resolveBaseUrlOnly(options) {
894
+ const baseUrl = normalizeBaseUrl(
895
+ options?.baseUrl?.trim() || autoDetectBaseUrl()
896
+ );
897
+ if (!baseUrl) {
898
+ throw new ConfigError(
899
+ `Invalid ${HOST_URL_ENV}. Expected an http(s) URL such as https://code.deepline.com.`
900
+ );
901
+ }
902
+ return baseUrl;
903
+ }
893
904
  function resolveConfig(options) {
894
905
  const baseUrl = normalizeBaseUrl(
895
906
  options?.baseUrl?.trim() || autoDetectBaseUrl()
@@ -1199,7 +1210,7 @@ var SDK_RELEASE = {
1199
1210
  // available at toolResponse.rawV2 while toolResponse.raw and all declared
1200
1211
  // getters keep their established compatibility behavior.
1201
1212
  // 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
1202
- version: "0.3.74",
1213
+ version: "0.3.76",
1203
1214
  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.",
1204
1215
  packageCapabilities: {
1205
1216
  updatePreferences: 1
@@ -1621,7 +1632,7 @@ var RUNTIME_INCIDENT_DRILL_CATALOG = [
1621
1632
  valueMeaning: "occurrence"
1622
1633
  },
1623
1634
  expected: {
1624
- outcome: "The same logical run completes through receipt replay; recovery remains bounded if the provider outcome must be retried.",
1635
+ outcome: "The same logical run completes through terminal-cache replay; any provider retry is governed by its separate operation policy.",
1625
1636
  safetyFacts: ["same_logical_run", "bounded_provider_execution"]
1626
1637
  },
1627
1638
  verification: {
@@ -4476,6 +4487,10 @@ var TERMINAL_PLAY_STATUSES = /* @__PURE__ */ new Set(["completed", "failed", "ca
4476
4487
  var INCLUDE_TOOL_METADATA_HEADER = "x-deepline-include-tool-metadata";
4477
4488
  var EXECUTE_RESPONSE_CONTRACT_HEADER = "x-deepline-execute-response-contract";
4478
4489
  var EXECUTE_RESPONSE_INTENT_HEADER = "x-deepline-execute-response-intent";
4490
+ var MONITOR_NON_RETRYABLE_MUTATION_OPTIONS = {
4491
+ maxRetries: 0,
4492
+ exactUrlOnly: true
4493
+ };
4479
4494
  var RAW_V2_EXECUTE_RESPONSE_CONTRACT = RAW_V2_TOOL_RESPONSE_CONTRACT;
4480
4495
  var COMPILE_MANIFEST_RETRY_DELAYS_MS = [250, 1e3];
4481
4496
  var REGISTER_PLAY_ARTIFACTS_COMPILE_CONCURRENCY = 3;
@@ -5034,11 +5049,15 @@ var DeeplineClient = class {
5034
5049
  update: (key, patch) => this.updateMonitor(key, patch),
5035
5050
  delete: (key, options2) => this.deleteMonitor(key, options2),
5036
5051
  reactivate: (key, options2) => this.reactivateMonitor(key, options2),
5052
+ audit: (options2) => this.auditMonitors(options2),
5053
+ repair: (options2) => this.repairMonitors(options2),
5054
+ health: (options2) => this.readMonitorsHealth(options2),
5037
5055
  fleets: {
5038
5056
  sync: (definitionOrId, options2) => this.syncMonitorFleet(definitionOrId, options2),
5039
5057
  get: (fleetId, options2) => fleetId === void 0 ? this.listMonitorFleets() : this.getMonitorFleet(fleetId, options2),
5040
5058
  list: () => this.listMonitorFleets(),
5041
5059
  deactivate: (fleetId, options2) => this.deactivateMonitorFleet(fleetId, options2),
5060
+ reactivate: (fleetId, options2) => this.reactivateMonitorFleet(fleetId, options2),
5042
5061
  waitForConvergence: (fleetId, options2) => this.waitForMonitorFleetConvergence(fleetId, options2)
5043
5062
  }
5044
5063
  };
@@ -6624,13 +6643,23 @@ var DeeplineClient = class {
6624
6643
  if (options?.grep?.trim()) {
6625
6644
  params.set("grep", options.grep.trim());
6626
6645
  params.set("grep_mode", options.grepMode ?? "all");
6646
+ params.set("grep_paginated", "1");
6627
6647
  params.set("limit", "60");
6628
6648
  }
6629
- const suffix = params.toString() ? `?${params.toString()}` : "";
6630
- const response = await this.http.get(
6631
- `/api/v2/plays${suffix}`
6632
- );
6633
- return response.plays ?? [];
6649
+ const plays = [];
6650
+ let cursor = null;
6651
+ let hasMore = true;
6652
+ do {
6653
+ if (cursor) params.set("cursor", cursor);
6654
+ const suffix = params.toString() ? `?${params.toString()}` : "";
6655
+ const response = await this.http.get(
6656
+ `/api/v2/plays${suffix}`
6657
+ );
6658
+ plays.push(...response.plays ?? []);
6659
+ cursor = response.pagination?.cursor ?? response.cursor ?? null;
6660
+ hasMore = Boolean(response.pagination?.hasMore ?? response.hasMore);
6661
+ } while (Boolean(options?.grep?.trim()) && hasMore && cursor);
6662
+ return plays;
6634
6663
  }
6635
6664
  /** Set whether an org-owned Play sorts before unpinned Plays. */
6636
6665
  async setPlayPinned(playName, pinned) {
@@ -7207,6 +7236,44 @@ var DeeplineClient = class {
7207
7236
  ...typeof payload.reason === "string" && payload.reason.trim() ? { reason: payload.reason.trim() } : {}
7208
7237
  };
7209
7238
  }
7239
+ /**
7240
+ * One bounded audit pass. Prefer `client.monitors.audit(...)`.
7241
+ *
7242
+ * Never auto-retried: it is idempotent, but a retry that races the caller's
7243
+ * own next pass would spend a provider slot to learn nothing new.
7244
+ */
7245
+ async auditMonitors(options) {
7246
+ return this.http.request("/api/v2/monitors/audit", {
7247
+ method: "POST",
7248
+ body: {
7249
+ ...options?.fleetId ? { fleet_id: options.fleetId } : {},
7250
+ ...options?.cursor ? { cursor: options.cursor } : {}
7251
+ },
7252
+ maxRetries: 0
7253
+ });
7254
+ }
7255
+ /** One repair pass or plan. Prefer `client.monitors.repair(...)`. */
7256
+ async repairMonitors(options) {
7257
+ return this.http.request("/api/v2/monitors/repair", {
7258
+ method: "POST",
7259
+ body: {
7260
+ ...options?.fleetId ? { fleet_id: options.fleetId } : {},
7261
+ ...options?.dryRun === void 0 ? {} : { dry_run: options.dryRun }
7262
+ },
7263
+ maxRetries: 0
7264
+ });
7265
+ }
7266
+ /** Delivery and convergence health. Prefer `client.monitors.health(...)`. */
7267
+ async readMonitorsHealth(options) {
7268
+ const params = new URLSearchParams();
7269
+ if (options?.fleetId) params.set("fleet_id", options.fleetId);
7270
+ const query = params.toString();
7271
+ const suffix = query ? `?${query}` : "";
7272
+ return this.http.request(
7273
+ `/api/v2/monitors/health${suffix}`,
7274
+ { method: "GET" }
7275
+ );
7276
+ }
7210
7277
  /**
7211
7278
  * The deployable monitor tools catalog. Pass a tool id (positional or
7212
7279
  * `{ tool }`) to describe one tool's full payload/stream contract, or no tool
@@ -7284,7 +7351,6 @@ var DeeplineClient = class {
7284
7351
  if (options?.limit !== void 0)
7285
7352
  params.set("limit", String(options.limit));
7286
7353
  if (options?.cursor) params.set("cursor", options.cursor);
7287
- if (options?.compact) params.set("compact", "true");
7288
7354
  if (options?.includeConsumers) params.set("include_consumers", "true");
7289
7355
  const query = params.toString();
7290
7356
  const suffix = query ? `?${query}` : "";
@@ -7301,13 +7367,22 @@ var DeeplineClient = class {
7301
7367
  );
7302
7368
  }
7303
7369
  async testMonitorWebhook(key, payload, options) {
7370
+ if (options?.dispatch === true || options?.validationOnly === false) {
7371
+ throw new DeeplineError(
7372
+ "Monitor tests are validation-only and cannot dispatch events.",
7373
+ void 0,
7374
+ "MONITOR_TEST_DISPATCH_NOT_SUPPORTED"
7375
+ );
7376
+ }
7304
7377
  return this.http.request(
7305
7378
  `/api/v2/monitors/deployed/${encodeURIComponent(key)}/test`,
7306
7379
  {
7307
7380
  method: "POST",
7308
7381
  body: {
7309
7382
  payload,
7310
- ...options?.validationOnly ? { mode: "validation_only" } : options?.dispatch ? { mode: "dispatch" } : {}
7383
+ // Send the legacy safe mode as well as accepting it server-side: an
7384
+ // upgraded SDK must be safe when it reaches a still-running server.
7385
+ mode: "validation_only"
7311
7386
  }
7312
7387
  }
7313
7388
  );
@@ -7335,7 +7410,14 @@ var DeeplineClient = class {
7335
7410
  async updateMonitor(key, patch) {
7336
7411
  return this.http.request(
7337
7412
  `/api/v2/monitors/deployed/${encodeURIComponent(key)}`,
7338
- { method: "PATCH", body: patch }
7413
+ {
7414
+ method: "PATCH",
7415
+ body: patch,
7416
+ // A monitor write may have reached the control plane before a network
7417
+ // failure reaches the caller. Do not turn that unknown outcome into a
7418
+ // second mutation with a fresh snapshot.
7419
+ ...MONITOR_NON_RETRYABLE_MUTATION_OPTIONS
7420
+ }
7339
7421
  );
7340
7422
  }
7341
7423
  /** Delete a deployed monitor and its upstream provider resource. `dryRun` returns the delete plan. Prefer `client.monitors.delete(...)`. */
@@ -7352,7 +7434,12 @@ var DeeplineClient = class {
7352
7434
  const query = params.toString();
7353
7435
  return this.http.request(
7354
7436
  `/api/v2/monitors/deployed/${encodeURIComponent(key)}${query ? `?${query}` : ""}`,
7355
- { method: "DELETE" }
7437
+ options?.dryRun ? { method: "DELETE" } : {
7438
+ method: "DELETE",
7439
+ // Deletion is a provider lifecycle operation. A timeout is an
7440
+ // unknown outcome, not authority to begin another delete attempt.
7441
+ ...MONITOR_NON_RETRYABLE_MUTATION_OPTIONS
7442
+ }
7356
7443
  );
7357
7444
  }
7358
7445
  /**
@@ -7363,7 +7450,13 @@ var DeeplineClient = class {
7363
7450
  const query = options?.dryRun ? "?dry_run=true" : "";
7364
7451
  return this.http.request(
7365
7452
  `/api/v2/monitors/deployed/${encodeURIComponent(key)}/reactivate${query}`,
7366
- { method: "POST", body: {} }
7453
+ options?.dryRun ? { method: "POST", body: {} } : {
7454
+ method: "POST",
7455
+ body: {},
7456
+ // Reactivation can create an upstream resource, so it must not use
7457
+ // the generic transport's automatic replay policy.
7458
+ ...MONITOR_NON_RETRYABLE_MUTATION_OPTIONS
7459
+ }
7367
7460
  );
7368
7461
  }
7369
7462
  // ——————————————————————————————————————————————————————————
@@ -7440,6 +7533,21 @@ var DeeplineClient = class {
7440
7533
  }
7441
7534
  );
7442
7535
  }
7536
+ async reactivateMonitorFleet(fleetId, options) {
7537
+ return this.http.request(
7538
+ `${this.monitorFleetPath(fleetId)}/reactivate`,
7539
+ {
7540
+ method: "POST",
7541
+ body: {},
7542
+ headers: this.monitorFleetHeaders(
7543
+ "reactivate",
7544
+ options?.idempotencyKey
7545
+ ),
7546
+ maxRetries: 0,
7547
+ exactUrlOnly: true
7548
+ }
7549
+ );
7550
+ }
7443
7551
  /**
7444
7552
  * Poll one fleet until the server reports a terminal status.
7445
7553
  *
@@ -8346,6 +8454,7 @@ function printCommandEnvelope(envelope, options = {}) {
8346
8454
  var EXIT_OK = 0;
8347
8455
  var EXIT_AUTH = 3;
8348
8456
  var EXIT_SERVER = 5;
8457
+ var AUTH_HTTP_TIMEOUT_MS = 1e4;
8349
8458
  function statusBannerLine(value) {
8350
8459
  if (!value || typeof value !== "object" || Array.isArray(value)) return null;
8351
8460
  const banner = value;
@@ -8512,30 +8621,37 @@ async function httpJson(method, url, apiKey, body) {
8512
8621
  if (apiKey) headers["Authorization"] = `Bearer ${apiKey}`;
8513
8622
  const bypassToken = process.env.VERCEL_PROTECTION_BYPASS_TOKEN?.trim();
8514
8623
  if (bypassToken) headers["x-vercel-protection-bypass"] = bypassToken;
8515
- let response = null;
8516
8624
  let lastError = null;
8517
8625
  for (const candidateUrl of buildCandidateUrls2(url)) {
8626
+ const controller = new AbortController();
8627
+ let requestTimedOut = false;
8628
+ const timeout = setTimeout(() => {
8629
+ requestTimedOut = true;
8630
+ controller.abort();
8631
+ }, AUTH_HTTP_TIMEOUT_MS);
8518
8632
  try {
8519
- response = await fetch(candidateUrl, {
8633
+ const response = await fetch(candidateUrl, {
8520
8634
  method,
8521
8635
  headers,
8522
- body: body !== void 0 ? JSON.stringify(body) : void 0
8636
+ body: body !== void 0 ? JSON.stringify(body) : void 0,
8637
+ signal: controller.signal
8523
8638
  });
8524
- break;
8639
+ let data;
8640
+ try {
8641
+ data = await response.json();
8642
+ } catch (error) {
8643
+ if (controller.signal.aborted) throw error;
8644
+ data = {};
8645
+ }
8646
+ return { status: response.status, data };
8525
8647
  } catch (error) {
8526
8648
  lastError = error;
8649
+ if (requestTimedOut && method !== "GET") break;
8650
+ } finally {
8651
+ clearTimeout(timeout);
8527
8652
  }
8528
8653
  }
8529
- if (!response) {
8530
- throw lastError instanceof Error ? lastError : new Error(String(lastError));
8531
- }
8532
- let data;
8533
- try {
8534
- data = await response.json();
8535
- } catch {
8536
- data = {};
8537
- }
8538
- return { status: response.status, data };
8654
+ throw lastError instanceof Error ? lastError : new Error(String(lastError));
8539
8655
  }
8540
8656
  async function reportSetupCompleted(input2) {
8541
8657
  const apiKey = input2.authScope === "folder" ? resolveProjectApiKeyForBaseUrl(input2.baseUrl) : resolveGlobalApiKeyForBaseUrl(input2.baseUrl);
@@ -9034,6 +9150,12 @@ async function handleStatus(args) {
9034
9150
  ...payload.workspace.name ? [`Workspace: ${payload.workspace.name}`] : [],
9035
9151
  ...payload.workspace.slug ? [`Workspace slug: ${payload.workspace.slug}`] : [],
9036
9152
  ...payload.workspace.id != null ? [`Org ID: ${payload.workspace.id}`] : [],
9153
+ // Switching orgs lives under `deepline org`, but this is where
9154
+ // people look when they discover they are in the wrong
9155
+ // workspace. Without the pointer the reasonable next move is
9156
+ // `deepline auth register`, which re-approves the same account
9157
+ // and leaves the active org unchanged.
9158
+ "Switch workspace: deepline org list, then deepline org set <org-id>",
9037
9159
  ...payload.user.id != null ? [`User ID: ${payload.user.id}`] : [],
9038
9160
  ...payload.examples.length > 0 ? [
9039
9161
  "Examples:",
@@ -9065,8 +9187,16 @@ Notes:
9065
9187
  opening the approval page in Cowork. Use --wait no in CI or agent runs, then
9066
9188
  finish with deepline auth wait.
9067
9189
  Auth status shows the target host and active workspace without printing secrets.
9190
+ Registering again re-approves the same account; it does not change the active
9191
+ workspace. To switch, use deepline org list and deepline org set <org-id>.
9068
9192
  `
9069
9193
  );
9194
+ auth.command("workspaces").description("Deprecated. Use deepline org list to see workspaces.").action(() => {
9195
+ console.error(
9196
+ "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."
9197
+ );
9198
+ process.exitCode = 1;
9199
+ });
9070
9200
  auth.command("register").description(
9071
9201
  "Register this device and open the approval page in your browser."
9072
9202
  ).addHelpText(
@@ -9311,6 +9441,18 @@ function billingTopUpFailureFromError(error, input2) {
9311
9441
  }
9312
9442
  return null;
9313
9443
  }
9444
+ function normalizeUnixMilliseconds(value) {
9445
+ const timestamp = Math.floor(value);
9446
+ return Number.isFinite(timestamp) && timestamp >= 0 && Number.isFinite(new Date(timestamp).getTime()) ? timestamp : null;
9447
+ }
9448
+ function parseSince(raw) {
9449
+ if (!raw?.trim()) return null;
9450
+ const numeric = Number(raw);
9451
+ const normalizedNumeric = normalizeUnixMilliseconds(numeric);
9452
+ if (normalizedNumeric !== null) return normalizedNumeric;
9453
+ const parsed = Date.parse(raw);
9454
+ return normalizeUnixMilliseconds(parsed);
9455
+ }
9314
9456
  function humanize(value) {
9315
9457
  return String(value || "").split("_").filter(Boolean).map((token) => token[0]?.toUpperCase() + token.slice(1)).join(" ") || "Unknown";
9316
9458
  }
@@ -9596,6 +9738,18 @@ async function handleHistory(options) {
9596
9738
  );
9597
9739
  }
9598
9740
  async function handleLedgerExportAll(options) {
9741
+ const sinceAt = parseSince(options.since);
9742
+ if (options.since && sinceAt === null) {
9743
+ reportBillingFailure(
9744
+ {
9745
+ exitCode: 2,
9746
+ code: "INVALID_SINCE",
9747
+ message: "--since must be an ISO-8601 timestamp or Unix milliseconds."
9748
+ },
9749
+ options
9750
+ );
9751
+ return;
9752
+ }
9599
9753
  const { http } = getAuthedHttpClient();
9600
9754
  const outputPath = options.output ? resolve3(String(options.output)) : defaultLedgerExportPath();
9601
9755
  let summary = { row_count: 0, net_delta_credits: 0 };
@@ -9605,6 +9759,8 @@ async function handleLedgerExportAll(options) {
9605
9759
  const params = new URLSearchParams({ limit: "5000" });
9606
9760
  if (cursor !== null) params.set("cursor", cursor);
9607
9761
  if (options.runId) params.set("run_id", options.runId);
9762
+ if (options.operation) params.set("operation", options.operation);
9763
+ if (sinceAt !== null) params.set("since_at", String(sinceAt));
9608
9764
  const payload = await http.get(
9609
9765
  `/api/v2/billing/ledger?${params.toString()}`
9610
9766
  );
@@ -9633,13 +9789,15 @@ async function handleLedgerExportAll(options) {
9633
9789
  net_delta_credits: summary.net_delta_credits,
9634
9790
  scope: "workspace",
9635
9791
  ...options.runId ? { run_id: options.runId } : {},
9792
+ ...options.operation ? { operation: options.operation } : {},
9793
+ ...sinceAt !== null ? { since_at: sinceAt } : {},
9636
9794
  render: {
9637
9795
  sections: [
9638
9796
  {
9639
9797
  title: "billing ledger",
9640
9798
  lines: [
9641
9799
  `Billing ledger written to ${outputPath}`,
9642
- `${summary.row_count} row(s) exported for the active workspace${options.runId ? ` and run ${options.runId}` : ""}.`,
9800
+ `${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()}` : ""}.`,
9643
9801
  `Net ledger delta: ${summary.net_delta_credits} Deepline Credits`
9644
9802
  ]
9645
9803
  }
@@ -10336,6 +10494,7 @@ Examples:
10336
10494
  deepline billing ledger export all
10337
10495
  deepline billing ledger export all --output ./ledger.csv
10338
10496
  deepline billing ledger export all --run-id play/demo/run/abc123
10497
+ deepline billing ledger export all --operation limadata_find_audience_identifiers --since 2026-09-01T00:00:00Z
10339
10498
  deepline billing ledger export all --json
10340
10499
  `
10341
10500
  ).addCommand(
@@ -10357,7 +10516,10 @@ Examples:
10357
10516
  deepline billing ledger export all
10358
10517
  deepline billing ledger export all --json
10359
10518
  `
10360
- ).option("--output <path>", "Write CSV to an explicit path").option("--run-id <run_id>", "Export ledger rows for one play run.").option(
10519
+ ).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(
10520
+ "--since <timestamp>",
10521
+ "Only export rows since ISO-8601 time or Unix milliseconds."
10522
+ ).option(
10361
10523
  "--json",
10362
10524
  "Emit JSON output. Also automatic when stdout is piped"
10363
10525
  ).action(handleLedgerExportAll)
@@ -16696,7 +16858,7 @@ async function traceCliSpan(phase, fields, run) {
16696
16858
  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.";
16697
16859
  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()`.";
16698
16860
  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.";
16699
- 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.";
16861
+ 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.";
16700
16862
  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.";
16701
16863
  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.";
16702
16864
  function sourceLineForError(sourceCode, error) {
@@ -32538,7 +32700,7 @@ function renderDeployedListText(payload, requestedStatus) {
32538
32700
  return status && count !== void 0 ? [`${status}: ${count}`] : [];
32539
32701
  }).join(" ") : "";
32540
32702
  if (summary) lines.push(`All lifecycle states: ${summary}`);
32541
- if (payload.is_truncated === true) {
32703
+ if (payload.has_more === true || payload.is_truncated === true) {
32542
32704
  const nextCursor = asString(payload.next_cursor);
32543
32705
  lines.push(
32544
32706
  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:',
@@ -32552,11 +32714,15 @@ function renderDeployedListText(payload, requestedStatus) {
32552
32714
  `;
32553
32715
  }
32554
32716
  async function handleMonitorsList(options) {
32717
+ if (options.compact) {
32718
+ process.stderr.write(
32719
+ "`--compact` is deprecated and now does nothing; returning the complete monitor records.\n"
32720
+ );
32721
+ }
32555
32722
  const payload = await new DeeplineClient().monitors.list({
32556
32723
  ...options.status ? { status: options.status } : {},
32557
32724
  ...options.limit ? { limit: options.limit } : {},
32558
32725
  ...options.cursor ? { cursor: options.cursor } : {},
32559
- ...options.compact ? { compact: true } : {},
32560
32726
  ...options.includeConsumers ? { includeConsumers: true } : {}
32561
32727
  });
32562
32728
  printCommandEnvelope(payload, {
@@ -32667,6 +32833,10 @@ var MONITOR_FLEET_COMMANDS = [
32667
32833
  {
32668
32834
  name: "deactivate",
32669
32835
  summary: "Deactivate a fleet and the monitors it owns."
32836
+ },
32837
+ {
32838
+ name: "reactivate",
32839
+ summary: "Explicitly recreate a fleet after a credit-triggered suspension."
32670
32840
  }
32671
32841
  ];
32672
32842
  var MONITOR_FLEET_AGENT_NOTES = [
@@ -33169,6 +33339,72 @@ async function handleMonitorFleetsGet(fleetId, options) {
33169
33339
  { json: options.json, text }
33170
33340
  );
33171
33341
  }
33342
+ function fleetReactivateCommandLine(fleetId, options) {
33343
+ const parts = [
33344
+ "deepline",
33345
+ "monitors",
33346
+ "fleets",
33347
+ "reactivate",
33348
+ fleetShellArg(fleetId),
33349
+ "--yes"
33350
+ ];
33351
+ if (options.wait) parts.push("--wait");
33352
+ if (options.timeout)
33353
+ parts.push(`--timeout ${fleetShellArg(options.timeout)}`);
33354
+ if (options.idempotencyKey)
33355
+ parts.push(`--idempotency-key ${fleetShellArg(options.idempotencyKey)}`);
33356
+ parts.push(...fleetJsonFlag(options));
33357
+ return parts.join(" ");
33358
+ }
33359
+ async function handleMonitorFleetsReactivate(fleetId, options, idempotencyKey) {
33360
+ if (!options.yes) {
33361
+ throw new MonitorsUsageError(
33362
+ `reactivate can recreate every suspended provider monitor and restart lifecycle billing. Confirm with --yes:
33363
+ ${fleetReactivateCommandLine(fleetId, options)}`
33364
+ );
33365
+ }
33366
+ const client2 = new DeeplineClient();
33367
+ const payload = await client2.monitors.fleets.reactivate(fleetId, {
33368
+ idempotencyKey
33369
+ });
33370
+ const accepted = { ...payload, idempotency_key: idempotencyKey };
33371
+ if (!options.wait) {
33372
+ printCommandEnvelope(accepted, {
33373
+ json: options.json,
33374
+ text: `Fleet ${fleetId} \u2014 ${asString(payload.status) ?? "billing_reactivating"}
33375
+ idempotency key ${idempotencyKey}
33376
+ `
33377
+ });
33378
+ return;
33379
+ }
33380
+ const timeoutMs = fleetTimeoutMs(options.timeout);
33381
+ const progress = fleetProgressReporter();
33382
+ let final;
33383
+ try {
33384
+ final = await client2.monitors.fleets.waitForConvergence(fleetId, {
33385
+ timeoutMs,
33386
+ pollIntervalMs: FLEET_POLL_INTERVAL_MS,
33387
+ onProgress: progress.report
33388
+ });
33389
+ } finally {
33390
+ progress.finish();
33391
+ }
33392
+ const envelope = { ...accepted, ...final };
33393
+ const text = renderFleetGet(final);
33394
+ if (fleetStatus(final) === "converged") {
33395
+ printCommandEnvelope(envelope, { json: options.json, text });
33396
+ return;
33397
+ }
33398
+ reportFleetState(
33399
+ envelope,
33400
+ new MonitorFleetStateError({
33401
+ code: "MONITOR_FLEET_WAIT_TIMEOUT",
33402
+ message: `Stopped waiting after ${timeoutMs}ms. Fleet ${fleetId} recovery is still in progress on the server.`,
33403
+ next: fleetServerNext(final) ?? `deepline monitors fleets get ${fleetShellArg(fleetId)} --json`
33404
+ }),
33405
+ { json: options.json, text }
33406
+ );
33407
+ }
33172
33408
  function fleetDeactivateCommandLine(fleetId, options) {
33173
33409
  const parts = [
33174
33410
  "deepline monitors fleets deactivate",
@@ -33466,18 +33702,11 @@ async function handleMonitorsGet(key, options) {
33466
33702
  }
33467
33703
  async function handleMonitorsTest(key, payload, options) {
33468
33704
  const explicitPayload = parseJsonObjectArg(payload, "<payload>");
33469
- const result = await new DeeplineClient().monitors.test(
33470
- key,
33471
- explicitPayload,
33472
- {
33473
- validationOnly: options.dispatch !== true,
33474
- dispatch: options.dispatch === true
33475
- }
33476
- );
33477
- const dispatch = options.dispatch === true;
33705
+ const result = await new DeeplineClient().monitors.test(key, explicitPayload);
33478
33706
  const text = `Monitor diagnostic for ${key}: ${result.accepted === true ? "accepted" : "rejected"}
33479
- ` + (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}
33480
- ${dispatch ? "dispatched" : "would dispatch"} bound Plays: ${asFiniteNumber(result.dispatched_bound_plays) ?? 0}
33707
+ mode: validation_only (no rows written, credits spent, or Plays dispatched)
33708
+ persisted rows: ${asFiniteNumber(result.persisted_rows) ?? 0}
33709
+ dispatched bound Plays: ${asFiniteNumber(result.dispatched_bound_plays) ?? 0}
33481
33710
  `;
33482
33711
  printCommandEnvelope(result, { json: options.json, text });
33483
33712
  }
@@ -33557,6 +33786,206 @@ async function handleMonitorsReactivate(key, options) {
33557
33786
  const payload = await client2.monitors.reactivate(key);
33558
33787
  printCommandEnvelope(payload, { json: options.json });
33559
33788
  }
33789
+ var MONITOR_VERB_POLL_INTERVAL_MS = 2e3;
33790
+ function monitorHealthLine(health) {
33791
+ return [
33792
+ `converged ${health.converged}/${health.scanned}`,
33793
+ `needs_repair ${health.needs_repair}`,
33794
+ `missing ${health.observed.missing}`,
33795
+ `unaudited ${health.observed.unknown + health.observed.unset}`,
33796
+ `silent ${health.silent}`
33797
+ ].join(" \xB7 ");
33798
+ }
33799
+ function monitorVerbProgressReporter() {
33800
+ const interactive = process.stderr.isTTY === true;
33801
+ let wrote = false;
33802
+ let lastPlainAt = 0;
33803
+ return {
33804
+ report: (health) => {
33805
+ const line = monitorHealthLine(health);
33806
+ if (interactive) {
33807
+ process.stderr.write(`\r\x1B[2K${line}`);
33808
+ wrote = true;
33809
+ return;
33810
+ }
33811
+ const now = Date.now();
33812
+ if (wrote && now - lastPlainAt < FLEET_PLAIN_PROGRESS_INTERVAL_MS) return;
33813
+ lastPlainAt = now;
33814
+ wrote = true;
33815
+ process.stderr.write(`${line}
33816
+ `);
33817
+ },
33818
+ finish: () => {
33819
+ if (interactive && wrote) process.stderr.write("\n");
33820
+ }
33821
+ };
33822
+ }
33823
+ async function watchMonitorHealth(input2) {
33824
+ const deadlineAt = Date.now() + input2.timeoutMs;
33825
+ const scope = input2.fleetId ? { fleetId: input2.fleetId } : {};
33826
+ let last = await input2.client.monitors.health(scope);
33827
+ input2.onProgress(last);
33828
+ while (Date.now() < deadlineAt) {
33829
+ if (last.needs_repair === 0 && last.observed.unknown === 0) return last;
33830
+ await new Promise(
33831
+ (resolve21) => setTimeout(resolve21, MONITOR_VERB_POLL_INTERVAL_MS)
33832
+ );
33833
+ last = await input2.client.monitors.health(scope);
33834
+ input2.onProgress(last);
33835
+ }
33836
+ return last;
33837
+ }
33838
+ function monitorHealthText(health) {
33839
+ const partial = health.truncated ? " (partial \u2014 scope larger than one read)" : "";
33840
+ const lines = [
33841
+ `scope: ${health.scope.fleet_id ?? "workspace"}${partial}`,
33842
+ monitorHealthLine(health)
33843
+ ];
33844
+ if (health.deactivation_reasons.length > 0) {
33845
+ lines.push("");
33846
+ lines.push("deactivated by Deepline:");
33847
+ for (const entry of health.deactivation_reasons) {
33848
+ const how = entry.resolution ? ` \u2014 ${entry.resolution}` : "";
33849
+ lines.push(` ${entry.reason} (${entry.count})${how}`);
33850
+ }
33851
+ }
33852
+ if (health.worst_offenders.length > 0) {
33853
+ lines.push("");
33854
+ lines.push(
33855
+ `silent longest (no delivery in ${health.silent_window_days}d):`
33856
+ );
33857
+ for (const entry of health.worst_offenders) {
33858
+ const when = entry.last_event_at === null ? "never" : new Date(entry.last_event_at).toISOString();
33859
+ lines.push(` ${entry.monitor_key} ${entry.tool} last event ${when}`);
33860
+ }
33861
+ }
33862
+ return `${lines.join("\n")}
33863
+ `;
33864
+ }
33865
+ async function handleMonitorsAudit(options) {
33866
+ const client2 = new DeeplineClient();
33867
+ const fleetId = options.fleet?.trim() || void 0;
33868
+ const scope = fleetId ? { fleetId } : {};
33869
+ let result = await client2.monitors.audit(scope);
33870
+ const passes = [result.audit];
33871
+ while (result.audit.cursor !== null) {
33872
+ result = await client2.monitors.audit({
33873
+ ...scope,
33874
+ cursor: result.audit.cursor
33875
+ });
33876
+ passes.push(result.audit);
33877
+ }
33878
+ const totals = passes.reduce(
33879
+ (sum, pass) => ({
33880
+ scanned: sum.scanned + pass.scanned,
33881
+ asked: sum.asked + pass.asked,
33882
+ stale: sum.stale + pass.stale,
33883
+ missing: sum.missing + pass.observed.missing
33884
+ }),
33885
+ { scanned: 0, asked: 0, stale: 0, missing: 0 }
33886
+ );
33887
+ let health = result.health;
33888
+ if (options.watch) {
33889
+ const progress = monitorVerbProgressReporter();
33890
+ try {
33891
+ health = await watchMonitorHealth({
33892
+ client: client2,
33893
+ ...scope,
33894
+ timeoutMs: fleetTimeoutMs(options.timeout),
33895
+ onProgress: progress.report
33896
+ });
33897
+ } finally {
33898
+ progress.finish();
33899
+ }
33900
+ }
33901
+ const unauditable = result.audit.unauditable_capabilities;
33902
+ const overtaken = totals.stale > 0 ? ` \xB7 ${totals.stale} observations overtaken by a concurrent settle` : "";
33903
+ const text = [
33904
+ `audited ${totals.scanned} monitors \xB7 asked the provider about ${totals.asked}`,
33905
+ `missing ${totals.missing}${overtaken}`,
33906
+ ...unauditable.length > 0 ? [`not auditable (no batch-read contract): ${unauditable.join(", ")}`] : [],
33907
+ "",
33908
+ monitorHealthText(health)
33909
+ ].join("\n");
33910
+ printCommandEnvelope(
33911
+ { ...result, audit: { ...result.audit, totals }, health },
33912
+ { json: options.json, text }
33913
+ );
33914
+ }
33915
+ async function handleMonitorsRepair(options) {
33916
+ const client2 = new DeeplineClient();
33917
+ const fleetId = options.fleet?.trim() || void 0;
33918
+ const scope = fleetId ? { fleetId } : {};
33919
+ const result = await client2.monitors.repair({
33920
+ ...scope,
33921
+ ...options.dryRun ? { dryRun: true } : {}
33922
+ });
33923
+ if (options.dryRun) {
33924
+ assertMonitorDryRunAcknowledged(
33925
+ result,
33926
+ { command: "monitors repair", mutation: "repair" }
33927
+ );
33928
+ }
33929
+ let health = result.health;
33930
+ if (options.watch && !options.dryRun) {
33931
+ const progress = monitorVerbProgressReporter();
33932
+ try {
33933
+ health = await watchMonitorHealth({
33934
+ client: client2,
33935
+ ...scope,
33936
+ timeoutMs: fleetTimeoutMs(options.timeout),
33937
+ onProgress: progress.report
33938
+ });
33939
+ } finally {
33940
+ progress.finish();
33941
+ }
33942
+ }
33943
+ const verb = options.dryRun ? "would queue" : "queued";
33944
+ const lines = [
33945
+ `${verb} ${result.repair.queued} of ${result.repair.scanned} monitors`
33946
+ ];
33947
+ for (const item of result.repair.plan.slice(0, REPAIR_PLAN_PREVIEW)) {
33948
+ const why = item.deactivation_reason ? ` \xB7 ${item.deactivation_reason}` : "";
33949
+ lines.push(
33950
+ ` ${item.action.padEnd(6)} ${item.monitor_key} desired ${item.desired} \xB7 observed ${item.observed}${why}`
33951
+ );
33952
+ }
33953
+ if (result.repair.plan.length > REPAIR_PLAN_PREVIEW) {
33954
+ lines.push(` \u2026 ${result.repair.plan.length - REPAIR_PLAN_PREVIEW} more`);
33955
+ }
33956
+ if (result.repair.unaudited.length > 0) {
33957
+ lines.push(
33958
+ `${result.repair.unaudited.length} monitors have never been observed \u2014 run 'deepline monitors audit' first.`
33959
+ );
33960
+ }
33961
+ if (result.repair.unowned.length > 0) {
33962
+ lines.push(
33963
+ `${result.repair.unowned.length} monitors disagree but no fleet owns them; repair those with 'deepline monitors deploy' or 'deepline monitors delete'.`
33964
+ );
33965
+ }
33966
+ if (result.repair.fenced.length > 0) {
33967
+ lines.push(
33968
+ `${result.repair.fenced.length} monitors have a provider operation in flight; Deepline is finishing those and repair left them alone.`
33969
+ );
33970
+ }
33971
+ lines.push("");
33972
+ lines.push(monitorHealthText(health));
33973
+ printCommandEnvelope(
33974
+ { ...result, health },
33975
+ { json: options.json, text: lines.join("\n") }
33976
+ );
33977
+ }
33978
+ var REPAIR_PLAN_PREVIEW = 20;
33979
+ async function handleMonitorsHealth(options) {
33980
+ const fleetId = options.fleet?.trim() || void 0;
33981
+ const health = await new DeeplineClient().monitors.health(
33982
+ fleetId ? { fleetId } : {}
33983
+ );
33984
+ printCommandEnvelope(health, {
33985
+ json: options.json,
33986
+ text: monitorHealthText(health)
33987
+ });
33988
+ }
33560
33989
  function registerMonitorsCommands(program) {
33561
33990
  const monitors = program.command("monitors").description("Discover, deploy, and manage Deepline monitors.").showSuggestionAfterError(true).addHelpText(
33562
33991
  "after",
@@ -33592,6 +34021,75 @@ Examples:
33592
34021
  deepline monitors reactivate my-monitor --dry-run
33593
34022
  `
33594
34023
  );
34024
+ withJsonOption(
34025
+ monitors.command("audit").description(
34026
+ "Re-read what the provider actually holds for your monitors."
34027
+ ).option("--fleet <fleet-id>", "Audit one fleet instead of every monitor").option("--watch", "Keep polling health until the scope settles").option(
34028
+ "--timeout <duration>",
34029
+ "How long --watch waits, e.g. 90s, 5m, 1h (default 10m)"
34030
+ ).addHelpText(
34031
+ "after",
34032
+ `
34033
+ Notes:
34034
+ Asks the provider, by resource id, what it still holds, and records the answer
34035
+ on each monitor. It changes nothing upstream: no creates, no deletes, no
34036
+ intent. Safe to run at any time, as often as you like \u2014 running it twice is
34037
+ running it once, twice.
34038
+
34039
+ A monitor the provider does not return is recorded "missing". Use
34040
+ 'deepline monitors repair' to act on that.
34041
+
34042
+ Examples:
34043
+ deepline monitors audit
34044
+ deepline monitors audit --fleet accounts-eu --json
34045
+ deepline monitors audit --fleet accounts-eu --watch --timeout 5m
34046
+ `
34047
+ )
34048
+ ).action(monitorsAction(handleMonitorsAudit));
34049
+ withJsonOption(
34050
+ monitors.command("repair").description(
34051
+ "Converge the monitors whose desired and observed states disagree."
34052
+ ).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(
34053
+ "--timeout <duration>",
34054
+ "How long --watch waits, e.g. 90s, 5m, 1h (default 10m)"
34055
+ ).addHelpText(
34056
+ "after",
34057
+ `
34058
+ Notes:
34059
+ Queues the monitors that disagree with the provider onto the same convergence
34060
+ loop a fleet sync uses; the provider work happens on Deepline's own schedule.
34061
+ Idempotent \u2014 the queue IS the disagreement, so a repeat run queues only what
34062
+ is still wrong.
34063
+
34064
+ Monitors nobody has observed are never repaired: run 'deepline monitors audit'
34065
+ first. Monitors no fleet owns are reported rather than queued; deploy or delete
34066
+ those directly.
34067
+
34068
+ Examples:
34069
+ deepline monitors repair --dry-run
34070
+ deepline monitors repair --fleet accounts-eu --watch
34071
+ `
34072
+ )
34073
+ ).action(monitorsAction(handleMonitorsRepair));
34074
+ withJsonOption(
34075
+ monitors.command("health").description("Delivery and convergence health for your monitors.").option(
34076
+ "--fleet <fleet-id>",
34077
+ "Report on one fleet instead of every monitor"
34078
+ ).addHelpText(
34079
+ "after",
34080
+ `
34081
+ Notes:
34082
+ Read-only. Reports how many monitors the provider holds as asked, how many
34083
+ disagree, how many Deepline deactivated and why, and how many are "silent" \u2014
34084
+ the provider holds them but nothing has been delivered recently. The worst
34085
+ offenders are listed longest-quiet first.
34086
+
34087
+ Examples:
34088
+ deepline monitors health
34089
+ deepline monitors health --fleet accounts-eu --json
34090
+ `
34091
+ )
34092
+ ).action(monitorsAction(handleMonitorsHealth));
33595
34093
  withJsonOption(
33596
34094
  monitors.command("status").description("Check whether you have access to Deepline monitors.").addHelpText(
33597
34095
  "after",
@@ -33644,10 +34142,10 @@ Examples:
33644
34142
  `
33645
34143
  Notes:
33646
34144
  Read-only. --status filters by monitor status: active (default), disabled, or
33647
- all. The output echoes the status filter that was applied. --compact returns
33648
- high-signal fields only. The response reports total (the true registry count,
33649
- not the page size), returned, is_truncated, and next_cursor. When is_truncated
33650
- is true, page with --cursor <next_cursor> until it is false \u2014 a "no matching
34145
+ all. The output echoes the status filter that was applied. The response reports
34146
+ total (the true registry count, not the page size), returned, has_more, and
34147
+ next_cursor. When has_more is true, page with --cursor <next_cursor> until it
34148
+ is false \u2014 a "no matching
33651
34149
  monitor" reuse conclusion off a truncated page deploys a duplicate paid feed.
33652
34150
  The default list stays cheap: it includes the current downstream Play binding
33653
34151
  metadata but does not resolve per-monitor delivery/run health. Pass
@@ -33658,7 +34156,6 @@ Examples:
33658
34156
  deepline monitors list
33659
34157
  deepline monitors list --status all --json
33660
34158
  deepline monitors list --status all --cursor <next_cursor> --json
33661
- deepline monitors list --compact --json
33662
34159
  deepline monitors list --include-consumers --limit 20 --json
33663
34160
  `
33664
34161
  ).option(
@@ -33667,7 +34164,10 @@ Examples:
33667
34164
  ).option("--limit <n>", "Limit the number of deployed monitors returned").option(
33668
34165
  "--cursor <cursor>",
33669
34166
  "Page past a truncated result using the next_cursor from a prior list response"
33670
- ).option("--compact", COMPACT_OPTION_DESCRIPTION).option(
34167
+ ).option(
34168
+ "--compact",
34169
+ "Deprecated no-op; complete records are always returned"
34170
+ ).option(
33671
34171
  "--include-consumers",
33672
34172
  "Include current SQL-listener consumer health (requires --limit 20 or fewer)"
33673
34173
  )
@@ -33690,10 +34190,7 @@ Examples:
33690
34190
  ).action(monitorsAction(handleMonitorsGet));
33691
34191
  withJsonOption(
33692
34192
  monitors.command("test <key> <payload>").description(
33693
- "Send an explicit payload through a monitor\u2019s webhook ingestion path."
33694
- ).option(
33695
- "--dispatch",
33696
- "Inject the test event through normal ingestion (writes rows and may dispatch bound Plays)"
34193
+ "Validate an explicit payload against a monitor\u2019s webhook contract."
33697
34194
  ).addHelpText(
33698
34195
  "after",
33699
34196
  `
@@ -33701,9 +34198,8 @@ Notes:
33701
34198
  <payload> must be an explicit JSON object. The command uses the deployed
33702
34199
  monitor\u2019s real binding and payload validation, but is a side-effect-free
33703
34200
  diagnostic: it does not persist rows, spend credits, dispatch Plays, or alter
33704
- monitor state. Pass --dispatch only when you deliberately need the historic
33705
- full-ingestion test event; it can write rows and trigger bound Plays. It does
33706
- not synthesize a provider event or accept an omitted payload.
34201
+ monitor state. It does not synthesize a provider event or accept an omitted
34202
+ payload.
33707
34203
 
33708
34204
  Examples:
33709
34205
  deepline monitors test rb2b-website-visitors '{"LinkedIn URL":"https://www.linkedin.com/in/example","Website":"https://example.com"}' --json
@@ -34020,6 +34516,40 @@ Examples:
34020
34516
  reportMonitorsFailure(error, { retryCommand });
34021
34517
  }
34022
34518
  });
34519
+ withJsonOption(
34520
+ fleets.command("reactivate <fleet-id>").description(
34521
+ "Explicitly recreate a fleet after a credit-triggered suspension."
34522
+ ).addHelpText(
34523
+ "after",
34524
+ `
34525
+ Notes:
34526
+ TAMRadar cannot reactivate a deleted radar. This command starts normal,
34527
+ fenced provider creates from the fleet's retained desired definitions and
34528
+ may restart lifecycle billing. A credit top-up alone never does this.
34529
+
34530
+ Example:
34531
+ deepline monitors fleets reactivate account-job-openings --yes --wait --json
34532
+ `
34533
+ ).option("--wait", "Poll until the fleet reports converged").option(
34534
+ "--timeout <duration>",
34535
+ "How long --wait may poll: 500ms, 90s, 10m, 1h (default 10m)"
34536
+ ).option("--yes", "Confirm recreating suspended provider monitors").option("--idempotency-key <key>", "Stable retry key")
34537
+ ).action(async (fleetId, options) => {
34538
+ let retryCommand = fleetReactivateCommandLine(fleetId, options);
34539
+ try {
34540
+ const idempotencyKey = fleetIdempotencyKey(
34541
+ "reactivate",
34542
+ options.idempotencyKey
34543
+ );
34544
+ retryCommand = fleetReactivateCommandLine(fleetId, {
34545
+ ...options,
34546
+ idempotencyKey
34547
+ });
34548
+ await handleMonitorFleetsReactivate(fleetId, options, idempotencyKey);
34549
+ } catch (error) {
34550
+ reportMonitorsFailure(error, { retryCommand });
34551
+ }
34552
+ });
34023
34553
  const deployed = withJsonOption(
34024
34554
  monitors.command("deployed", { hidden: true }).description("Alias of `monitors list` (plus get/update/delete aliases).").option(
34025
34555
  "--status <status>",
@@ -34027,7 +34557,10 @@ Examples:
34027
34557
  ).option("--limit <n>", "Limit the number of deployed monitors returned").option(
34028
34558
  "--cursor <cursor>",
34029
34559
  "Page past a truncated result using the next_cursor from a prior list response"
34030
- ).option("--compact", COMPACT_OPTION_DESCRIPTION).option(
34560
+ ).option(
34561
+ "--compact",
34562
+ "Deprecated no-op; complete records are always returned"
34563
+ ).option(
34031
34564
  "--include-consumers",
34032
34565
  "Include current SQL-listener consumer health (requires --limit 20 or fewer)"
34033
34566
  )
@@ -34355,11 +34888,13 @@ async function handleOrgStatus(options) {
34355
34888
  host_env_path: hostPath,
34356
34889
  folder_target: folderTargetPayload,
34357
34890
  project_pin: provenance.scope === "global" && provenance.project.state === "project" ? {
34358
- required: true,
34891
+ available: true,
34892
+ required: false,
34359
34893
  path: provenance.project.pinPath,
34360
- cloud_mutations_blocked: true,
34894
+ cloud_mutations_blocked: false,
34361
34895
  command: "deepline org set --auth-scope folder"
34362
34896
  } : {
34897
+ available: false,
34363
34898
  required: false,
34364
34899
  cloud_mutations_blocked: false
34365
34900
  },
@@ -34780,8 +35315,8 @@ Examples:
34780
35315
  Notes:
34781
35316
  Selection can be a list number, exact organization name, or organization id.
34782
35317
  Without a selection, prints choices. With --auth-scope folder while this
34783
- project is using global host auth, it pins the current target directly; this
34784
- is the fastest safe repair for a blocked cloud mutation.
35318
+ project is using global host auth, it pins the current target directly
35319
+ without an additional organization lookup.
34785
35320
 
34786
35321
  Mutates local auth state and asks Deepline for an org-scoped API key. It
34787
35322
  writes only the selected scope:
@@ -34798,7 +35333,9 @@ Notes:
34798
35333
 
34799
35334
  Prefer --auth-scope folder for a repository or customer workspace. Use
34800
35335
  --auth-scope global only for deliberate host-wide interactive defaults; it
34801
- is shared by every unpinned CLI on this machine. For automation, pass
35336
+ is shared by every unpinned CLI on this machine. Global auth remains
35337
+ supported in projects; use a folder pin when you want a project-specific
35338
+ default. For automation, pass
34802
35339
  DEEPLINE_API_KEY only to that invocation and confirm with org status --json.
34803
35340
 
34804
35341
  Use --json for stable fields including effective_auth_scope,
@@ -34841,6 +35378,318 @@ Examples:
34841
35378
  );
34842
35379
  }
34843
35380
 
35381
+ // src/cli/commands/git.ts
35382
+ function renderProject(project) {
35383
+ const root = project.rootDirectory ? ` (${project.rootDirectory})` : "";
35384
+ const flags = [
35385
+ project.disabled ? "unlinked" : "linked",
35386
+ `deploys ${project.productionBranch}`,
35387
+ project.checkOnPullRequest ? "PR checks on" : "PR checks off"
35388
+ ].join(", ");
35389
+ return `${project.id} ${project.repoFullName}${root} - ${flags}`;
35390
+ }
35391
+ function renderDeployment(deployment) {
35392
+ const ref = deployment.ref.replace("refs/heads/", "");
35393
+ const kind = deployment.isProduction ? "production" : deployment.trigger === "pull_request" ? `pr #${deployment.pullRequestNumber ?? "?"}` : deployment.trigger;
35394
+ const suffix = deployment.error ? ` - ${deployment.error.slice(0, 80)}` : "";
35395
+ return `${deployment.id} ${deployment.commitSha.slice(0, 10)} ${ref} (${kind}) - ${deployment.status}${suffix}`;
35396
+ }
35397
+ async function handleList(options) {
35398
+ const { http } = getAuthedHttpClient();
35399
+ const payload = await http.get(
35400
+ `/api/v2/play-projects${options.all ? "?includeDisabled=1" : ""}`
35401
+ );
35402
+ printCommandEnvelope(
35403
+ {
35404
+ projects: payload.projects,
35405
+ count: payload.projects.length,
35406
+ render: {
35407
+ sections: [
35408
+ {
35409
+ title: "linked repositories",
35410
+ lines: payload.projects.length ? payload.projects.map(renderProject) : [
35411
+ "No repositories are linked. Run `deepline git repos` to see what the GitHub installation can reach, then `deepline git link`."
35412
+ ]
35413
+ }
35414
+ ]
35415
+ }
35416
+ },
35417
+ { json: options.json }
35418
+ );
35419
+ }
35420
+ async function handleRepos(options) {
35421
+ const { http } = getAuthedHttpClient();
35422
+ const query = options.installation ? `?installationId=${encodeURIComponent(options.installation)}` : "";
35423
+ const payload = await http.get(`/api/v2/github/repos${query}`);
35424
+ printCommandEnvelope(
35425
+ {
35426
+ installation: payload.installation,
35427
+ repositories: payload.repositories,
35428
+ count: payload.repositories.length,
35429
+ render: {
35430
+ sections: [
35431
+ {
35432
+ title: `repos on installation @${payload.installation.accountLogin} (${payload.installation.repositorySelection})`,
35433
+ lines: payload.repositories.map(
35434
+ (repo) => `${repo.repoId} ${repo.fullName} (default: ${repo.defaultBranch}${repo.private ? ", private" : ""}${repo.fork ? ", fork" : ""})`
35435
+ )
35436
+ }
35437
+ ]
35438
+ }
35439
+ },
35440
+ { json: options.json }
35441
+ );
35442
+ }
35443
+ async function resolveRepoId(repo, installation) {
35444
+ if (/^\d+$/.test(repo)) return Number(repo);
35445
+ const { http } = getAuthedHttpClient();
35446
+ const query = installation ? `?installationId=${encodeURIComponent(installation)}` : "";
35447
+ const payload = await http.get(
35448
+ `/api/v2/github/repos${query}`
35449
+ );
35450
+ const match = payload.repositories.find(
35451
+ (entry) => entry.fullName.toLowerCase() === repo.toLowerCase()
35452
+ );
35453
+ if (!match) {
35454
+ throw new Error(
35455
+ `Repo "${repo}" is not accessible to the workspace's GitHub installation. Run \`deepline git repos\` to list what is.`
35456
+ );
35457
+ }
35458
+ return match.repoId;
35459
+ }
35460
+ async function handleLink(repo, options) {
35461
+ const repoId = await resolveRepoId(repo, options.installation);
35462
+ const { http } = getAuthedHttpClient();
35463
+ const payload = await http.post("/api/v2/play-projects", {
35464
+ repoId,
35465
+ ...options.installation !== void 0 ? { installationId: options.installation } : {},
35466
+ ...options.rootDir !== void 0 ? { rootDirectory: options.rootDir } : {},
35467
+ ...options.manifest !== void 0 ? { manifestPath: options.manifest } : {},
35468
+ ...options.branch !== void 0 ? { productionBranch: options.branch } : {},
35469
+ ...options.prChecks !== void 0 ? { checkOnPullRequest: options.prChecks } : {}
35470
+ });
35471
+ printCommandEnvelope(
35472
+ {
35473
+ project: payload.project,
35474
+ render: {
35475
+ sections: [
35476
+ {
35477
+ title: "linked",
35478
+ lines: [
35479
+ renderProject(payload.project),
35480
+ ...(payload.warnings ?? []).map(
35481
+ (warning) => `WARNING: ${warning}`
35482
+ ),
35483
+ "Pushes to the production branch now register and promote changed plays.",
35484
+ "Anyone who can push to this repo can change what runs in this workspace."
35485
+ ]
35486
+ }
35487
+ ]
35488
+ }
35489
+ },
35490
+ { json: options.json }
35491
+ );
35492
+ }
35493
+ async function handleGet(id, options) {
35494
+ const { http } = getAuthedHttpClient();
35495
+ const payload = await http.get(
35496
+ `/api/v2/play-projects/${encodeURIComponent(id)}`
35497
+ );
35498
+ printCommandEnvelope(
35499
+ {
35500
+ project: payload.project,
35501
+ render: {
35502
+ sections: [
35503
+ {
35504
+ title: "linked repository",
35505
+ lines: [renderProject(payload.project)]
35506
+ }
35507
+ ]
35508
+ }
35509
+ },
35510
+ { json: options.json }
35511
+ );
35512
+ }
35513
+ async function handleSet(id, options) {
35514
+ const { http } = getAuthedHttpClient();
35515
+ const payload = await http.patch(
35516
+ `/api/v2/play-projects/${encodeURIComponent(id)}`,
35517
+ {
35518
+ ...options.branch !== void 0 ? { productionBranch: options.branch } : {},
35519
+ ...options.rootDir !== void 0 ? { rootDirectory: options.rootDir } : {},
35520
+ ...options.manifest !== void 0 ? { manifestPath: options.manifest } : {},
35521
+ ...options.prChecks !== void 0 ? { checkOnPullRequest: options.prChecks } : {},
35522
+ ...options.disabled !== void 0 ? { disabled: options.disabled } : {}
35523
+ }
35524
+ );
35525
+ printCommandEnvelope(
35526
+ {
35527
+ project: payload.project,
35528
+ render: {
35529
+ sections: [
35530
+ { title: "updated", lines: [renderProject(payload.project)] }
35531
+ ]
35532
+ }
35533
+ },
35534
+ { json: options.json }
35535
+ );
35536
+ }
35537
+ async function handleUnlink(id, options) {
35538
+ const { http } = getAuthedHttpClient();
35539
+ await http.delete(`/api/v2/play-projects/${encodeURIComponent(id)}`);
35540
+ printCommandEnvelope(
35541
+ {
35542
+ ok: true,
35543
+ id,
35544
+ render: {
35545
+ sections: [
35546
+ {
35547
+ title: "unlinked",
35548
+ lines: [
35549
+ `Repository link ${id} removed. Deployments stop immediately and in-flight deploy credentials die; live plays keep running.`
35550
+ ]
35551
+ }
35552
+ ]
35553
+ }
35554
+ },
35555
+ { json: options.json }
35556
+ );
35557
+ }
35558
+ async function handleConnect(options) {
35559
+ const baseUrl = resolveBaseUrlOnly();
35560
+ const connectUrl = `${baseUrl.replace(/\/$/, "")}/api/v2/github/connect`;
35561
+ const opened = openInBrowser(connectUrl);
35562
+ printCommandEnvelope(
35563
+ {
35564
+ connectUrl,
35565
+ browser: opened,
35566
+ render: {
35567
+ sections: [
35568
+ {
35569
+ title: "connect GitHub",
35570
+ lines: [
35571
+ opened === "opened" ? `Opened ${connectUrl} in your browser.` : `Open ${connectUrl} in your browser.`,
35572
+ "Sign in as a workspace admin if prompted, approve the GitHub",
35573
+ "installation, then return here and run `deepline git repos`."
35574
+ ]
35575
+ }
35576
+ ]
35577
+ }
35578
+ },
35579
+ { json: options.json }
35580
+ );
35581
+ }
35582
+ async function handleDeploymentsList(options) {
35583
+ const { http } = getAuthedHttpClient();
35584
+ const query = new URLSearchParams();
35585
+ if (options.repo) query.set("projectId", options.repo);
35586
+ if (options.limit) query.set("limit", options.limit);
35587
+ const suffix = query.size > 0 ? `?${query.toString()}` : "";
35588
+ const payload = await http.get(
35589
+ `/api/v2/deployments${suffix}`
35590
+ );
35591
+ printCommandEnvelope(
35592
+ {
35593
+ deployments: payload.deployments,
35594
+ count: payload.deployments.length,
35595
+ render: {
35596
+ sections: [
35597
+ {
35598
+ title: "deployments",
35599
+ lines: payload.deployments.length ? payload.deployments.map(renderDeployment) : [
35600
+ "No deployments yet. Push to a linked repository to create one."
35601
+ ]
35602
+ }
35603
+ ]
35604
+ }
35605
+ },
35606
+ { json: options.json }
35607
+ );
35608
+ }
35609
+ async function handleDeploymentGet(id, options) {
35610
+ const { http } = getAuthedHttpClient();
35611
+ const payload = await http.get(`/api/v2/deployments/${encodeURIComponent(id)}`);
35612
+ const results = payload.deployment.results;
35613
+ const playLines = Array.isArray(results?.plays) ? results.plays.map(
35614
+ (play) => `${play.name ?? "?"} - ${play.status ?? "?"}${play.error ? `: ${play.error}` : ""}`
35615
+ ) : [];
35616
+ printCommandEnvelope(
35617
+ {
35618
+ deployment: payload.deployment,
35619
+ project: payload.project,
35620
+ render: {
35621
+ sections: [
35622
+ {
35623
+ title: `deployment ${payload.deployment.id}${payload.project ? ` (${payload.project.repoFullName})` : ""}`,
35624
+ lines: [renderDeployment(payload.deployment)]
35625
+ },
35626
+ ...playLines.length ? [{ title: "plays", lines: playLines }] : []
35627
+ ]
35628
+ }
35629
+ },
35630
+ { json: options.json }
35631
+ );
35632
+ }
35633
+ function registerGitCommands(program) {
35634
+ const git = program.command("git").alias("projects").description(
35635
+ "Git deploys: link repositories to this workspace and deploy plays on push."
35636
+ ).addHelpText(
35637
+ "after",
35638
+ `
35639
+ Examples:
35640
+ deepline git connect
35641
+ deepline git repos
35642
+ deepline git link acme/growth --branch main
35643
+ deepline git list
35644
+ deepline git set <id> --branch release
35645
+ deepline git unlink <id>
35646
+ deepline git deployments --repo <id>
35647
+ `
35648
+ );
35649
+ git.command("connect").description("Connect a GitHub installation (browser step).").option("--json", "Emit JSON output").action(async (options) => handleConnect(options));
35650
+ git.command("repos").description("List repos the workspace's GitHub installation can reach.").option(
35651
+ "--installation <id>",
35652
+ "GitHub installation id (required when several are connected)"
35653
+ ).option("--json", "Emit JSON output").action(
35654
+ async (options) => handleRepos(options)
35655
+ );
35656
+ git.command("list").description("List linked repositories.").option("--all", "Include unlinked repositories").option("--json", "Emit JSON output").action(
35657
+ async (options) => handleList(options)
35658
+ );
35659
+ 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(
35660
+ "--manifest <file>",
35661
+ "Manifest file name under the base path (default: deepline.json)"
35662
+ ).option(
35663
+ "--installation <id>",
35664
+ "GitHub installation id (required when several are connected)"
35665
+ ).option("--no-pr-checks", "Skip Check Runs on pull requests").option("--json", "Emit JSON output").action(
35666
+ async (repo, options) => handleLink(repo, options)
35667
+ );
35668
+ 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));
35669
+ 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(
35670
+ "--manifest <file>",
35671
+ "Manifest file name under the base path (default: deepline.json)"
35672
+ ).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(
35673
+ async (id, options) => handleSet(id, {
35674
+ ...options,
35675
+ disabled: options.enabled === true ? false : options.disabled === true ? true : void 0
35676
+ })
35677
+ );
35678
+ git.command("unlink").description("Unlink a repository (live plays keep running).").argument("<id>", "Repository link id").option("--json", "Emit JSON output").action(
35679
+ async (id, options) => handleUnlink(id, options)
35680
+ );
35681
+ 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(
35682
+ async (id, options) => id ? handleDeploymentGet(id, options) : handleDeploymentsList(options)
35683
+ );
35684
+ const deployments = program.command("deployments", { hidden: true });
35685
+ deployments.command("list").option("--project <id>", "Filter to one repository link").option("--limit <n>", "Max rows (default 50)").option("--json", "Emit JSON output").action(
35686
+ async (options) => handleDeploymentsList({ ...options, repo: options.project })
35687
+ );
35688
+ deployments.command("get").argument("<id>", "Deployment id").option("--json", "Emit JSON output").action(
35689
+ async (id, options) => handleDeploymentGet(id, options)
35690
+ );
35691
+ }
35692
+
34844
35693
  // src/cli/getting-started.ts
34845
35694
  var DEEPLINE_GTM_SKILL = "/deepline-gtm";
34846
35695
  var DEEPLINE_GTM_STARTER_PROMPTS = [
@@ -35081,7 +35930,7 @@ function preventShellHistoryLeak(forbidden) {
35081
35930
  );
35082
35931
  }
35083
35932
  }
35084
- async function handleList(options) {
35933
+ async function handleList2(options) {
35085
35934
  const client2 = new DeeplineClient();
35086
35935
  const secrets = await client2.listSecrets();
35087
35936
  printCommandEnvelope(
@@ -35124,7 +35973,7 @@ async function handleCheck(nameInput, options) {
35124
35973
  );
35125
35974
  if (!secret) process.exitCode = 4;
35126
35975
  }
35127
- async function handleSet(nameInput, forbidden, options) {
35976
+ async function handleSet2(nameInput, forbidden, options) {
35128
35977
  preventShellHistoryLeak(forbidden);
35129
35978
  const name = normalizeSecretName(nameInput);
35130
35979
  const scope = options.scope === "play" ? "play" : "org";
@@ -35183,14 +36032,14 @@ Examples:
35183
36032
  `
35184
36033
  );
35185
36034
  secrets.command("list").description("List secret metadata only.").option("--json", "Emit JSON output").action(async (options) => {
35186
- await handleList(options);
36035
+ await handleList2(options);
35187
36036
  });
35188
36037
  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) => {
35189
36038
  await handleCheck(name, options);
35190
36039
  });
35191
36040
  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(
35192
36041
  async (name, forbidden, options) => {
35193
- await handleSet(name, forbidden ?? [], options);
36042
+ await handleSet2(name, forbidden ?? [], options);
35194
36043
  }
35195
36044
  );
35196
36045
  }
@@ -36840,7 +37689,7 @@ function failSetupPhase(phases, phase, code) {
36840
37689
  }
36841
37690
  function rollbackCommand(scope, root) {
36842
37691
  const prefix = scope === "local" && root ? ` --prefix ${JSON.stringify(join17(root, ".deepline", "runtime"))}` : "";
36843
- return `npm install -g${prefix} --no-audit --no-fund --include=optional --allow-scripts=esbuild deepline@${SDK_VERSION}`;
37692
+ return `npm install -g${prefix} --no-audit --no-fund --include=optional deepline@${SDK_VERSION}`;
36844
37693
  }
36845
37694
  function setupResumeCommand(baseUrl, scope) {
36846
37695
  const hostPrefix = baseUrl === "https://code.deepline.com" ? "" : `DEEPLINE_HOST_URL=${JSON.stringify(baseUrl)} `;
@@ -37409,9 +38258,7 @@ async function runSetupCommand(options) {
37409
38258
  title: "setup",
37410
38259
  lines: [
37411
38260
  workspaceName ? `Deepline is installed and connected to ${workspaceName}.` : "Deepline is installed and connected.",
37412
- ...workspaceName ? [
37413
- "To link a different workspace, run: deepline auth register"
37414
- ] : [],
38261
+ ...workspaceName ? ["To link a different workspace, run: deepline auth register"] : [],
37415
38262
  `Use ${DEEPLINE_GTM_SKILL} in your agent.`,
37416
38263
  ...DEEPLINE_GTM_STARTER_PROMPTS.map(
37417
38264
  (example, index) => `${index + 1}. ${example.title}: ${example.prompt}`
@@ -37778,12 +38625,6 @@ var NPM_SDK_INSTALL_COMMON_FLAGS = [
37778
38625
  "--no-fund",
37779
38626
  "--include=optional"
37780
38627
  ];
37781
- var NPM_SDK_GLOBAL_INSTALL_FLAGS = [
37782
- "--no-audit",
37783
- "--no-fund",
37784
- "--include=optional",
37785
- "--allow-scripts=esbuild"
37786
- ];
37787
38628
  var NPM_SDK_SIDECAR_PACKAGE_JSON = `${JSON.stringify(
37788
38629
  {
37789
38630
  private: true,
@@ -38018,9 +38859,9 @@ function resolveUpdatePlan(options = {}) {
38018
38859
  "-g",
38019
38860
  "--prefix",
38020
38861
  installPrefix,
38021
- ...NPM_SDK_GLOBAL_INSTALL_FLAGS,
38862
+ ...NPM_SDK_INSTALL_COMMON_FLAGS,
38022
38863
  packageSpec
38023
- ] : ["install", "-g", ...NPM_SDK_GLOBAL_INSTALL_FLAGS, packageSpec];
38864
+ ] : ["install", "-g", ...NPM_SDK_INSTALL_COMMON_FLAGS, packageSpec];
38024
38865
  const fallbackRegistryUrl = options.npmFallbackRegistryUrl !== void 0 ? options.npmFallbackRegistryUrl : publicNpmFallbackRegistryUrl(
38025
38866
  env.DEEPLINE_HOST_URL?.trim() || autoDetectBaseUrl()
38026
38867
  );
@@ -39772,6 +40613,17 @@ function numberValue(value) {
39772
40613
  return typeof value === "number" && Number.isFinite(value) ? value : null;
39773
40614
  }
39774
40615
 
40616
+ // src/cli/tool-connection-status.ts
40617
+ function toolConnectionStatusMessage(input2) {
40618
+ if (input2.credentialStatus === "requires_connection") {
40619
+ return "requires your credentials \u2014 not connected (connect to use)";
40620
+ }
40621
+ if (input2.connected === false && input2.credentialStatus === "managed") {
40622
+ return "temporarily unavailable";
40623
+ }
40624
+ return null;
40625
+ }
40626
+
39775
40627
  // src/cli/commands/tools.ts
39776
40628
  var TOOL_COMMAND_TEMPLATES = {
39777
40629
  describe: "deepline tools describe <toolId>",
@@ -39896,10 +40748,11 @@ function notConnectedSuffix(tool) {
39896
40748
  const record2 = tool;
39897
40749
  const status = stringField2(record2, "credentialStatus", "credential_status");
39898
40750
  const connected = record2.connected;
39899
- if (status === "requires_connection" || connected === false) {
39900
- return " - \u26A0 requires your credentials \u2014 not connected (connect to use)";
39901
- }
39902
- return "";
40751
+ const message = toolConnectionStatusMessage({
40752
+ connected: connected === false ? false : void 0,
40753
+ credentialStatus: status || void 0
40754
+ });
40755
+ return message ? ` - \u26A0 ${message}` : "";
39903
40756
  }
39904
40757
  function shortPricingHint(tool) {
39905
40758
  const pricing = recordField2(
@@ -42449,14 +43302,14 @@ async function handleTransform(id, options) {
42449
43302
  );
42450
43303
  return outcomes.every((o) => o.ok) ? 0 : 1;
42451
43304
  }
42452
- async function handleList2(options) {
43305
+ async function handleList3(options) {
42453
43306
  const limit = options.limit ? Number(options.limit) : void 0;
42454
43307
  const result = await client().listWorkflows({
42455
43308
  limit: Number.isFinite(limit) ? limit : void 0
42456
43309
  });
42457
43310
  emitPassThrough("list", result, options);
42458
43311
  }
42459
- async function handleGet(id, options) {
43312
+ async function handleGet2(id, options) {
42460
43313
  emitPassThrough("get", await client().getWorkflow(id), options);
42461
43314
  }
42462
43315
  async function handleDelete(id, options) {
@@ -42575,12 +43428,12 @@ Notes:
42575
43428
  });
42576
43429
  withJsonOption2(
42577
43430
  workflows.command("list").description("List workspace workflows.").option("--limit <n>", "Max workflows to return")
42578
- ).action(handleList2);
43431
+ ).action(handleList3);
42579
43432
  withJsonOption2(
42580
43433
  workflows.command("get <id>").description(
42581
43434
  "Fetch a workflow, including its published-revision config."
42582
43435
  )
42583
- ).action(handleGet);
43436
+ ).action(handleGet2);
42584
43437
  withJsonOption2(
42585
43438
  workflows.command("disable <id>").description("Turn a workflow off.")
42586
43439
  ).action(handleDisable);
@@ -42633,6 +43486,7 @@ function registerDeeplineCommandGroups(program) {
42633
43486
  registerBillingCommands(program);
42634
43487
  registerMonitorsCommands(program);
42635
43488
  registerOrgCommands(program);
43489
+ registerGitCommands(program);
42636
43490
  registerEnrichCommand(program);
42637
43491
  registerCsvCommands(program);
42638
43492
  registerDbCommands(program);
@@ -42846,97 +43700,6 @@ What changed in ${response.update_summary.version}: ${response.update_summary.su
42846
43700
 
42847
43701
  // src/cli/index.ts
42848
43702
  var PREFLIGHT_TIMEOUT_MS = 3e3;
42849
- var ProjectOrgPinRequiredError = class extends Error {
42850
- code = "PROJECT_ORG_NOT_PINNED";
42851
- exitCode = 3;
42852
- payload;
42853
- constructor(input2) {
42854
- super("Cloud work is blocked because this project uses global host auth.");
42855
- this.name = "ProjectOrgPinRequiredError";
42856
- this.payload = {
42857
- ok: false,
42858
- exitCode: this.exitCode,
42859
- code: this.code,
42860
- message: this.message,
42861
- command: input2.command,
42862
- auth: { scope: "global", source: "host", projectPinned: false },
42863
- project: { dir: input2.projectDir, pinPath: input2.pinPath },
42864
- next: "deepline org set --auth-scope folder"
42865
- };
42866
- }
42867
- };
42868
- function commandUsesOnlyReadOrLocalOperations(command) {
42869
- const [group, action] = command.split(" ");
42870
- if ([
42871
- "auth",
42872
- "org",
42873
- "health",
42874
- "preflight",
42875
- "version",
42876
- "update",
42877
- "skills",
42878
- "doctor",
42879
- "quickstart"
42880
- ].includes(group ?? "")) {
42881
- return true;
42882
- }
42883
- if (group === "plays") {
42884
- return [
42885
- "check",
42886
- "get",
42887
- "list",
42888
- "search",
42889
- "grep",
42890
- "describe",
42891
- "versions"
42892
- ].includes(action ?? "");
42893
- }
42894
- if (group === "runs") {
42895
- return ["get", "list", "tail", "logs", "export"].includes(action ?? "");
42896
- }
42897
- if (group === "tools") {
42898
- return ["list", "search", "get", "describe"].includes(action ?? "");
42899
- }
42900
- if (group === "providers") return ["list", "get"].includes(action ?? "");
42901
- if (group === "secrets") return ["list", "check"].includes(action ?? "");
42902
- if (group === "billing")
42903
- return ["balance", "usage", "history"].includes(action ?? "");
42904
- return false;
42905
- }
42906
- function assertProjectCloudWorkIsPinned(command) {
42907
- if (process.argv.includes("--dry-run") || commandUsesOnlyReadOrLocalOperations(command)) {
42908
- return;
42909
- }
42910
- const config = resolveConfig();
42911
- const provenance = resolveCliAuthProvenance(config);
42912
- if (provenance.scope !== "global" || provenance.project.state !== "project") {
42913
- return;
42914
- }
42915
- throw new ProjectOrgPinRequiredError({
42916
- command,
42917
- projectDir: provenance.project.dir,
42918
- pinPath: provenance.project.pinPath
42919
- });
42920
- }
42921
- function printProjectOrgPinRequiredError(error) {
42922
- if (shouldEmitJson(process.argv.includes("--json"))) {
42923
- printJson(error.payload);
42924
- return;
42925
- }
42926
- const project = error.payload.project;
42927
- process.stderr.write(
42928
- [
42929
- "\u2717 Cloud work is blocked in this project",
42930
- "",
42931
- " Auth: global host default",
42932
- " This project is not pinned. Global auth is shared by every unpinned CLI on this machine.",
42933
- "",
42934
- " Pin this folder to the current target:",
42935
- " deepline org set --auth-scope folder",
42936
- ` This writes: ${project.pinPath}`
42937
- ].join("\n") + "\n"
42938
- );
42939
- }
42940
43703
  function asCommanderError(error) {
42941
43704
  if (!(error instanceof Error) || !("code" in error)) {
42942
43705
  return null;
@@ -43247,7 +44010,6 @@ Exit codes:
43247
44010
  return;
43248
44011
  }
43249
44012
  const compatibilityCommand = compatibilityCommandPath(actionCommand) || actionCommand.name();
43250
- assertProjectCloudWorkIsPinned(compatibilityCommand);
43251
44013
  if (printStartupPhase) {
43252
44014
  progress?.phase("checking sdk compatibility");
43253
44015
  }
@@ -43424,10 +44186,7 @@ Examples:
43424
44186
  });
43425
44187
  progress?.fail();
43426
44188
  const wantsJson = process.argv.includes("--json");
43427
- if (error instanceof ProjectOrgPinRequiredError) {
43428
- printProjectOrgPinRequiredError(error);
43429
- process.exitCode = error.exitCode;
43430
- } else if (commanderError) {
44189
+ if (commanderError) {
43431
44190
  if (commanderError.code === "commander.unknownCommand") {
43432
44191
  }
43433
44192
  process.exitCode = commanderError.code === "commander.unknownCommand" && !wantsJson ? 2 : commanderError.exitCode ?? 1;