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.
@@ -3449,7 +3449,7 @@ var SDK_RELEASE = {
3449
3449
  // getters keep their established compatibility behavior.
3450
3450
  // 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
3451
3451
  // 0.3.90 is the first deliberately versioned SDK release for API v3.
3452
- version: "0.3.235",
3452
+ version: "0.3.237",
3453
3453
  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.",
3454
3454
  packageCapabilities: {
3455
3455
  updatePreferences: 1
@@ -4128,6 +4128,15 @@ function describeRequestTarget(path) {
4128
4128
  }
4129
4129
  return "Deepline";
4130
4130
  }
4131
+ function networkDiagnosticUrl(value) {
4132
+ try {
4133
+ const url = new URL(value);
4134
+ if (url.protocol !== "https:" && url.protocol !== "http:") return void 0;
4135
+ return `${url.origin}${url.pathname}`;
4136
+ } catch {
4137
+ return void 0;
4138
+ }
4139
+ }
4131
4140
  function providerLabelFromToolId(toolId) {
4132
4141
  const normalized = toolId.trim().toLowerCase();
4133
4142
  const provider = normalized.split(/[_:./-]+/)[0];
@@ -4228,6 +4237,10 @@ var HttpClient = class {
4228
4237
  const baseUrl = this.config.baseUrl;
4229
4238
  const url = `${baseUrl}${path}`;
4230
4239
  const method = options?.method ?? "GET";
4240
+ const requestStartedAt = Date.now();
4241
+ let fetchAttempts = 0;
4242
+ let lastRequestUrl = url;
4243
+ let networkFailedAt;
4231
4244
  const headers = this.authHeaders(options?.headers);
4232
4245
  if (options?.body !== void 0) {
4233
4246
  headers["Content-Type"] = "application/json";
@@ -4239,6 +4252,7 @@ var HttpClient = class {
4239
4252
  requestAttempts: for (let attempt = 0; attempt <= maxRetries; attempt++) {
4240
4253
  if (options?.signal?.aborted) {
4241
4254
  lastError = requestCancelledError(options.signal);
4255
+ networkFailedAt = Date.now();
4242
4256
  break;
4243
4257
  }
4244
4258
  if (attempt > 0) {
@@ -4249,12 +4263,14 @@ var HttpClient = class {
4249
4263
  await sleep(delayMs, options?.signal);
4250
4264
  } catch (error) {
4251
4265
  lastError = error instanceof Error ? error : new Error(String(error));
4266
+ networkFailedAt = Date.now();
4252
4267
  break;
4253
4268
  }
4254
4269
  }
4255
4270
  for (const candidateUrl of candidateUrls) {
4256
4271
  if (options?.signal?.aborted) {
4257
4272
  lastError = requestCancelledError(options.signal);
4273
+ networkFailedAt = Date.now();
4258
4274
  break requestAttempts;
4259
4275
  }
4260
4276
  const controller = new AbortController();
@@ -4269,10 +4285,13 @@ var HttpClient = class {
4269
4285
  once: true
4270
4286
  });
4271
4287
  try {
4288
+ const requestBody = options?.formData !== void 0 ? typeof options.formData === "function" ? options.formData() : options.formData : options?.body !== void 0 ? JSON.stringify(options.body) : void 0;
4289
+ fetchAttempts += 1;
4290
+ lastRequestUrl = candidateUrl;
4272
4291
  const response = await fetch(candidateUrl, {
4273
4292
  method,
4274
4293
  headers,
4275
- body: options?.formData !== void 0 ? typeof options.formData === "function" ? options.formData() : options.formData : options?.body !== void 0 ? JSON.stringify(options.body) : void 0,
4294
+ body: requestBody,
4276
4295
  signal: controller.signal
4277
4296
  });
4278
4297
  options?.onResponse?.(response);
@@ -4376,6 +4395,7 @@ var HttpClient = class {
4376
4395
  return parsed;
4377
4396
  } catch (error) {
4378
4397
  clearTimeout(timeoutId);
4398
+ networkFailedAt = Date.now();
4379
4399
  if (options?.signal?.aborted) {
4380
4400
  lastError = requestCancelledError(options.signal);
4381
4401
  break requestAttempts;
@@ -4406,6 +4426,19 @@ var HttpClient = class {
4406
4426
  lastError,
4407
4427
  describeRequestTarget(path)
4408
4428
  );
4429
+ const failedAt = networkFailedAt ?? Date.now();
4430
+ const diagnosticUrl = networkDiagnosticUrl(lastRequestUrl);
4431
+ const networkDetails = {
4432
+ ...mappedNetworkError.details,
4433
+ request: {
4434
+ method,
4435
+ ...diagnosticUrl === void 0 ? {} : { url: diagnosticUrl },
4436
+ failedAtUtc: new Date(failedAt).toISOString(),
4437
+ // Elapsed time covers the entire logical request, including retries.
4438
+ elapsedMs: Math.max(0, failedAt - requestStartedAt),
4439
+ attempts: fetchAttempts
4440
+ }
4441
+ };
4409
4442
  if (options?.toolId) {
4410
4443
  const code = mappedNetworkError.code;
4411
4444
  throw withErrorCause(
@@ -4426,7 +4459,7 @@ var HttpClient = class {
4426
4459
  retryAfterMs: null,
4427
4460
  networkKind: code === "NETWORK_TIMEOUT" ? "timeout" : code === "NETWORK_ABORTED" ? "unknown" : "unavailable",
4428
4461
  networkScope: "client_to_deepline",
4429
- details: mappedNetworkError.details,
4462
+ details: networkDetails,
4430
4463
  publicDetails: options.idempotencyKey ? { idempotencyKey: options.idempotencyKey } : null
4431
4464
  }
4432
4465
  ),
@@ -4438,7 +4471,7 @@ var HttpClient = class {
4438
4471
  withCoworkNetworkHint(mappedNetworkError.message),
4439
4472
  void 0,
4440
4473
  mappedNetworkError.code,
4441
- mappedNetworkError.details
4474
+ networkDetails
4442
4475
  ),
4443
4476
  lastError
4444
4477
  );
@@ -12873,9 +12906,13 @@ function recentUsageLines(entries) {
12873
12906
  for (const entry of entries) {
12874
12907
  const op = `${humanize(entry.provider)} ${humanize(entry.operation)}`.trim();
12875
12908
  const roughUsd = Number(entry.rough_usd_cost);
12876
- const usdText = entry.charge_state !== "pending" && entry.rough_usd_cost !== null && entry.rough_usd_cost !== void 0 && Number.isFinite(roughUsd) ? ` (\u2248$${roughUsd.toFixed(2)})` : "";
12877
- 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}`;
12878
- const state = entry.charge_state === "temporary_hold" ? "temporary hold, final charge pending" : entry.charge_state === "pending" ? "no final charge recorded yet" : entry.status || "completed";
12909
+ const credits = entry.credits !== null && entry.credits !== void 0 && String(entry.credits).trim().length > 0 && Number.isFinite(Number(entry.credits)) ? Number(entry.credits) : null;
12910
+ const temporaryHold = entry.charge_state === "temporary_hold";
12911
+ const pending = entry.charge_state === "pending" || entry.charge_finality === "pending";
12912
+ const unknown = entry.charge_finality === "unknown" || credits === null;
12913
+ const usdText = !pending && !unknown && entry.rough_usd_cost !== null && entry.rough_usd_cost !== void 0 && Number.isFinite(roughUsd) ? ` (\u2248$${roughUsd.toFixed(2)})` : "";
12914
+ 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}`;
12915
+ const state = temporaryHold ? "temporary hold, final charge pending" : pending ? "no final charge recorded yet" : entry.status || "unknown";
12879
12916
  const auditBits = [
12880
12917
  entry.outcome ? `outcome=${entry.outcome}` : null,
12881
12918
  entry.pricing_basis ? `priced_by=${entry.pricing_basis}` : null,
@@ -13072,6 +13109,7 @@ async function handleUsage(options) {
13072
13109
  const recentLines = recentUsageLines(
13073
13110
  Array.isArray(recent.entries) ? recent.entries : []
13074
13111
  );
13112
+ 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;
13075
13113
  const lines = options.requestId ? [`Charge lookup: ${options.requestId}`, ...recentLines] : [
13076
13114
  `Balance: ${payload.balance ?? "(unknown)"}`,
13077
13115
  `Last 30 days usage: ${last30Usage ?? "(unknown)"}`,
@@ -13080,8 +13118,10 @@ async function handleUsage(options) {
13080
13118
  ...options.runId && recent.run_id ? [
13081
13119
  `Run spend: ${(payload.run ?? {}).spent_credits ?? "(unknown)"} Deepline Credits`
13082
13120
  ] : [],
13121
+ ...matchingActivity ? [matchingActivity] : [],
13083
13122
  ...recentLines,
13084
- ...recent.has_more === true || recent.incomplete === true ? ["List truncated \u2014 more recent calls match this query."] : [],
13123
+ ...recent.has_more === true ? ["More activity pages are available."] : [],
13124
+ ...recent.incomplete === true ? ["Recent activity is incomplete; the matching count may be higher."] : [],
13085
13125
  ...nextPage ? [`Next page: ${nextPage}`] : [],
13086
13126
  ...!nextPage && (recent.has_more === true || recent.incomplete === true) ? [
13087
13127
  "No continuation is available for this view. Use deepline billing ledger export all --json for the full ledger."
@@ -13161,7 +13201,13 @@ async function handleLimitOff(options) {
13161
13201
  async function exportLedger(http, outputPath, options) {
13162
13202
  let summary = { row_count: 0, net_delta_credits: 0 };
13163
13203
  let initialized = false;
13204
+ let pageNumber = 0;
13205
+ console.error(`Exporting billing ledger to ${outputPath}`);
13164
13206
  for await (const entries of iterateCursorPages(async (cursor) => {
13207
+ pageNumber += 1;
13208
+ console.error(
13209
+ `Fetching page ${pageNumber}; ${summary.row_count} rows written.`
13210
+ );
13165
13211
  const params = new URLSearchParams({ limit: "5000" });
13166
13212
  if (cursor) params.set("cursor", cursor);
13167
13213
  if (options.sinceAt !== null)
@@ -13188,7 +13234,11 @@ async function exportLedger(http, outputPath, options) {
13188
13234
  const rows = entries.map(ledgerApiEntryToRow);
13189
13235
  await appendFile(outputPath, ledgerRowsToCsv(rows, false), "utf-8");
13190
13236
  summary = summarizeLedgerRows(summary, rows);
13237
+ console.error(
13238
+ `Wrote page ${pageNumber}; ${summary.row_count} rows written.`
13239
+ );
13191
13240
  }
13241
+ console.error(`Export complete: ${summary.row_count} rows written.`);
13192
13242
  return summary;
13193
13243
  }
13194
13244
  async function handleHistory(options) {
@@ -13988,6 +14038,8 @@ function registerBillingCommands(program) {
13988
14038
  `
13989
14039
  Concepts:
13990
14040
  Billing commands show Deepline credits, not raw provider spend.
14041
+ Balance is shared by the workspace; concurrent work changes it. Use a job_id
14042
+ charge lookup to attribute one tool command instead of comparing balances.
13991
14043
  checkout/subscribe/redeem-code can open a browser unless --no-open is set.
13992
14044
 
13993
14045
  Examples:
@@ -13997,6 +14049,10 @@ Examples:
13997
14049
  deepline billing plans --json
13998
14050
  deepline billing subscription status --json
13999
14051
 
14052
+ # Price a tool before execution; look up its exact charge afterward
14053
+ deepline tools describe <tool-id> --pricing-only
14054
+ deepline billing usage --request-id <job_id> --json
14055
+
14000
14056
  # Buy credits or a plan
14001
14057
  deepline billing top-up 1000 --json
14002
14058
  deepline billing checkout --credits 1000 --no-open --json
@@ -14018,6 +14074,8 @@ Examples:
14018
14074
  `
14019
14075
  Notes:
14020
14076
  Read-only. Shows the current Deepline credit balance for the active workspace.
14077
+ The balance includes concurrent workspace activity, so a before/after difference
14078
+ cannot isolate one command. Use billing usage --request-id <job_id> --json.
14021
14079
 
14022
14080
  Examples:
14023
14081
  deepline billing balance
@@ -14030,6 +14088,9 @@ Examples:
14030
14088
  Notes:
14031
14089
  Read-only. Shows last-30-day Deepline credit usage plus a bounded recent-call
14032
14090
  page. Use --limit/--cursor to paginate the recent-call section.
14091
+ For one tool command, use the job_id returned by tools execute, or its next.billing
14092
+ command. Pending charges and temporary holds are not final spend; unknown means
14093
+ final charge evidence is unavailable. Workspace balance changes include other work.
14033
14094
 
14034
14095
  Examples:
14035
14096
  deepline billing usage
@@ -29981,7 +30042,23 @@ async function handleRunsList(args) {
29981
30042
  }
29982
30043
  }
29983
30044
  if (!playName && !statusFilter) {
29984
- console.error(usage);
30045
+ const message = "runs list requires --play or --status.";
30046
+ const next = {
30047
+ discover: "deepline plays list --json",
30048
+ running: "deepline runs list --status running --json"
30049
+ };
30050
+ console.error(
30051
+ `${message}
30052
+ ${usage}
30053
+ Discover Plays: ${next.discover}
30054
+ Active runs: ${next.running}`
30055
+ );
30056
+ if (argsWantJson(args)) {
30057
+ printCommandEnvelope(
30058
+ { ok: false, exitCode: 1, code: "RUN_FILTER_REQUIRED", message, next },
30059
+ { json: true }
30060
+ );
30061
+ }
29985
30062
  return 1;
29986
30063
  }
29987
30064
  if ((offset ?? 0) > 0 && !playName) {
@@ -32414,11 +32491,15 @@ Examples:
32414
32491
  "after",
32415
32492
  `
32416
32493
  Notes:
32494
+ Requires --play or --status. Discover Play references with deepline plays list --json.
32417
32495
  Bounded inventory for a play's recent runs. Use --compact for agent loops.
32496
+ Use the exact qualified Play reference, such as workspace/my-play or prebuilt/my-play.
32497
+ --offset requires --play; narrow status-only lists with a Play reference to paginate.
32418
32498
  Common statuses include running, completed, failed, and stopped.
32419
32499
 
32420
32500
  Examples:
32421
32501
  deepline runs list --play my-play
32502
+ deepline runs list --play workspace/my-play --json
32422
32503
  deepline runs list --play my-play --status failed --compact --json
32423
32504
  deepline runs list --status running --compact --json
32424
32505
  `
@@ -49976,11 +50057,17 @@ var CapabilityDescription = class _CapabilityDescription {
49976
50057
  legacyCost.pricingModel ?? legacyCost.pricing_model
49977
50058
  );
49978
50059
  const pricingModel = unit === "call" ? "fixed" : unit === "result" || unit === "page" ? `per_${unit}` : unit === "usage" ? "provider_usage" : legacyPricingModel;
49979
- const canonicalCredits = numberValue(
49980
- pricing.creditsPerUnit ?? pricing.credits_per_unit
49981
- );
49982
- const canonicalUsd = numberValue(
49983
- pricing.usdPerUnit ?? pricing.usd_per_unit
50060
+ const canonicalCredits = pricingNumber(
50061
+ pricing,
50062
+ "creditsPerUnit",
50063
+ "credits_per_unit",
50064
+ this.#catalogEntry.deeplineCreditsPerPricingUnit ?? this.#catalogEntry.deepline_credits_per_pricing_unit
50065
+ );
50066
+ const canonicalUsd = pricingNumber(
50067
+ pricing,
50068
+ "usdPerUnit",
50069
+ "usd_per_unit",
50070
+ this.#catalogEntry.deeplineUsdPerPricingUnit ?? this.#catalogEntry.deepline_usd_per_pricing_unit
49984
50071
  );
49985
50072
  const billingSource = stringValue4(
49986
50073
  this.#catalogEntry.billingSource ?? this.#catalogEntry.billing_source
@@ -49999,12 +50086,8 @@ var CapabilityDescription = class _CapabilityDescription {
49999
50086
  ),
50000
50087
  billingSource,
50001
50088
  billingSourceLabel,
50002
- deeplineCreditsPerPricingUnit: isFree ? 0 : canonicalCredits ?? numberValue(
50003
- this.#catalogEntry.deeplineCreditsPerPricingUnit ?? this.#catalogEntry.deepline_credits_per_pricing_unit
50004
- ),
50005
- deeplineUsdPerPricingUnit: isFree ? 0 : canonicalUsd ?? numberValue(
50006
- this.#catalogEntry.deeplineUsdPerPricingUnit ?? this.#catalogEntry.deepline_usd_per_pricing_unit
50007
- )
50089
+ deeplineCreditsPerPricingUnit: isFree ? 0 : canonicalCredits,
50090
+ deeplineUsdPerPricingUnit: isFree ? 0 : canonicalUsd
50008
50091
  };
50009
50092
  }
50010
50093
  };
@@ -50017,6 +50100,13 @@ function stringValue4(value) {
50017
50100
  function numberValue(value) {
50018
50101
  return typeof value === "number" && Number.isFinite(value) ? value : null;
50019
50102
  }
50103
+ function pricingNumber(pricing, canonicalKey, aliasKey, legacyValue) {
50104
+ for (const key of [canonicalKey, aliasKey]) {
50105
+ if (Object.prototype.hasOwnProperty.call(pricing, key))
50106
+ return numberValue(pricing[key]);
50107
+ }
50108
+ return numberValue(legacyValue);
50109
+ }
50020
50110
 
50021
50111
  // src/cli/tool-connection-status.ts
50022
50112
  function toolConnectionStatusMessage(input2) {
@@ -50610,11 +50700,15 @@ Concepts:
50610
50700
  Common commands:
50611
50701
  deepline tools search email --json
50612
50702
  deepline tools describe hunter_email_verifier --json
50703
+ deepline tools describe hunter_email_verifier --pricing-only --json
50613
50704
  deepline tools execute hunter_email_verifier --input '{"email":"a@b.com"}'
50705
+ deepline billing usage --request-id <job_id> --json
50614
50706
 
50615
50707
  Output:
50616
50708
  Use describe for tool contracts.
50617
50709
  Use execute to run a tool.
50710
+ Read pricing before execution; use the returned next.billing command for its
50711
+ exact charge. Workspace balance changes also include other callers' activity.
50618
50712
  `
50619
50713
  );
50620
50714
  tools.command("list [category]").description("Browse tool categories, or list every tool in a category.").addHelpText(
@@ -50740,6 +50834,7 @@ Notes:
50740
50834
  Examples:
50741
50835
  deepline tools describe hunter_email_verifier
50742
50836
  deepline tools describe hunter_email_verifier --pricing-only
50837
+ deepline tools describe hunter_email_verifier --pricing-only --json
50743
50838
  deepline tools describe hunter_email_verifier --schema-only
50744
50839
  deepline tools describe hunter_email_verifier --examples-only
50745
50840
  deepline tools describe hunter_email_verifier --json
@@ -50789,10 +50884,15 @@ Notes:
50789
50884
  waterfalls, row maps, checkpoints, and retries.
50790
50885
  Calling a provider-backed tool can spend Deepline credits. Use --json for the
50791
50886
  stable result payload plus output preview and debugging helpers.
50887
+ Read pricing first with tools describe <toolId> --pricing-only --json.
50888
+ Use the returned next.billing command to look up this execution's exact charge;
50889
+ workspace balance changes also include other callers' activity.
50792
50890
  --timeout sets this CLI request's HTTP deadline; it does not cancel provider work.
50793
50891
 
50794
50892
  Examples:
50795
50893
  deepline tools execute hunter_email_verifier --input '{"email":"a@b.com"}'
50894
+ deepline tools describe hunter_email_verifier --pricing-only --json
50895
+ deepline billing usage --request-id <job_id> --json
50796
50896
  deepline tools execute bounceban_verify_bulk --input @batch.json --timeout 10m --json
50797
50897
  deepline tools execute hunter_email_verifier -p email=a@b.com
50798
50898
  deepline tools execute test_rate_limit --input '{"key":"smoke"}' --timeout 90s --json
@@ -50896,6 +50996,38 @@ async function getTool(toolId, options = {}) {
50896
50996
  );
50897
50997
  return 2;
50898
50998
  }
50999
+ const onlyModes = [
51000
+ options.pricingOnly,
51001
+ options.schemaOnly,
51002
+ options.examplesOnly,
51003
+ options.gettersOnly
51004
+ ].filter(Boolean).length;
51005
+ if (onlyModes > 1) {
51006
+ console.error(
51007
+ "Use only one of --pricing-only, --schema-only, --examples-only, or --getters-only."
51008
+ );
51009
+ return 2;
51010
+ }
51011
+ if (options.pricingOnly) {
51012
+ const lines = toolPricingOnlyLines(tool, toolId);
51013
+ if (inferenceQuote)
51014
+ lines.push(...inferenceQuoteSummaryLines(inferenceQuote));
51015
+ printCommandEnvelope(
51016
+ {
51017
+ toolId: String(tool.toolId || toolId),
51018
+ cost: Capability.fromCatalogEntry(tool).describe().customerCost(),
51019
+ ...modelDescription ? { modelOptions: modelDescription } : {},
51020
+ ...isMonitorTypeTool(tool) ? { pricing: recordField2(tool, "pricing") } : {},
51021
+ ...inferenceQuote ? { inferenceQuote } : {}
51022
+ },
51023
+ {
51024
+ json: Boolean(options.json || options.contractJson),
51025
+ text: `${lines.join("\n")}
51026
+ `
51027
+ }
51028
+ );
51029
+ return 0;
51030
+ }
50899
51031
  if (options.contractJson) {
50900
51032
  printCompactJson({
50901
51033
  ...toolContractJsonForDescribe(tool, toolId),
@@ -50913,23 +51045,6 @@ async function getTool(toolId, options = {}) {
50913
51045
  });
50914
51046
  return 0;
50915
51047
  }
50916
- const onlyModes = [
50917
- options.pricingOnly,
50918
- options.schemaOnly,
50919
- options.examplesOnly,
50920
- options.gettersOnly
50921
- ].filter(Boolean).length;
50922
- if (onlyModes > 1) {
50923
- console.error(
50924
- "Use only one of --pricing-only, --schema-only, --examples-only, or --getters-only."
50925
- );
50926
- return 2;
50927
- }
50928
- if (options.pricingOnly) {
50929
- printToolPricingOnly(tool, toolId);
50930
- if (inferenceQuote) printInferenceQuoteSummary(inferenceQuote);
50931
- return 0;
50932
- }
50933
51048
  if (options.schemaOnly) {
50934
51049
  printToolSchemaOnly(tool, toolId);
50935
51050
  if (inferenceQuote) printInferenceQuoteSummary(inferenceQuote);
@@ -50970,11 +51085,16 @@ ${formatModelDescription(modelDescription)}`);
50970
51085
  if (inferenceQuote) printInferenceQuoteSummary(inferenceQuote);
50971
51086
  return 0;
50972
51087
  }
50973
- function printInferenceQuoteSummary(_quote) {
50974
- console.log("");
50975
- console.log("Inference quote:");
50976
- console.log("- Temporary hold: priced estimate (minimum 0.02 credits)");
50977
- console.log("- Final charge: actual usage");
51088
+ function inferenceQuoteSummaryLines(_quote) {
51089
+ return [
51090
+ "",
51091
+ "Inference quote:",
51092
+ "- Temporary hold: priced estimate (minimum 0.02 credits)",
51093
+ "- Final charge: actual usage"
51094
+ ];
51095
+ }
51096
+ function printInferenceQuoteSummary(quote) {
51097
+ for (const line of inferenceQuoteSummaryLines(quote)) console.log(line);
50978
51098
  }
50979
51099
  function toolContractJsonForDescribe(tool, requestedToolId) {
50980
51100
  const toolId = String(tool.toolId || requestedToolId);
@@ -51033,6 +51153,7 @@ function toolContractJsonForDescribe(tool, requestedToolId) {
51033
51153
  toolId,
51034
51154
  provider: tool.provider,
51035
51155
  displayName: tool.displayName,
51156
+ cost: pricing,
51036
51157
  description: tool.description,
51037
51158
  categories: tool.categories,
51038
51159
  ...deprecated ? {
@@ -51052,7 +51173,6 @@ function toolContractJsonForDescribe(tool, requestedToolId) {
51052
51173
  } : {},
51053
51174
  ...executionMetadata ? { executionMetadata } : {},
51054
51175
  ...batchCapability ? { batchCapability } : {},
51055
- cost: pricing,
51056
51176
  getters: {
51057
51177
  extractedLists,
51058
51178
  extractedValues
@@ -51128,7 +51248,7 @@ function printMonitorTypeStreams(tool) {
51128
51248
  console.log(`- ${name}: ${cols.join(", ")}`);
51129
51249
  }
51130
51250
  }
51131
- function printMonitorTypePricing(tool) {
51251
+ function monitorTypePricingLines(tool) {
51132
51252
  const pricing = recordField2(tool, "pricing");
51133
51253
  const byType = recordField2(
51134
51254
  pricing,
@@ -51137,17 +51257,20 @@ function printMonitorTypePricing(tool) {
51137
51257
  );
51138
51258
  const keys = Object.keys(byType);
51139
51259
  if (!keys.length) {
51140
- console.log("Pricing: Deepline credits per accepted event (see --json)");
51141
- return;
51260
+ return ["Pricing: Deepline credits per accepted event (see --json)"];
51142
51261
  }
51143
- console.log("Pricing (Deepline credits per accepted event):");
51262
+ const lines = ["Pricing (Deepline credits per accepted event):"];
51144
51263
  for (const key of keys) {
51145
51264
  const entry = isRecord13(byType[key]) ? byType[key] : {};
51146
51265
  const credits = numberField2(entry, "deepline_credits", "deeplineCredits");
51147
51266
  const display = stringField2(entry, "display");
51148
51267
  const shown = display || (credits !== null ? `${formatDecimal(credits)} credits/event` : "see --json");
51149
- console.log(`- ${key}: ${shown}`);
51268
+ lines.push(`- ${key}: ${shown}`);
51150
51269
  }
51270
+ return lines;
51271
+ }
51272
+ function printMonitorTypePricing(tool) {
51273
+ for (const line of monitorTypePricingLines(tool)) console.log(line);
51151
51274
  }
51152
51275
  function printMonitorTypeDeploy(tool) {
51153
51276
  const deploy = recordField2(tool, "deploy");
@@ -51285,13 +51408,12 @@ function printCompactToolContract(tool, requestedToolId) {
51285
51408
  `More: deepline tools describe ${contract.toolId} --pricing-only | --schema-only | --examples-only | --getters-only | --json`
51286
51409
  );
51287
51410
  }
51288
- function printToolPricingOnly(tool, requestedToolId, options = {}) {
51411
+ function toolPricingOnlyLines(tool, requestedToolId, options = {}) {
51289
51412
  if (isMonitorTypeTool(tool)) {
51290
- printMonitorTypePricing(tool);
51291
- return;
51413
+ return monitorTypePricingLines(tool);
51292
51414
  }
51293
- const contract = toolContractJsonForDescribe(tool, requestedToolId);
51294
- const cost = isRecord13(contract.cost) ? contract.cost : {};
51415
+ const toolId = String(tool.toolId || requestedToolId);
51416
+ const cost = Capability.fromCatalogEntry(tool).describe().customerCost();
51295
51417
  const pricingModel = stringField2(cost, "pricingModel") || "unknown";
51296
51418
  const billing = stringField2(cost, "billingSourceLabel") || stringField2(cost, "billingSource") || stringField2(cost, "billingMode") || "unknown";
51297
51419
  const explicitUnit = stringField2(cost, "unit");
@@ -51301,8 +51423,14 @@ function printToolPricingOnly(tool, requestedToolId, options = {}) {
51301
51423
  const displayText = stringField2(cost, "displayText");
51302
51424
  const summary = stringField2(cost, "summary");
51303
51425
  const price = displayText || summary || (credits !== null ? `${formatDecimal(credits)} Deepline credits${usd !== null ? ` / ${formatUsd(usd)}` : ""} per ${unit}` : "pricing unavailable");
51304
- console.log(`${options.heading ?? `Pricing: ${contract.toolId}`}: ${price}`);
51305
- console.log(`Billing: ${billing}`);
51426
+ return [
51427
+ `${options.heading ?? `Pricing: ${toolId}`}: ${price}`,
51428
+ `Billing: ${billing}`
51429
+ ];
51430
+ }
51431
+ function printToolPricingOnly(tool, requestedToolId, options = {}) {
51432
+ for (const line of toolPricingOnlyLines(tool, requestedToolId, options))
51433
+ console.log(line);
51306
51434
  }
51307
51435
  function printToolSchemaOnly(tool, requestedToolId) {
51308
51436
  if (isMonitorTypeTool(tool)) {
@@ -51515,6 +51643,7 @@ function toolMetadataJsonForDescribe(tool, requestedToolId) {
51515
51643
  } = tool;
51516
51644
  const outputSchemaRecord = recordField2(tool, "outputSchema", "output_schema");
51517
51645
  return {
51646
+ cost: Capability.fromCatalogEntry(tool).describe().customerCost(),
51518
51647
  ...publicTool,
51519
51648
  toolId,
51520
51649
  provider: tool.provider,
@@ -51526,7 +51655,6 @@ function toolMetadataJsonForDescribe(tool, requestedToolId) {
51526
51655
  )
51527
51656
  } : {},
51528
51657
  inputFields: inputFields.map(inputFieldJsonForDescribe),
51529
- cost: Capability.fromCatalogEntry(tool).describe().customerCost(),
51530
51658
  usageGuidance,
51531
51659
  runtimeOutputHelp: {
51532
51660
  contract: "tools describe shows declared schema and Deepline getters; it is not an observed provider response.",
package/dist/index.d.mts CHANGED
@@ -4738,6 +4738,8 @@ type BillingRecentUsageEntry = {
4738
4738
  outcome: string | null;
4739
4739
  billing_note: string | null;
4740
4740
  charge_state: 'posted' | 'temporary_hold' | 'hold_release' | 'pending' | 'free' | 'failed';
4741
+ /** Final billing truth may be unknown even after execution completes. */
4742
+ charge_finality?: 'final' | 'pending' | 'unknown';
4741
4743
  rough_usd_cost: number | null;
4742
4744
  created_at: string;
4743
4745
  };
@@ -4767,6 +4769,10 @@ type BillingUsageResult = {
4767
4769
  run_id: string | null;
4768
4770
  request_id?: string;
4769
4771
  total: number;
4772
+ /** Only true when total covers the complete matching history. */
4773
+ total_is_exact?: boolean;
4774
+ /** Proven matching entries, without assuming unscanned rows match. */
4775
+ total_lower_bound?: number;
4770
4776
  offset: number;
4771
4777
  limit: number;
4772
4778
  next_offset: number;
package/dist/index.d.ts CHANGED
@@ -4738,6 +4738,8 @@ type BillingRecentUsageEntry = {
4738
4738
  outcome: string | null;
4739
4739
  billing_note: string | null;
4740
4740
  charge_state: 'posted' | 'temporary_hold' | 'hold_release' | 'pending' | 'free' | 'failed';
4741
+ /** Final billing truth may be unknown even after execution completes. */
4742
+ charge_finality?: 'final' | 'pending' | 'unknown';
4741
4743
  rough_usd_cost: number | null;
4742
4744
  created_at: string;
4743
4745
  };
@@ -4767,6 +4769,10 @@ type BillingUsageResult = {
4767
4769
  run_id: string | null;
4768
4770
  request_id?: string;
4769
4771
  total: number;
4772
+ /** Only true when total covers the complete matching history. */
4773
+ total_is_exact?: boolean;
4774
+ /** Proven matching entries, without assuming unscanned rows match. */
4775
+ total_lower_bound?: number;
4770
4776
  offset: number;
4771
4777
  limit: number;
4772
4778
  next_offset: number;