deepline 0.2.16 → 0.2.18

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.
@@ -77,6 +77,7 @@ import type {
77
77
  ToolMetadata,
78
78
  CustomerDbQueryResult,
79
79
  DeeplineAgentModelDescription,
80
+ InferenceQuote,
80
81
  } from './types.js';
81
82
  import type { MonitorDefinition } from './monitors.js';
82
83
  import type { PlayStagedFileRef } from './plays/local-file-discovery.js';
@@ -1919,6 +1920,22 @@ export class DeeplineClient {
1919
1920
  );
1920
1921
  }
1921
1922
 
1923
+ /**
1924
+ * Quote dynamic AI inference pricing for a concrete payload.
1925
+ *
1926
+ * The result separates a planning estimate from a proven authorization
1927
+ * maximum and contains Deepline credits only.
1928
+ */
1929
+ async quoteInferenceTool(
1930
+ toolId: 'ai_inference' | 'deeplineagent',
1931
+ payload: Record<string, unknown>,
1932
+ ): Promise<InferenceQuote> {
1933
+ return this.http.post<InferenceQuote>(
1934
+ `/api/v2/integrations/${encodeURIComponent(toolId)}/quote`,
1935
+ payload,
1936
+ );
1937
+ }
1938
+
1922
1939
  /**
1923
1940
  * Execute a tool and return the standard execution envelope.
1924
1941
  *
@@ -160,7 +160,7 @@ export const SDK_RELEASE = {
160
160
  // 0.2.0 makes Dataset Handles uniformly async-only after 0.1.320 briefly
161
161
  // exposed storage-dependent synchronous access. This deliberate minor
162
162
  // release keeps lazy paging semantics independent of row residency.
163
- version: '0.2.16',
163
+ version: '0.2.18',
164
164
  contracts: {
165
165
  api: {
166
166
  name: 'sdk-http-api',
@@ -336,8 +336,51 @@ export interface DeeplineAgentModelDescription {
336
336
  };
337
337
  caveats: string[];
338
338
  sources: string[];
339
+ inferencePricing: InferenceDynamicPricingCapability;
339
340
  }
340
341
 
342
+ export interface InferenceDynamicPricingCapability {
343
+ settlement: 'actual_usage';
344
+ staticUnitPrice: null;
345
+ quoteEndpointTemplate: string;
346
+ supportedQualities: Array<'bounded_max' | 'estimate_only' | 'unavailable'>;
347
+ payloadFields: string[];
348
+ }
349
+
350
+ export type InferenceQuoteAssumptions = {
351
+ modelCallCount: number;
352
+ planningModelCallCount: number;
353
+ estimatedInputTokens: number;
354
+ estimatedOutputTokens: number;
355
+ maxOutputTokens: number | null;
356
+ candidateRouteCount: number;
357
+ pricedRouteCount: number;
358
+ inputBound: 'proven_request_tokens' | 'catalog_context' | 'not_proven';
359
+ inputBoundProofId?: string;
360
+ };
361
+
362
+ export type InferenceQuote = {
363
+ quality: 'bounded_max' | 'estimate_only' | 'unavailable';
364
+ estimate:
365
+ | {
366
+ quality: 'estimate_only';
367
+ credits: number;
368
+ assumptions: InferenceQuoteAssumptions;
369
+ }
370
+ | { quality: 'unavailable'; assumptions: InferenceQuoteAssumptions };
371
+ authorization:
372
+ | {
373
+ quality: 'bounded_max';
374
+ maximumCredits: number;
375
+ assumptions: InferenceQuoteAssumptions;
376
+ }
377
+ | {
378
+ quality: 'estimate_only' | 'unavailable';
379
+ assumptions: InferenceQuoteAssumptions;
380
+ };
381
+ settlement: 'actual_usage';
382
+ };
383
+
341
384
  /**
342
385
  * Query options for ranked tool/provider discovery.
343
386
  */
