deepline 0.3.235 → 0.3.237

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.
package/dist/cli/index.js CHANGED
@@ -3454,7 +3454,7 @@ var SDK_RELEASE = {
3454
3454
  // getters keep their established compatibility behavior.
3455
3455
  // 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
3456
3456
  // 0.3.90 is the first deliberately versioned SDK release for API v3.
3457
- version: "0.3.235",
3457
+ version: "0.3.237",
3458
3458
  updateSummary: "Play grep now returns concise results with the matched fields and terms. Automatic CLI updates are enabled by default; use `deepline settings autoupdate off` to opt out, `deepline settings autoupdate on` to re-enable updates, or `deepline settings autoupdate pin <version>` to hold an exact release.",
3459
3459
  packageCapabilities: {
3460
3460
  updatePreferences: 1
@@ -4133,6 +4133,15 @@ function describeRequestTarget(path) {
4133
4133
  }
4134
4134
  return "Deepline";
4135
4135
  }
4136
+ function networkDiagnosticUrl(value) {
4137
+ try {
4138
+ const url = new URL(value);
4139
+ if (url.protocol !== "https:" && url.protocol !== "http:") return void 0;
4140
+ return `${url.origin}${url.pathname}`;
4141
+ } catch {
4142
+ return void 0;
4143
+ }
4144
+ }
4136
4145
  function providerLabelFromToolId(toolId) {
4137
4146
  const normalized = toolId.trim().toLowerCase();
4138
4147
  const provider = normalized.split(/[_:./-]+/)[0];
@@ -4233,6 +4242,10 @@ var HttpClient = class {
4233
4242
  const baseUrl = this.config.baseUrl;
4234
4243
  const url = `${baseUrl}${path}`;
4235
4244
  const method = options?.method ?? "GET";
4245
+ const requestStartedAt = Date.now();
4246
+ let fetchAttempts = 0;
4247
+ let lastRequestUrl = url;
4248
+ let networkFailedAt;
4236
4249
  const headers = this.authHeaders(options?.headers);
4237
4250
  if (options?.body !== void 0) {
4238
4251
  headers["Content-Type"] = "application/json";
@@ -4244,6 +4257,7 @@ var HttpClient = class {
4244
4257
  requestAttempts: for (let attempt = 0; attempt <= maxRetries; attempt++) {
4245
4258
  if (options?.signal?.aborted) {
4246
4259
  lastError = requestCancelledError(options.signal);
4260
+ networkFailedAt = Date.now();
4247
4261
  break;
4248
4262
  }
4249
4263
  if (attempt > 0) {
@@ -4254,12 +4268,14 @@ var HttpClient = class {
4254
4268
  await sleep(delayMs, options?.signal);
4255
4269
  } catch (error) {
4256
4270
  lastError = error instanceof Error ? error : new Error(String(error));
4271
+ networkFailedAt = Date.now();
4257
4272
  break;
4258
4273
  }
4259
4274
  }
4260
4275
  for (const candidateUrl of candidateUrls) {
4261
4276
  if (options?.signal?.aborted) {
4262
4277
  lastError = requestCancelledError(options.signal);
4278
+ networkFailedAt = Date.now();
4263
4279
  break requestAttempts;
4264
4280
  }
4265
4281
  const controller = new AbortController();
@@ -4274,10 +4290,13 @@ var HttpClient = class {
4274
4290
  once: true
4275
4291
  });
4276
4292
  try {
4293
+ const requestBody = options?.formData !== void 0 ? typeof options.formData === "function" ? options.formData() : options.formData : options?.body !== void 0 ? JSON.stringify(options.body) : void 0;
4294
+ fetchAttempts += 1;
4295
+ lastRequestUrl = candidateUrl;
4277
4296
  const response = await fetch(candidateUrl, {
4278
4297
  method,
4279
4298
  headers,
4280
- body: options?.formData !== void 0 ? typeof options.formData === "function" ? options.formData() : options.formData : options?.body !== void 0 ? JSON.stringify(options.body) : void 0,
4299
+ body: requestBody,
4281
4300
  signal: controller.signal
4282
4301
  });
4283
4302
  options?.onResponse?.(response);
@@ -4381,6 +4400,7 @@ var HttpClient = class {
4381
4400
  return parsed;
4382
4401
  } catch (error) {
4383
4402
  clearTimeout(timeoutId);
4403
+ networkFailedAt = Date.now();
4384
4404
  if (options?.signal?.aborted) {
4385
4405
  lastError = requestCancelledError(options.signal);
4386
4406
  break requestAttempts;
@@ -4411,6 +4431,19 @@ var HttpClient = class {
4411
4431
  lastError,
4412
4432
  describeRequestTarget(path)
4413
4433
  );
4434
+ const failedAt = networkFailedAt ?? Date.now();
4435
+ const diagnosticUrl = networkDiagnosticUrl(lastRequestUrl);
4436
+ const networkDetails = {
4437
+ ...mappedNetworkError.details,
4438
+ request: {
4439
+ method,
4440
+ ...diagnosticUrl === void 0 ? {} : { url: diagnosticUrl },
4441
+ failedAtUtc: new Date(failedAt).toISOString(),
4442
+ // Elapsed time covers the entire logical request, including retries.
4443
+ elapsedMs: Math.max(0, failedAt - requestStartedAt),
4444
+ attempts: fetchAttempts
4445
+ }
4446
+ };
4414
4447
  if (options?.toolId) {
4415
4448
  const code = mappedNetworkError.code;
4416
4449
  throw withErrorCause(
@@ -4431,7 +4464,7 @@ var HttpClient = class {
4431
4464
  retryAfterMs: null,
4432
4465
  networkKind: code === "NETWORK_TIMEOUT" ? "timeout" : code === "NETWORK_ABORTED" ? "unknown" : "unavailable",
4433
4466
  networkScope: "client_to_deepline",
4434
- details: mappedNetworkError.details,
4467
+ details: networkDetails,
4435
4468
  publicDetails: options.idempotencyKey ? { idempotencyKey: options.idempotencyKey } : null
4436
4469
  }
4437
4470
  ),
@@ -4443,7 +4476,7 @@ var HttpClient = class {
4443
4476
  withCoworkNetworkHint(mappedNetworkError.message),
4444
4477
  void 0,
4445
4478
  mappedNetworkError.code,
4446
- mappedNetworkError.details
4479
+ networkDetails
4447
4480
  ),
4448
4481
  lastError
4449
4482
  );
@@ -12866,9 +12899,13 @@ function recentUsageLines(entries) {
12866
12899
  for (const entry of entries) {
12867
12900
  const op = `${humanize(entry.provider)} ${humanize(entry.operation)}`.trim();
12868
12901
  const roughUsd = Number(entry.rough_usd_cost);
12869
- const usdText = entry.charge_state !== "pending" && entry.rough_usd_cost !== null && entry.rough_usd_cost !== void 0 && Number.isFinite(roughUsd) ? ` (\u2248$${roughUsd.toFixed(2)})` : "";
12870
- const charge = entry.billing_mode === "no_bill" ? "free" : entry.charge_state === "temporary_hold" ? `${entry.credits ?? 0} cr held${usdText}, not final` : entry.charge_state === "pending" ? "final Deepline charge pending" : `${entry.credits ?? 0} cr${usdText}`;
12871
- const state = entry.charge_state === "temporary_hold" ? "temporary hold, final charge pending" : entry.charge_state === "pending" ? "no final charge recorded yet" : entry.status || "completed";
12902
+ const credits = entry.credits !== null && entry.credits !== void 0 && String(entry.credits).trim().length > 0 && Number.isFinite(Number(entry.credits)) ? Number(entry.credits) : null;
12903
+ const temporaryHold = entry.charge_state === "temporary_hold";
12904
+ const pending = entry.charge_state === "pending" || entry.charge_finality === "pending";
12905
+ const unknown = entry.charge_finality === "unknown" || credits === null;
12906
+ const usdText = !pending && !unknown && entry.rough_usd_cost !== null && entry.rough_usd_cost !== void 0 && Number.isFinite(roughUsd) ? ` (\u2248$${roughUsd.toFixed(2)})` : "";
12907
+ const charge = temporaryHold ? `${credits === null ? "unknown amount" : `${credits} cr`} held${usdText}, not final` : pending ? "final Deepline charge pending" : unknown ? "charge unknown" : entry.billing_mode === "no_bill" ? "free" : credits === 0 && (entry.charge_finality === "final" || entry.charge_state === "hold_release") ? "0 cr, final" : `${credits} cr${usdText}`;
12908
+ const state = temporaryHold ? "temporary hold, final charge pending" : pending ? "no final charge recorded yet" : entry.status || "unknown";
12872
12909
  const auditBits = [
12873
12910
  entry.outcome ? `outcome=${entry.outcome}` : null,
12874
12911
  entry.pricing_basis ? `priced_by=${entry.pricing_basis}` : null,
@@ -13065,6 +13102,7 @@ async function handleUsage(options) {
13065
13102
  const recentLines = recentUsageLines(
13066
13103
  Array.isArray(recent.entries) ? recent.entries : []
13067
13104
  );
13105
+ const matchingActivity = typeof recent.total === "number" && Number.isFinite(recent.total) && recent.total >= 0 && typeof recent.total_is_exact === "boolean" ? recent.total_is_exact ? `Matching activity: ${recent.total}` : typeof recent.total_lower_bound === "number" && Number.isFinite(recent.total_lower_bound) && recent.total_lower_bound >= 0 ? `Matching activity: at least ${recent.total_lower_bound}` : `Matching activity: count not exact (reported ${recent.total})` : null;
13068
13106
  const lines = options.requestId ? [`Charge lookup: ${options.requestId}`, ...recentLines] : [
13069
13107
  `Balance: ${payload.balance ?? "(unknown)"}`,
13070
13108
  `Last 30 days usage: ${last30Usage ?? "(unknown)"}`,
@@ -13073,8 +13111,10 @@ async function handleUsage(options) {
13073
13111
  ...options.runId && recent.run_id ? [
13074
13112
  `Run spend: ${(payload.run ?? {}).spent_credits ?? "(unknown)"} Deepline Credits`
13075
13113
  ] : [],
13114
+ ...matchingActivity ? [matchingActivity] : [],
13076
13115
  ...recentLines,
13077
- ...recent.has_more === true || recent.incomplete === true ? ["List truncated \u2014 more recent calls match this query."] : [],
13116
+ ...recent.has_more === true ? ["More activity pages are available."] : [],
13117
+ ...recent.incomplete === true ? ["Recent activity is incomplete; the matching count may be higher."] : [],
13078
13118
  ...nextPage ? [`Next page: ${nextPage}`] : [],
13079
13119
  ...!nextPage && (recent.has_more === true || recent.incomplete === true) ? [
13080
13120
  "No continuation is available for this view. Use deepline billing ledger export all --json for the full ledger."
@@ -13154,7 +13194,13 @@ async function handleLimitOff(options) {
13154
13194
  async function exportLedger(http, outputPath, options) {
13155
13195
  let summary = { row_count: 0, net_delta_credits: 0 };
13156
13196
  let initialized = false;
13197
+ let pageNumber = 0;
13198
+ console.error(`Exporting billing ledger to ${outputPath}`);
13157
13199
  for await (const entries of iterateCursorPages(async (cursor) => {
13200
+ pageNumber += 1;
13201
+ console.error(
13202
+ `Fetching page ${pageNumber}; ${summary.row_count} rows written.`
13203
+ );
13158
13204
  const params = new URLSearchParams({ limit: "5000" });
13159
13205
  if (cursor) params.set("cursor", cursor);
13160
13206
  if (options.sinceAt !== null)
@@ -13181,7 +13227,11 @@ async function exportLedger(http, outputPath, options) {
13181
13227
  const rows = entries.map(ledgerApiEntryToRow);
13182
13228
  await (0, import_promises2.appendFile)(outputPath, ledgerRowsToCsv(rows, false), "utf-8");
13183
13229
  summary = summarizeLedgerRows(summary, rows);
13230
+ console.error(
13231
+ `Wrote page ${pageNumber}; ${summary.row_count} rows written.`
13232
+ );
13184
13233
  }
13234
+ console.error(`Export complete: ${summary.row_count} rows written.`);
13185
13235
  return summary;
13186
13236
  }
13187
13237
  async function handleHistory(options) {
@@ -13981,6 +14031,8 @@ function registerBillingCommands(program) {
13981
14031
  `
13982
14032
  Concepts:
13983
14033
  Billing commands show Deepline credits, not raw provider spend.
14034
+ Balance is shared by the workspace; concurrent work changes it. Use a job_id
14035
+ charge lookup to attribute one tool command instead of comparing balances.
13984
14036
  checkout/subscribe/redeem-code can open a browser unless --no-open is set.
13985
14037
 
13986
14038
  Examples:
@@ -13990,6 +14042,10 @@ Examples:
13990
14042
  deepline billing plans --json
13991
14043
  deepline billing subscription status --json
13992
14044
 
14045
+ # Price a tool before execution; look up its exact charge afterward
14046
+ deepline tools describe <tool-id> --pricing-only
14047
+ deepline billing usage --request-id <job_id> --json
14048
+
13993
14049
  # Buy credits or a plan
13994
14050
  deepline billing top-up 1000 --json
13995
14051
  deepline billing checkout --credits 1000 --no-open --json
@@ -14011,6 +14067,8 @@ Examples:
14011
14067
  `
14012
14068
  Notes:
14013
14069
  Read-only. Shows the current Deepline credit balance for the active workspace.
14070
+ The balance includes concurrent workspace activity, so a before/after difference
14071
+ cannot isolate one command. Use billing usage --request-id <job_id> --json.
14014
14072
 
14015
14073
  Examples:
14016
14074
  deepline billing balance
@@ -14023,6 +14081,9 @@ Examples:
14023
14081
  Notes:
14024
14082
  Read-only. Shows last-30-day Deepline credit usage plus a bounded recent-call
14025
14083
  page. Use --limit/--cursor to paginate the recent-call section.
14084
+ For one tool command, use the job_id returned by tools execute, or its next.billing
14085
+ command. Pending charges and temporary holds are not final spend; unknown means
14086
+ final charge evidence is unavailable. Workspace balance changes include other work.
14026
14087
 
14027
14088
  Examples:
14028
14089
  deepline billing usage
@@ -29908,7 +29969,23 @@ async function handleRunsList(args) {
29908
29969
  }
29909
29970
  }
29910
29971
  if (!playName && !statusFilter) {
29911
- console.error(usage);
29972
+ const message = "runs list requires --play or --status.";
29973
+ const next = {
29974
+ discover: "deepline plays list --json",
29975
+ running: "deepline runs list --status running --json"
29976
+ };
29977
+ console.error(
29978
+ `${message}
29979
+ ${usage}
29980
+ Discover Plays: ${next.discover}
29981
+ Active runs: ${next.running}`
29982
+ );
29983
+ if (argsWantJson(args)) {
29984
+ printCommandEnvelope(
29985
+ { ok: false, exitCode: 1, code: "RUN_FILTER_REQUIRED", message, next },
29986
+ { json: true }
29987
+ );
29988
+ }
29912
29989
  return 1;
29913
29990
  }
29914
29991
  if ((offset ?? 0) > 0 && !playName) {
@@ -32341,11 +32418,15 @@ Examples:
32341
32418
  "after",
32342
32419
  `
32343
32420
  Notes:
32421
+ Requires --play or --status. Discover Play references with deepline plays list --json.
32344
32422
  Bounded inventory for a play's recent runs. Use --compact for agent loops.
32423
+ Use the exact qualified Play reference, such as workspace/my-play or prebuilt/my-play.
32424
+ --offset requires --play; narrow status-only lists with a Play reference to paginate.
32345
32425
  Common statuses include running, completed, failed, and stopped.
32346
32426
 
32347
32427
  Examples:
32348
32428
  deepline runs list --play my-play
32429
+ deepline runs list --play workspace/my-play --json
32349
32430
  deepline runs list --play my-play --status failed --compact --json
32350
32431
  deepline runs list --status running --compact --json
32351
32432
  `
@@ -49823,11 +49904,17 @@ var CapabilityDescription = class _CapabilityDescription {
49823
49904
  legacyCost.pricingModel ?? legacyCost.pricing_model
49824
49905
  );
49825
49906
  const pricingModel = unit === "call" ? "fixed" : unit === "result" || unit === "page" ? `per_${unit}` : unit === "usage" ? "provider_usage" : legacyPricingModel;
49826
- const canonicalCredits = numberValue(
49827
- pricing.creditsPerUnit ?? pricing.credits_per_unit
49828
- );
49829
- const canonicalUsd = numberValue(
49830
- pricing.usdPerUnit ?? pricing.usd_per_unit
49907
+ const canonicalCredits = pricingNumber(
49908
+ pricing,
49909
+ "creditsPerUnit",
49910
+ "credits_per_unit",
49911
+ this.#catalogEntry.deeplineCreditsPerPricingUnit ?? this.#catalogEntry.deepline_credits_per_pricing_unit
49912
+ );
49913
+ const canonicalUsd = pricingNumber(
49914
+ pricing,
49915
+ "usdPerUnit",
49916
+ "usd_per_unit",
49917
+ this.#catalogEntry.deeplineUsdPerPricingUnit ?? this.#catalogEntry.deepline_usd_per_pricing_unit
49831
49918
  );
49832
49919
  const billingSource = stringValue4(
49833
49920
  this.#catalogEntry.billingSource ?? this.#catalogEntry.billing_source
@@ -49846,12 +49933,8 @@ var CapabilityDescription = class _CapabilityDescription {
49846
49933
  ),
49847
49934
  billingSource,
49848
49935
  billingSourceLabel,
49849
- deeplineCreditsPerPricingUnit: isFree ? 0 : canonicalCredits ?? numberValue(
49850
- this.#catalogEntry.deeplineCreditsPerPricingUnit ?? this.#catalogEntry.deepline_credits_per_pricing_unit
49851
- ),
49852
- deeplineUsdPerPricingUnit: isFree ? 0 : canonicalUsd ?? numberValue(
49853
- this.#catalogEntry.deeplineUsdPerPricingUnit ?? this.#catalogEntry.deepline_usd_per_pricing_unit
49854
- )
49936
+ deeplineCreditsPerPricingUnit: isFree ? 0 : canonicalCredits,
49937
+ deeplineUsdPerPricingUnit: isFree ? 0 : canonicalUsd
49855
49938
  };
49856
49939
  }
49857
49940
  };
@@ -49864,6 +49947,13 @@ function stringValue4(value) {
49864
49947
  function numberValue(value) {
49865
49948
  return typeof value === "number" && Number.isFinite(value) ? value : null;
49866
49949
  }
49950
+ function pricingNumber(pricing, canonicalKey, aliasKey, legacyValue) {
49951
+ for (const key of [canonicalKey, aliasKey]) {
49952
+ if (Object.prototype.hasOwnProperty.call(pricing, key))
49953
+ return numberValue(pricing[key]);
49954
+ }
49955
+ return numberValue(legacyValue);
49956
+ }
49867
49957
 
49868
49958
  // src/cli/tool-connection-status.ts
49869
49959
  function toolConnectionStatusMessage(input2) {
@@ -50457,11 +50547,15 @@ Concepts:
50457
50547
  Common commands:
50458
50548
  deepline tools search email --json
50459
50549
  deepline tools describe hunter_email_verifier --json
50550
+ deepline tools describe hunter_email_verifier --pricing-only --json
50460
50551
  deepline tools execute hunter_email_verifier --input '{"email":"a@b.com"}'
50552
+ deepline billing usage --request-id <job_id> --json
50461
50553
 
50462
50554
  Output:
50463
50555
  Use describe for tool contracts.
50464
50556
  Use execute to run a tool.
50557
+ Read pricing before execution; use the returned next.billing command for its
50558
+ exact charge. Workspace balance changes also include other callers' activity.
50465
50559
  `
50466
50560
  );
50467
50561
  tools.command("list [category]").description("Browse tool categories, or list every tool in a category.").addHelpText(
@@ -50587,6 +50681,7 @@ Notes:
50587
50681
  Examples:
50588
50682
  deepline tools describe hunter_email_verifier
50589
50683
  deepline tools describe hunter_email_verifier --pricing-only
50684
+ deepline tools describe hunter_email_verifier --pricing-only --json
50590
50685
  deepline tools describe hunter_email_verifier --schema-only
50591
50686
  deepline tools describe hunter_email_verifier --examples-only
50592
50687
  deepline tools describe hunter_email_verifier --json
@@ -50636,10 +50731,15 @@ Notes:
50636
50731
  waterfalls, row maps, checkpoints, and retries.
50637
50732
  Calling a provider-backed tool can spend Deepline credits. Use --json for the
50638
50733
  stable result payload plus output preview and debugging helpers.
50734
+ Read pricing first with tools describe <toolId> --pricing-only --json.
50735
+ Use the returned next.billing command to look up this execution's exact charge;
50736
+ workspace balance changes also include other callers' activity.
50639
50737
  --timeout sets this CLI request's HTTP deadline; it does not cancel provider work.
50640
50738
 
50641
50739
  Examples:
50642
50740
  deepline tools execute hunter_email_verifier --input '{"email":"a@b.com"}'
50741
+ deepline tools describe hunter_email_verifier --pricing-only --json
50742
+ deepline billing usage --request-id <job_id> --json
50643
50743
  deepline tools execute bounceban_verify_bulk --input @batch.json --timeout 10m --json
50644
50744
  deepline tools execute hunter_email_verifier -p email=a@b.com
50645
50745
  deepline tools execute test_rate_limit --input '{"key":"smoke"}' --timeout 90s --json
@@ -50743,6 +50843,38 @@ async function getTool(toolId, options = {}) {
50743
50843
  );
50744
50844
  return 2;
50745
50845
  }
50846
+ const onlyModes = [
50847
+ options.pricingOnly,
50848
+ options.schemaOnly,
50849
+ options.examplesOnly,
50850
+ options.gettersOnly
50851
+ ].filter(Boolean).length;
50852
+ if (onlyModes > 1) {
50853
+ console.error(
50854
+ "Use only one of --pricing-only, --schema-only, --examples-only, or --getters-only."
50855
+ );
50856
+ return 2;
50857
+ }
50858
+ if (options.pricingOnly) {
50859
+ const lines = toolPricingOnlyLines(tool, toolId);
50860
+ if (inferenceQuote)
50861
+ lines.push(...inferenceQuoteSummaryLines(inferenceQuote));
50862
+ printCommandEnvelope(
50863
+ {
50864
+ toolId: String(tool.toolId || toolId),
50865
+ cost: Capability.fromCatalogEntry(tool).describe().customerCost(),
50866
+ ...modelDescription ? { modelOptions: modelDescription } : {},
50867
+ ...isMonitorTypeTool(tool) ? { pricing: recordField2(tool, "pricing") } : {},
50868
+ ...inferenceQuote ? { inferenceQuote } : {}
50869
+ },
50870
+ {
50871
+ json: Boolean(options.json || options.contractJson),
50872
+ text: `${lines.join("\n")}
50873
+ `
50874
+ }
50875
+ );
50876
+ return 0;
50877
+ }
50746
50878
  if (options.contractJson) {
50747
50879
  printCompactJson({
50748
50880
  ...toolContractJsonForDescribe(tool, toolId),
@@ -50760,23 +50892,6 @@ async function getTool(toolId, options = {}) {
50760
50892
  });
50761
50893
  return 0;
50762
50894
  }
50763
- const onlyModes = [
50764
- options.pricingOnly,
50765
- options.schemaOnly,
50766
- options.examplesOnly,
50767
- options.gettersOnly
50768
- ].filter(Boolean).length;
50769
- if (onlyModes > 1) {
50770
- console.error(
50771
- "Use only one of --pricing-only, --schema-only, --examples-only, or --getters-only."
50772
- );
50773
- return 2;
50774
- }
50775
- if (options.pricingOnly) {
50776
- printToolPricingOnly(tool, toolId);
50777
- if (inferenceQuote) printInferenceQuoteSummary(inferenceQuote);
50778
- return 0;
50779
- }
50780
50895
  if (options.schemaOnly) {
50781
50896
  printToolSchemaOnly(tool, toolId);
50782
50897
  if (inferenceQuote) printInferenceQuoteSummary(inferenceQuote);
@@ -50817,11 +50932,16 @@ ${formatModelDescription(modelDescription)}`);
50817
50932
  if (inferenceQuote) printInferenceQuoteSummary(inferenceQuote);
50818
50933
  return 0;
50819
50934
  }
50820
- function printInferenceQuoteSummary(_quote) {
50821
- console.log("");
50822
- console.log("Inference quote:");
50823
- console.log("- Temporary hold: priced estimate (minimum 0.02 credits)");
50824
- console.log("- Final charge: actual usage");
50935
+ function inferenceQuoteSummaryLines(_quote) {
50936
+ return [
50937
+ "",
50938
+ "Inference quote:",
50939
+ "- Temporary hold: priced estimate (minimum 0.02 credits)",
50940
+ "- Final charge: actual usage"
50941
+ ];
50942
+ }
50943
+ function printInferenceQuoteSummary(quote) {
50944
+ for (const line of inferenceQuoteSummaryLines(quote)) console.log(line);
50825
50945
  }
50826
50946
  function toolContractJsonForDescribe(tool, requestedToolId) {
50827
50947
  const toolId = String(tool.toolId || requestedToolId);
@@ -50880,6 +51000,7 @@ function toolContractJsonForDescribe(tool, requestedToolId) {
50880
51000
  toolId,
50881
51001
  provider: tool.provider,
50882
51002
  displayName: tool.displayName,
51003
+ cost: pricing,
50883
51004
  description: tool.description,
50884
51005
  categories: tool.categories,
50885
51006
  ...deprecated ? {
@@ -50899,7 +51020,6 @@ function toolContractJsonForDescribe(tool, requestedToolId) {
50899
51020
  } : {},
50900
51021
  ...executionMetadata ? { executionMetadata } : {},
50901
51022
  ...batchCapability ? { batchCapability } : {},
50902
- cost: pricing,
50903
51023
  getters: {
50904
51024
  extractedLists,
50905
51025
  extractedValues
@@ -50975,7 +51095,7 @@ function printMonitorTypeStreams(tool) {
50975
51095
  console.log(`- ${name}: ${cols.join(", ")}`);
50976
51096
  }
50977
51097
  }
50978
- function printMonitorTypePricing(tool) {
51098
+ function monitorTypePricingLines(tool) {
50979
51099
  const pricing = recordField2(tool, "pricing");
50980
51100
  const byType = recordField2(
50981
51101
  pricing,
@@ -50984,17 +51104,20 @@ function printMonitorTypePricing(tool) {
50984
51104
  );
50985
51105
  const keys = Object.keys(byType);
50986
51106
  if (!keys.length) {
50987
- console.log("Pricing: Deepline credits per accepted event (see --json)");
50988
- return;
51107
+ return ["Pricing: Deepline credits per accepted event (see --json)"];
50989
51108
  }
50990
- console.log("Pricing (Deepline credits per accepted event):");
51109
+ const lines = ["Pricing (Deepline credits per accepted event):"];
50991
51110
  for (const key of keys) {
50992
51111
  const entry = isRecord13(byType[key]) ? byType[key] : {};
50993
51112
  const credits = numberField2(entry, "deepline_credits", "deeplineCredits");
50994
51113
  const display = stringField2(entry, "display");
50995
51114
  const shown = display || (credits !== null ? `${formatDecimal(credits)} credits/event` : "see --json");
50996
- console.log(`- ${key}: ${shown}`);
51115
+ lines.push(`- ${key}: ${shown}`);
50997
51116
  }
51117
+ return lines;
51118
+ }
51119
+ function printMonitorTypePricing(tool) {
51120
+ for (const line of monitorTypePricingLines(tool)) console.log(line);
50998
51121
  }
50999
51122
  function printMonitorTypeDeploy(tool) {
51000
51123
  const deploy = recordField2(tool, "deploy");
@@ -51132,13 +51255,12 @@ function printCompactToolContract(tool, requestedToolId) {
51132
51255
  `More: deepline tools describe ${contract.toolId} --pricing-only | --schema-only | --examples-only | --getters-only | --json`
51133
51256
  );
51134
51257
  }
51135
- function printToolPricingOnly(tool, requestedToolId, options = {}) {
51258
+ function toolPricingOnlyLines(tool, requestedToolId, options = {}) {
51136
51259
  if (isMonitorTypeTool(tool)) {
51137
- printMonitorTypePricing(tool);
51138
- return;
51260
+ return monitorTypePricingLines(tool);
51139
51261
  }
51140
- const contract = toolContractJsonForDescribe(tool, requestedToolId);
51141
- const cost = isRecord13(contract.cost) ? contract.cost : {};
51262
+ const toolId = String(tool.toolId || requestedToolId);
51263
+ const cost = Capability.fromCatalogEntry(tool).describe().customerCost();
51142
51264
  const pricingModel = stringField2(cost, "pricingModel") || "unknown";
51143
51265
  const billing = stringField2(cost, "billingSourceLabel") || stringField2(cost, "billingSource") || stringField2(cost, "billingMode") || "unknown";
51144
51266
  const explicitUnit = stringField2(cost, "unit");
@@ -51148,8 +51270,14 @@ function printToolPricingOnly(tool, requestedToolId, options = {}) {
51148
51270
  const displayText = stringField2(cost, "displayText");
51149
51271
  const summary = stringField2(cost, "summary");
51150
51272
  const price = displayText || summary || (credits !== null ? `${formatDecimal(credits)} Deepline credits${usd !== null ? ` / ${formatUsd(usd)}` : ""} per ${unit}` : "pricing unavailable");
51151
- console.log(`${options.heading ?? `Pricing: ${contract.toolId}`}: ${price}`);
51152
- console.log(`Billing: ${billing}`);
51273
+ return [
51274
+ `${options.heading ?? `Pricing: ${toolId}`}: ${price}`,
51275
+ `Billing: ${billing}`
51276
+ ];
51277
+ }
51278
+ function printToolPricingOnly(tool, requestedToolId, options = {}) {
51279
+ for (const line of toolPricingOnlyLines(tool, requestedToolId, options))
51280
+ console.log(line);
51153
51281
  }
51154
51282
  function printToolSchemaOnly(tool, requestedToolId) {
51155
51283
  if (isMonitorTypeTool(tool)) {
@@ -51362,6 +51490,7 @@ function toolMetadataJsonForDescribe(tool, requestedToolId) {
51362
51490
  } = tool;
51363
51491
  const outputSchemaRecord = recordField2(tool, "outputSchema", "output_schema");
51364
51492
  return {
51493
+ cost: Capability.fromCatalogEntry(tool).describe().customerCost(),
51365
51494
  ...publicTool,
51366
51495
  toolId,
51367
51496
  provider: tool.provider,
@@ -51373,7 +51502,6 @@ function toolMetadataJsonForDescribe(tool, requestedToolId) {
51373
51502
  )
51374
51503
  } : {},
51375
51504
  inputFields: inputFields.map(inputFieldJsonForDescribe),
51376
- cost: Capability.fromCatalogEntry(tool).describe().customerCost(),
51377
51505
  usageGuidance,
51378
51506
  runtimeOutputHelp: {
51379
51507
  contract: "tools describe shows declared schema and Deepline getters; it is not an observed provider response.",