@@ -7617,6 +7617,7 @@ export class PlayContextImpl implements ScalarPlayAuthoringRuntimeContext {
7617
7617
  const compositionNamespace = this.inlineChildCompositionNamespace(
7618
7618
  resolvedName,
7619
7619
  normalizedKey,
7620
+ input,
7620
7621
  );
7621
7622
  const inlineChildGovernor =
7622
7623
  await this.currentExecutionGovernor.forkInlineChild({
@@ -7728,35 +7729,42 @@ export class PlayContextImpl implements ScalarPlayAuthoringRuntimeContext {
7728
7729
  }
7729
7730
 
7730
7731
  /**
7731
- * Replay-stable composition namespace for one inline `ctx.runPlay`
7732
- * invocation. Format `child:<playName>#<callKey>[@<rowScope>]`:
7732
+ * Replay-stable receipt namespace for primitives executed by one inline
7733
+ * `ctx.runPlay` invocation. Format
7734
+ * `child:<playName>#<callKey>@<invocationDigest>`:
7733
7735
  *
7734
7736
  * - `callKey` is the author's normalized `ctx.runPlay(key, ...)` call key,
7735
7737
  * so distinct call sites never collide.
7736
- * - `rowScope` (table namespace + row key) is appended when the invocation
7737
- * runs inside a map/dataset row resolver, so the SAME call site invoked
7738
- * across rows scopes each row's child step receipts separately.
7738
+ * - `invocationDigest` hashes the resolved child input and inherited row
7739
+ * scope. The row scope keeps concurrent map invocations isolated; the
7740
+ * input prevents two different people at an otherwise identical caller
7741
+ * row from ever recovering one another's child step or fetch receipt.
7739
7742
  *
7740
- * The namespace is derived purely from authored, content-stable inputs
7741
- * never from arrival order so a retried run attempt reproduces the same
7742
- * namespace under any row-completion interleaving and the child's tool
7743
- * receipts (owned by the PARENT run) recover instead of re-billing. Inline
7744
- * children carry NO durable run id this namespace is their only identity.
7745
- * See ADR 0013.
7743
+ * This is not a `runPlay` result cache: `runPlay` always executes the child.
7744
+ * It only scopes the child's own durable step and fetch receipts. Parent run
7745
+ * identity is intentionally excluded, allowing semantically identical child
7746
+ * work to recover across retries and parent runs without permitting a
7747
+ * different child input to reuse a result. See ADR 0013.
7746
7748
  */
7747
7749
  private inlineChildCompositionNamespace(
7748
7750
  childPlayName: string,
7749
7751
  normalizedKey: string,
7752
+ input: Record<string, unknown>,
7750
7753
  ): string {
7751
7754
  const rowScope = rowContext.getStore();
7752
- const rowScopeKey = rowScope
7753
- ? `${rowScope.tableNamespace ?? rowScope.fieldName ?? 'rows'}:${
7754
- rowScope.rowKey ?? String(rowScope.rowId)
7755
- }`
7756
- : '';
7757
- const namespace = `child:${childPlayName}#${normalizedKey}${
7758
- rowScopeKey ? `@${rowScopeKey}` : ''
7759
- }`;
7755
+ const invocationScope = buildDurableRunPlayInvocationScope({
7756
+ childPlayName,
7757
+ input,
7758
+ rowScope: rowScope
7759
+ ? {
7760
+ tableNamespace: rowScope.tableNamespace ?? null,
7761
+ rowKey: rowScope.rowKey ?? null,
7762
+ rowId: rowScope.rowKey ? null : rowScope.rowId,
7763
+ fieldName: rowScope.fieldName ?? null,
7764
+ }
7765
+ : null,
7766
+ });
7767
+ const namespace = `child:${childPlayName}#${normalizedKey}@${invocationScope}`;
7760
7768
  if (rowScope) {
7761
7769
  const namespaces = (rowScope.inlineChildInvocationNamespaces ??=
7762
7770
  new Set<string>());
@@ -8138,6 +8146,11 @@ export class PlayContextImpl implements ScalarPlayAuthoringRuntimeContext {
8138
8146
  rowId: rowStore.rowKey ? null : rowStore.rowId,
8139
8147
  fieldName: rowStore.fieldName ?? null,
8140
8148
  callIndex,
8149
+ // Row scope prevents unrelated map cells from sharing a
8150
+ // checkpoint. A supplied semantic key identifies the actual
8151
+ // work (for example, ctx.runSteps hashes its current input),
8152
+ // so it must refine row scope rather than being discarded.
8153
+ semanticKey: options?.semanticKey ?? null,
8141
8154
  }),
8142
8155
  )
8143
8156
  : options?.semanticKey,
@@ -1,3 +1,5 @@
1
+ import { ToolExecutionError } from '../tool-execution-error';
2
+
1
3
  const CLOUDFLARE_DURABLE_OBJECT_RESET_RE =
2
4
  /Durable Object.*(?:code (?:was|has been) updated|storage caused object)/;
3
5
  const CLOUDFLARE_WORKER_SUBREQUEST_LIMIT_RE =
@@ -280,6 +282,20 @@ function toErrorText(error: unknown): string {
280
282
  export function normalizePlayRunFailure(error: unknown): PlayRunFailureDetails {
281
283
  const rawCause = toErrorText(error);
282
284
  const cause = boundedFailureText(rawCause);
285
+ if (
286
+ error instanceof ToolExecutionError &&
287
+ error.origin === 'deepline' &&
288
+ error.category === 'billing' &&
289
+ error.code !== 'BILLING_UNAVAILABLE'
290
+ ) {
291
+ return {
292
+ code: error.code?.trim() || 'BILLING_DENIED',
293
+ phase: 'billing',
294
+ message: cause,
295
+ retryable: false,
296
+ cause,
297
+ };
298
+ }
283
299
  if (
284
300
  (error &&
285
301
  typeof error === 'object' &&
package/dist/cli/index.js CHANGED
@@ -1044,7 +1044,7 @@ var SDK_RELEASE = {
1044
1044
  // 0.2.0 makes Dataset Handles uniformly async-only after 0.1.320 briefly
1045
1045
  // exposed storage-dependent synchronous access. This deliberate minor
1046
1046
  // release keeps lazy paging semantics independent of row residency.
1047
- version: "0.2.16",
1047
+ version: "0.2.18",
1048
1048
  contracts: {
1049
1049
  api: {
1050
1050
  name: "sdk-http-api",
@@ -4040,6 +4040,18 @@ var DeeplineClient = class {
4040
4040
  }
4041
4041
  );
4042
4042
  }
4043
+ /**
4044
+ * Quote dynamic AI inference pricing for a concrete payload.
4045
+ *
4046
+ * The result separates a planning estimate from a proven authorization
4047
+ * maximum and contains Deepline credits only.
4048
+ */
4049
+ async quoteInferenceTool(toolId, payload) {
4050
+ return this.http.post(
4051
+ `/api/v2/integrations/${encodeURIComponent(toolId)}/quote`,
4052
+ payload
4053
+ );
4054
+ }
4043
4055
  /**
4044
4056
  * Execute a tool and return the standard execution envelope.
4045
4057
  *
@@ -33005,11 +33017,15 @@ Examples:
33005
33017
  deepline tools describe hunter_email_verifier --examples-only
33006
33018
  deepline tools describe hunter_email_verifier --json
33007
33019
  deepline tools describe deeplineagent --model openai/gpt-5.5 --json
33020
+ deepline tools describe ai_inference --estimate-payload @payload.json --json
33008
33021
  deepline tools execute hunter_email_verifier --input '{"email":"a@b.com"}'
33009
33022
  `
33010
33023
  ).option("--json", "Emit JSON output. Also automatic when stdout is piped").option(
33011
33024
  "--model <model>",
33012
33025
  "For deeplineagent, include AI Gateway model/provider option metadata"
33026
+ ).option(
33027
+ "--estimate-payload <payload>",
33028
+ "Quote an ai_inference or deeplineagent JSON payload (inline or @file)"
33013
33029
  ).option("--pricing-only", "Only print pricing and billing semantics").option("--schema-only", "Only print input schema fields").option(
33014
33030
  "--examples-only",
33015
33031
  "Only print runnable examples and sample payloads"
@@ -33032,7 +33048,8 @@ Examples:
33032
33048
  schemaOnly: Boolean(options.schemaOnly),
33033
33049
  examplesOnly: Boolean(options.examplesOnly),
33034
33050
  gettersOnly: Boolean(options.gettersOnly),
33035
- model: typeof options.model === "string" ? options.model : void 0
33051
+ model: typeof options.model === "string" ? options.model : void 0,
33052
+ estimatePayload: typeof options.estimatePayload === "string" ? options.estimatePayload : void 0
33036
33053
  });
33037
33054
  });
33038
33055
  addToolMetadataCommand(tools.command("describe <toolId>").alias("get"));
@@ -33106,6 +33123,23 @@ async function getTool(toolId, options = {}) {
33106
33123
  }
33107
33124
  throw error;
33108
33125
  }
33126
+ let inferenceQuote = null;
33127
+ if (options.estimatePayload) {
33128
+ if (toolId !== "deeplineagent" && toolId !== "ai_inference") {
33129
+ console.error(
33130
+ "--estimate-payload is only supported for deeplineagent and ai_inference."
33131
+ );
33132
+ return 2;
33133
+ }
33134
+ const estimatePayload = parseJsonObjectArgument(
33135
+ options.estimatePayload,
33136
+ "--estimate-payload"
33137
+ );
33138
+ if (options.model && estimatePayload.model === void 0) {
33139
+ estimatePayload.model = options.model;
33140
+ }
33141
+ inferenceQuote = await client2.quoteInferenceTool(toolId, estimatePayload);
33142
+ }
33109
33143
  const modelDescription = options.model && (toolId === "deeplineagent" || toolId === "ai_inference") ? await client2.describeModel(options.model) : null;
33110
33144
  if (options.model && !modelDescription) {
33111
33145
  console.error(
@@ -33117,7 +33151,8 @@ async function getTool(toolId, options = {}) {
33117
33151
  process.stdout.write(
33118
33152
  `${JSON.stringify({
33119
33153
  ...toolContractJsonForDescribe(tool, toolId),
33120
- ...modelDescription ? { modelOptions: modelDescription } : {}
33154
+ ...modelDescription ? { modelOptions: modelDescription } : {},
33155
+ ...inferenceQuote ? { inferenceQuote } : {}
33121
33156
  })}
33122
33157
  `
33123
33158
  );
@@ -33128,7 +33163,8 @@ async function getTool(toolId, options = {}) {
33128
33163
  process.stdout.write(
33129
33164
  `${JSON.stringify({
33130
33165
  ...toolMetadataJsonForDescribe(tool, toolId),
33131
- ...modelDescription ? { modelOptions: modelDescription } : {}
33166
+ ...modelDescription ? { modelOptions: modelDescription } : {},
33167
+ ...inferenceQuote ? { inferenceQuote } : {}
33132
33168
  })}
33133
33169
  `
33134
33170
  );
@@ -33148,18 +33184,22 @@ async function getTool(toolId, options = {}) {
33148
33184
  }
33149
33185
  if (options.pricingOnly) {
33150
33186
  printToolPricingOnly(tool, toolId);
33187
+ if (inferenceQuote) printInferenceQuoteSummary(inferenceQuote);
33151
33188
  return 0;
33152
33189
  }
33153
33190
  if (options.schemaOnly) {
33154
33191
  printToolSchemaOnly(tool, toolId);
33192
+ if (inferenceQuote) printInferenceQuoteSummary(inferenceQuote);
33155
33193
  return 0;
33156
33194
  }
33157
33195
  if (options.examplesOnly) {
33158
33196
  printToolExamplesOnly(tool, toolId);
33197
+ if (inferenceQuote) printInferenceQuoteSummary(inferenceQuote);
33159
33198
  return 0;
33160
33199
  }
33161
33200
  if (options.gettersOnly) {
33162
33201
  printToolGettersOnly(tool, toolId);
33202
+ if (inferenceQuote) printInferenceQuoteSummary(inferenceQuote);
33163
33203
  return 0;
33164
33204
  }
33165
33205
  if (options.compact) {
@@ -33168,13 +33208,15 @@ async function getTool(toolId, options = {}) {
33168
33208
  process.stdout.write(`
33169
33209
  ${formatModelDescription(modelDescription)}`);
33170
33210
  }
33211
+ if (inferenceQuote) printInferenceQuoteSummary(inferenceQuote);
33171
33212
  return 0;
33172
33213
  }
33173
33214
  if (shouldEmitJson()) {
33174
33215
  process.stdout.write(
33175
33216
  `${JSON.stringify({
33176
33217
  ...toolContractJsonForDescribe(tool, toolId),
33177
- ...modelDescription ? { modelOptions: modelDescription } : {}
33218
+ ...modelDescription ? { modelOptions: modelDescription } : {},
33219
+ ...inferenceQuote ? { inferenceQuote } : {}
33178
33220
  })}
33179
33221
  `
33180
33222
  );
@@ -33185,8 +33227,26 @@ ${formatModelDescription(modelDescription)}`);
33185
33227
  process.stdout.write(`
33186
33228
  ${formatModelDescription(modelDescription)}`);
33187
33229
  }
33230
+ if (inferenceQuote) printInferenceQuoteSummary(inferenceQuote);
33188
33231
  return 0;
33189
33232
  }
33233
+ function printInferenceQuoteSummary(quote) {
33234
+ console.log("");
33235
+ console.log("Inference quote:");
33236
+ if (quote.estimate.quality === "estimate_only") {
33237
+ console.log(`- Planning estimate: ${quote.estimate.credits} credits`);
33238
+ } else {
33239
+ console.log("- Planning estimate: unavailable");
33240
+ }
33241
+ if (quote.authorization.quality === "bounded_max") {
33242
+ console.log(
33243
+ `- Maximum authorization: ${quote.authorization.maximumCredits} credits`
33244
+ );
33245
+ } else {
33246
+ console.log(`- Maximum authorization: ${quote.authorization.quality}`);
33247
+ }
33248
+ console.log("- Settlement: actual usage");
33249
+ }
33190
33250
  function toolContractJsonForDescribe(tool, requestedToolId) {
33191
33251
  const toolId = String(tool.toolId || requestedToolId);
33192
33252
  const inputFields = toolInputFieldsForDisplay(
@@ -1030,7 +1030,7 @@ var SDK_RELEASE = {
1030
1030
  // 0.2.0 makes Dataset Handles uniformly async-only after 0.1.320 briefly
1031
1031
  // exposed storage-dependent synchronous access. This deliberate minor
1032
1032
  // release keeps lazy paging semantics independent of row residency.
1033
- version: "0.2.16",
1033
+ version: "0.2.18",
1034
1034
  contracts: {
1035
1035
  api: {
1036
1036
  name: "sdk-http-api",
@@ -4026,6 +4026,18 @@ var DeeplineClient = class {
4026
4026
  }
4027
4027
  );
4028
4028
  }
4029
+ /**
4030
+ * Quote dynamic AI inference pricing for a concrete payload.
4031
+ *
4032
+ * The result separates a planning estimate from a proven authorization
4033
+ * maximum and contains Deepline credits only.
4034
+ */
4035
+ async quoteInferenceTool(toolId, payload) {
4036
+ return this.http.post(
4037
+ `/api/v2/integrations/${encodeURIComponent(toolId)}/quote`,
4038
+ payload
4039
+ );
4040
+ }
4029
4041
  /**
4030
4042
  * Execute a tool and return the standard execution envelope.
4031
4043
  *
@@ -33068,11 +33080,15 @@ Examples:
33068
33080
  deepline tools describe hunter_email_verifier --examples-only
33069
33081
  deepline tools describe hunter_email_verifier --json
33070
33082
  deepline tools describe deeplineagent --model openai/gpt-5.5 --json
33083
+ deepline tools describe ai_inference --estimate-payload @payload.json --json
33071
33084
  deepline tools execute hunter_email_verifier --input '{"email":"a@b.com"}'
33072
33085
  `
33073
33086
  ).option("--json", "Emit JSON output. Also automatic when stdout is piped").option(
33074
33087
  "--model <model>",
33075
33088
  "For deeplineagent, include AI Gateway model/provider option metadata"
33089
+ ).option(
33090
+ "--estimate-payload <payload>",
33091
+ "Quote an ai_inference or deeplineagent JSON payload (inline or @file)"
33076
33092
  ).option("--pricing-only", "Only print pricing and billing semantics").option("--schema-only", "Only print input schema fields").option(
33077
33093
  "--examples-only",
33078
33094
  "Only print runnable examples and sample payloads"
@@ -33095,7 +33111,8 @@ Examples:
33095
33111
  schemaOnly: Boolean(options.schemaOnly),
33096
33112
  examplesOnly: Boolean(options.examplesOnly),
33097
33113
  gettersOnly: Boolean(options.gettersOnly),
33098
- model: typeof options.model === "string" ? options.model : void 0
33114
+ model: typeof options.model === "string" ? options.model : void 0,
33115
+ estimatePayload: typeof options.estimatePayload === "string" ? options.estimatePayload : void 0
33099
33116
  });
33100
33117
  });
33101
33118
  addToolMetadataCommand(tools.command("describe <toolId>").alias("get"));
@@ -33169,6 +33186,23 @@ async function getTool(toolId, options = {}) {
33169
33186
  }
33170
33187
  throw error;
33171
33188
  }
33189
+ let inferenceQuote = null;
33190
+ if (options.estimatePayload) {
33191
+ if (toolId !== "deeplineagent" && toolId !== "ai_inference") {
33192
+ console.error(
33193
+ "--estimate-payload is only supported for deeplineagent and ai_inference."
33194
+ );
33195
+ return 2;
33196
+ }
33197
+ const estimatePayload = parseJsonObjectArgument(
33198
+ options.estimatePayload,
33199
+ "--estimate-payload"
33200
+ );
33201
+ if (options.model && estimatePayload.model === void 0) {
33202
+ estimatePayload.model = options.model;
33203
+ }
33204
+ inferenceQuote = await client2.quoteInferenceTool(toolId, estimatePayload);
33205
+ }
33172
33206
  const modelDescription = options.model && (toolId === "deeplineagent" || toolId === "ai_inference") ? await client2.describeModel(options.model) : null;
33173
33207
  if (options.model && !modelDescription) {
33174
33208
  console.error(
@@ -33180,7 +33214,8 @@ async function getTool(toolId, options = {}) {
33180
33214
  process.stdout.write(
33181
33215
  `${JSON.stringify({
33182
33216
  ...toolContractJsonForDescribe(tool, toolId),
33183
- ...modelDescription ? { modelOptions: modelDescription } : {}
33217
+ ...modelDescription ? { modelOptions: modelDescription } : {},
33218
+ ...inferenceQuote ? { inferenceQuote } : {}
33184
33219
  })}
33185
33220
  `
33186
33221
  );
@@ -33191,7 +33226,8 @@ async function getTool(toolId, options = {}) {
33191
33226
  process.stdout.write(
33192
33227
  `${JSON.stringify({
33193
33228
  ...toolMetadataJsonForDescribe(tool, toolId),
33194
- ...modelDescription ? { modelOptions: modelDescription } : {}
33229
+ ...modelDescription ? { modelOptions: modelDescription } : {},
33230
+ ...inferenceQuote ? { inferenceQuote } : {}
33195
33231
  })}
33196
33232
  `
33197
33233
  );
@@ -33211,18 +33247,22 @@ async function getTool(toolId, options = {}) {
33211
33247
  }
33212
33248
  if (options.pricingOnly) {
33213
33249
  printToolPricingOnly(tool, toolId);
33250
+ if (inferenceQuote) printInferenceQuoteSummary(inferenceQuote);
33214
33251
  return 0;
33215
33252
  }
33216
33253
  if (options.schemaOnly) {
33217
33254
  printToolSchemaOnly(tool, toolId);
33255
+ if (inferenceQuote) printInferenceQuoteSummary(inferenceQuote);
33218
33256
  return 0;
33219
33257
  }
33220
33258
  if (options.examplesOnly) {
33221
33259
  printToolExamplesOnly(tool, toolId);
33260
+ if (inferenceQuote) printInferenceQuoteSummary(inferenceQuote);
33222
33261
  return 0;
33223
33262
  }
33224
33263
  if (options.gettersOnly) {
33225
33264
  printToolGettersOnly(tool, toolId);
33265
+ if (inferenceQuote) printInferenceQuoteSummary(inferenceQuote);
33226
33266
  return 0;
33227
33267
  }
33228
33268
  if (options.compact) {
@@ -33231,13 +33271,15 @@ async function getTool(toolId, options = {}) {
33231
33271
  process.stdout.write(`
33232
33272
  ${formatModelDescription(modelDescription)}`);
33233
33273
  }
33274
+ if (inferenceQuote) printInferenceQuoteSummary(inferenceQuote);
33234
33275
  return 0;
33235
33276
  }
33236
33277
  if (shouldEmitJson()) {
33237
33278
  process.stdout.write(
33238
33279
  `${JSON.stringify({
33239
33280
  ...toolContractJsonForDescribe(tool, toolId),
33240
- ...modelDescription ? { modelOptions: modelDescription } : {}
33281
+ ...modelDescription ? { modelOptions: modelDescription } : {},
33282
+ ...inferenceQuote ? { inferenceQuote } : {}
33241
33283
  })}
33242
33284
  `
33243
33285
  );
@@ -33248,8 +33290,26 @@ ${formatModelDescription(modelDescription)}`);
33248
33290
  process.stdout.write(`
33249
33291
  ${formatModelDescription(modelDescription)}`);
33250
33292
  }
33293
+ if (inferenceQuote) printInferenceQuoteSummary(inferenceQuote);
33251
33294
  return 0;
33252
33295
  }
33296
+ function printInferenceQuoteSummary(quote) {
33297
+ console.log("");
33298
+ console.log("Inference quote:");
33299
+ if (quote.estimate.quality === "estimate_only") {
33300
+ console.log(`- Planning estimate: ${quote.estimate.credits} credits`);
33301
+ } else {
33302
+ console.log("- Planning estimate: unavailable");
33303
+ }
33304
+ if (quote.authorization.quality === "bounded_max") {
33305
+ console.log(
33306
+ `- Maximum authorization: ${quote.authorization.maximumCredits} credits`
33307
+ );
33308
+ } else {
33309
+ console.log(`- Maximum authorization: ${quote.authorization.quality}`);
33310
+ }
33311
+ console.log("- Settlement: actual usage");
33312
+ }
33253
33313
  function toolContractJsonForDescribe(tool, requestedToolId) {
33254
33314
  const toolId = String(tool.toolId || requestedToolId);
33255
33315
  const inputFields = toolInputFieldsForDisplay(
package/dist/index.d.mts CHANGED
@@ -411,7 +411,46 @@ interface DeeplineAgentModelDescription {
411
411
  };
412
412
  caveats: string[];
413
413
  sources: string[];
414
+ inferencePricing: InferenceDynamicPricingCapability;
414
415
  }
416
+ interface InferenceDynamicPricingCapability {
417
+ settlement: 'actual_usage';
418
+ staticUnitPrice: null;
419
+ quoteEndpointTemplate: string;
420
+ supportedQualities: Array<'bounded_max' | 'estimate_only' | 'unavailable'>;
421
+ payloadFields: string[];
422
+ }
423
+ type InferenceQuoteAssumptions = {
424
+ modelCallCount: number;
425
+ planningModelCallCount: number;
426
+ estimatedInputTokens: number;
427
+ estimatedOutputTokens: number;
428
+ maxOutputTokens: number | null;
429
+ candidateRouteCount: number;
430
+ pricedRouteCount: number;
431
+ inputBound: 'proven_request_tokens' | 'catalog_context' | 'not_proven';
432
+ inputBoundProofId?: string;
433
+ };
434
+ type InferenceQuote = {
435
+ quality: 'bounded_max' | 'estimate_only' | 'unavailable';
436
+ estimate: {
437
+ quality: 'estimate_only';
438
+ credits: number;
439
+ assumptions: InferenceQuoteAssumptions;
440
+ } | {
441
+ quality: 'unavailable';
442
+ assumptions: InferenceQuoteAssumptions;
443
+ };
444
+ authorization: {
445
+ quality: 'bounded_max';
446
+ maximumCredits: number;
447
+ assumptions: InferenceQuoteAssumptions;
448
+ } | {
449
+ quality: 'estimate_only' | 'unavailable';
450
+ assumptions: InferenceQuoteAssumptions;
451
+ };
452
+ settlement: 'actual_usage';
453
+ };
415
454
  /**
416
455
  * Query options for ranked tool/provider discovery.
417
456
  */
@@ -2446,6 +2485,13 @@ declare class DeeplineClient {
2446
2485
  * @returns Model metadata, provider option shapes, and runnable examples
2447
2486
  */
2448
2487
  describeModel(model: string): Promise<DeeplineAgentModelDescription>;
2488
+ /**
2489
+ * Quote dynamic AI inference pricing for a concrete payload.
2490
+ *
2491
+ * The result separates a planning estimate from a proven authorization
2492
+ * maximum and contains Deepline credits only.
2493
+ */
2494
+ quoteInferenceTool(toolId: 'ai_inference' | 'deeplineagent', payload: Record<string, unknown>): Promise<InferenceQuote>;
2449
2495
  /**
2450
2496
  * Execute a tool and return the standard execution envelope.
2451
2497
  *
package/dist/index.d.ts CHANGED
@@ -411,7 +411,46 @@ interface DeeplineAgentModelDescription {
411
411
  };
412
412
  caveats: string[];
413
413
  sources: string[];
414
+ inferencePricing: InferenceDynamicPricingCapability;
414
415
  }
416
+ interface InferenceDynamicPricingCapability {
417
+ settlement: 'actual_usage';
418
+ staticUnitPrice: null;
419
+ quoteEndpointTemplate: string;
420
+ supportedQualities: Array<'bounded_max' | 'estimate_only' | 'unavailable'>;
421
+ payloadFields: string[];
422
+ }
423
+ type InferenceQuoteAssumptions = {
424
+ modelCallCount: number;
425
+ planningModelCallCount: number;
426
+ estimatedInputTokens: number;
427
+ estimatedOutputTokens: number;
428
+ maxOutputTokens: number | null;
429
+ candidateRouteCount: number;
430
+ pricedRouteCount: number;
431
+ inputBound: 'proven_request_tokens' | 'catalog_context' | 'not_proven';
432
+ inputBoundProofId?: string;
433
+ };
434
+ type InferenceQuote = {
435
+ quality: 'bounded_max' | 'estimate_only' | 'unavailable';
436
+ estimate: {
437
+ quality: 'estimate_only';
438
+ credits: number;
439
+ assumptions: InferenceQuoteAssumptions;
440
+ } | {
441
+ quality: 'unavailable';
442
+ assumptions: InferenceQuoteAssumptions;
443
+ };
444
+ authorization: {
445
+ quality: 'bounded_max';
446
+ maximumCredits: number;
447
+ assumptions: InferenceQuoteAssumptions;
448
+ } | {
449
+ quality: 'estimate_only' | 'unavailable';
450
+ assumptions: InferenceQuoteAssumptions;
451
+ };
452
+ settlement: 'actual_usage';
453
+ };
415
454
  /**
416
455
  * Query options for ranked tool/provider discovery.
417
456
  */
@@ -2446,6 +2485,13 @@ declare class DeeplineClient {
2446
2485
  * @returns Model metadata, provider option shapes, and runnable examples
2447
2486
  */
2448
2487
  describeModel(model: string): Promise<DeeplineAgentModelDescription>;
2488
+ /**
2489
+ * Quote dynamic AI inference pricing for a concrete payload.
2490
+ *
2491
+ * The result separates a planning estimate from a proven authorization
2492
+ * maximum and contains Deepline credits only.
2493
+ */
2494
+ quoteInferenceTool(toolId: 'ai_inference' | 'deeplineagent', payload: Record<string, unknown>): Promise<InferenceQuote>;
2449
2495
  /**
2450
2496
  * Execute a tool and return the standard execution envelope.
2451
2497
  *
package/dist/index.js CHANGED
@@ -763,7 +763,7 @@ var SDK_RELEASE = {
763
763
  // 0.2.0 makes Dataset Handles uniformly async-only after 0.1.320 briefly
764
764
  // exposed storage-dependent synchronous access. This deliberate minor
765
765
  // release keeps lazy paging semantics independent of row residency.
766
- version: "0.2.16",
766
+ version: "0.2.18",
767
767
  contracts: {
768
768
  api: {
769
769
  name: "sdk-http-api",
@@ -3759,6 +3759,18 @@ var DeeplineClient = class {
3759
3759
  }
3760
3760
  );
3761
3761
  }
3762
+ /**
3763
+ * Quote dynamic AI inference pricing for a concrete payload.
3764
+ *
3765
+ * The result separates a planning estimate from a proven authorization
3766
+ * maximum and contains Deepline credits only.
3767
+ */
3768
+ async quoteInferenceTool(toolId, payload) {
3769
+ return this.http.post(
3770
+ `/api/v2/integrations/${encodeURIComponent(toolId)}/quote`,
3771
+ payload
3772
+ );
3773
+ }
3762
3774
  /**
3763
3775
  * Execute a tool and return the standard execution envelope.
3764
3776
  *
package/dist/index.mjs CHANGED
@@ -689,7 +689,7 @@ var SDK_RELEASE = {
689
689
  // 0.2.0 makes Dataset Handles uniformly async-only after 0.1.320 briefly
690
690
  // exposed storage-dependent synchronous access. This deliberate minor
691
691
  // release keeps lazy paging semantics independent of row residency.
692
- version: "0.2.16",
692
+ version: "0.2.18",
693
693
  contracts: {
694
694
  api: {
695
695
  name: "sdk-http-api",
@@ -3685,6 +3685,18 @@ var DeeplineClient = class {
3685
3685
  }
3686
3686
  );
3687
3687
  }
3688
+ /**
3689
+ * Quote dynamic AI inference pricing for a concrete payload.
3690
+ *
3691
+ * The result separates a planning estimate from a proven authorization
3692
+ * maximum and contains Deepline credits only.
3693
+ */
3694
+ async quoteInferenceTool(toolId, payload) {
3695
+ return this.http.post(
3696
+ `/api/v2/integrations/${encodeURIComponent(toolId)}/quote`,
3697
+ payload
3698
+ );
3699
+ }
3688
3700
  /**
3689
3701
  * Execute a tool and return the standard execution envelope.
3690
3702
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deepline",
3
- "version": "0.2.16",
3
+ "version": "0.2.18",
4
4
  "description": "Deepline SDK + CLI — B2B data enrichment powered by durable cloud execution",
5
5
  "license": "MIT",
6
6
  "repository": {