deepline 0.1.277 → 0.1.279

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.
@@ -155,7 +155,7 @@ export const SDK_RELEASE = {
155
155
  // 0.1.253 makes play-page browser opening opt-in and retires --no-open.
156
156
  // 0.1.254 removes the internal operations tree from the published SDK CLI.
157
157
  // Operators use the checkout-local deepline-admin binary instead.
158
- version: '0.1.277',
158
+ version: '0.1.279',
159
159
  contracts: {
160
160
  api: {
161
161
  name: 'sdk-http-api',
@@ -1225,6 +1225,16 @@ export class PlayContextImpl {
1225
1225
  private readonly executionScope: RunExecutionScope;
1226
1226
  private logBuffer: string[] = [];
1227
1227
  private checkpoint: PlayCheckpoint;
1228
+ /**
1229
+ * Durable tool receipts are the replay/cache authority for the execution
1230
+ * paths the host supports. Keeping the same completed result in this
1231
+ * checkpoint retained every provider payload for the lifetime of a run and
1232
+ * copied it again while serializing the terminal. Paths without a matching
1233
+ * receipt API keep the legacy checkpoint cache so local/in-process replay
1234
+ * and bulk-only hosts' direct calls still work.
1235
+ */
1236
+ private readonly durableMappedToolResultsBackedByReceipts: boolean;
1237
+ private readonly durableDirectToolResultsBackedByReceipts: boolean;
1228
1238
  private steps: PlayStep[] = [];
1229
1239
  private explicitMapInvocationKeys = new Set<string>();
1230
1240
  /** The map step currently being built — substeps go here instead of top-level. */
@@ -1383,6 +1393,24 @@ export class PlayContextImpl {
1383
1393
  constructor(options: ContextOptions) {
1384
1394
  this.#options = options;
1385
1395
  this.checkpoint = options.checkpoint ?? emptyCheckpoint();
1396
+ this.durableMappedToolResultsBackedByReceipts = Boolean(
1397
+ (options.claimRuntimeStepReceipt || options.claimRuntimeStepReceipts) &&
1398
+ (options.getRuntimeStepReceipt || options.getRuntimeStepReceipts) &&
1399
+ (options.completeRuntimeStepReceipt ||
1400
+ options.completeRuntimeStepReceipts),
1401
+ );
1402
+ this.durableDirectToolResultsBackedByReceipts = Boolean(
1403
+ options.claimRuntimeStepReceipt &&
1404
+ options.getRuntimeStepReceipt &&
1405
+ options.completeRuntimeStepReceipt,
1406
+ );
1407
+ if (this.durableDirectToolResultsBackedByReceipts) {
1408
+ // A resumed durable runner may receive a legacy checkpoint containing
1409
+ // full tool results. Drop that redundant copy immediately and recover
1410
+ // through the receipt store below. Bulk-only receipt contexts retain the
1411
+ // checkpoint because direct tool calls cannot use the bulk claim path.
1412
+ this.checkpoint.completedToolBatches = {};
1413
+ }
1386
1414
  // The governance play id keys durable ctx receipts (durableCtxKey), the
1387
1415
  // cycle guard, and per-parent child-call counters. It must be the STABLE
1388
1416
  // play name — not the per-run workflow id — so receipts written by one
@@ -3077,16 +3105,25 @@ export class PlayContextImpl {
3077
3105
  private getCachedToolResult(
3078
3106
  toolId: string,
3079
3107
  rowCacheKey: string,
3108
+ path: 'mapped' | 'direct' = 'mapped',
3080
3109
  ): ToolBatchResult | undefined {
3110
+ if (
3111
+ path === 'direct'
3112
+ ? this.durableDirectToolResultsBackedByReceipts
3113
+ : this.durableMappedToolResultsBackedByReceipts
3114
+ ) {
3115
+ return undefined;
3116
+ }
3081
3117
  return this.checkpoint.completedToolBatches[toolId]?.[rowCacheKey];
3082
3118
  }
3083
3119
 
3084
3120
  private getCachedToolResultCandidate(
3085
3121
  toolId: string,
3086
3122
  rowCacheKeys: readonly string[],
3123
+ path: 'mapped' | 'direct' = 'mapped',
3087
3124
  ): { cacheKey: string; result: ToolBatchResult } | null {
3088
3125
  for (const rowCacheKey of rowCacheKeys) {
3089
- const cached = this.getCachedToolResult(toolId, rowCacheKey);
3126
+ const cached = this.getCachedToolResult(toolId, rowCacheKey, path);
3090
3127
  if (cached?.done) {
3091
3128
  return { cacheKey: rowCacheKey, result: cached };
3092
3129
  }
@@ -3098,7 +3135,15 @@ export class PlayContextImpl {
3098
3135
  toolId: string,
3099
3136
  rowCacheKey: string,
3100
3137
  result: unknown | null,
3138
+ path: 'mapped' | 'direct' = 'mapped',
3101
3139
  ): void {
3140
+ if (
3141
+ path === 'direct'
3142
+ ? this.durableDirectToolResultsBackedByReceipts
3143
+ : this.durableMappedToolResultsBackedByReceipts
3144
+ ) {
3145
+ return;
3146
+ }
3102
3147
  if (!this.checkpoint.completedToolBatches[toolId]) {
3103
3148
  this.checkpoint.completedToolBatches[toolId] = {};
3104
3149
  }
@@ -6349,7 +6394,11 @@ export class PlayContextImpl {
6349
6394
  ? null
6350
6395
  : toolCachePolicy.force
6351
6396
  ? null
6352
- : this.getCachedToolResultCandidate(toolId, checkpointCacheKeys);
6397
+ : this.getCachedToolResultCandidate(
6398
+ toolId,
6399
+ checkpointCacheKeys,
6400
+ 'direct',
6401
+ );
6353
6402
  if (cached) {
6354
6403
  this.log(`Calling tool: ${toolId} recovered from checkpoint`);
6355
6404
  return await this.wrapToolExecutionResult({
@@ -6429,13 +6478,7 @@ export class PlayContextImpl {
6429
6478
  }),
6430
6479
  });
6431
6480
  if (cacheableToolResult) {
6432
- this.checkpoint.completedToolBatches[toolId] = {
6433
- ...(this.checkpoint.completedToolBatches[toolId] ?? {}),
6434
- [directCacheKey]: {
6435
- done: true,
6436
- result: wrapped,
6437
- },
6438
- };
6481
+ this.cacheToolResult(toolId, directCacheKey, wrapped, 'direct');
6439
6482
  this.#options.onBatchComplete?.(this.checkpoint);
6440
6483
  }
6441
6484
  return wrapped;
@@ -7348,23 +7391,27 @@ export class PlayContextImpl {
7348
7391
  const toolSettlements = await Promise.allSettled(
7349
7392
  [...byTool.entries()].map(async ([toolId, requests]) => {
7350
7393
  this.log(`Executing tool batch ${toolId}: ${requests.length} calls`);
7351
- const liveStepResults = new Map<string, unknown>();
7394
+ const successfulLiveStepCallIds = new Set<string>();
7352
7395
 
7353
7396
  const recordToolStep = (stepRequests: ToolCallRequest[]): void => {
7354
7397
  if (stepRequests.length === 0) return;
7355
7398
  const stepResults: PlayStepRowResult[] = stepRequests.map((req) => {
7356
- const hasLiveResult = liveStepResults.has(req.callId);
7357
- const result = hasLiveResult
7358
- ? liveStepResults.get(req.callId)
7359
- : this.getCachedToolResult(toolId, req.cacheKey)?.result;
7399
+ const success =
7400
+ successfulLiveStepCallIds.has(req.callId) ||
7401
+ this.getCachedToolResult(toolId, req.cacheKey)?.result != null;
7360
7402
  return {
7361
7403
  rowId: req.rowId,
7362
- status: result != null ? 'completed' : 'failed',
7363
- success: result != null,
7364
- value: result,
7365
- error: result != null ? null : 'Tool call failed',
7404
+ status: success ? 'completed' : 'failed',
7405
+ success,
7406
+ error: success ? null : 'Tool call failed',
7366
7407
  };
7367
7408
  });
7409
+ // Step traces are lifecycle observability, not a second row/receipt
7410
+ // store. Keep only call ids long enough to record their bounded
7411
+ // status preview.
7412
+ for (const request of stepRequests) {
7413
+ successfulLiveStepCallIds.delete(request.callId);
7414
+ }
7368
7415
  const toolStep = {
7369
7416
  type: 'tool' as const,
7370
7417
  toolId,
@@ -7643,6 +7690,7 @@ export class PlayContextImpl {
7643
7690
  });
7644
7691
  this.cacheToolResult(toolId, request.cacheKey, wrapped);
7645
7692
  for (const waitingRequest of requestsForKey) {
7693
+ successfulLiveStepCallIds.add(waitingRequest.callId);
7646
7694
  const resolver = this.toolCallResolvers.get(
7647
7695
  waitingRequest.callId,
7648
7696
  );
@@ -7822,7 +7870,9 @@ export class PlayContextImpl {
7822
7870
  execution?.jobId,
7823
7871
  execution?.meta,
7824
7872
  );
7825
- liveStepResults.set(owner.callId, result);
7873
+ if (result != null) {
7874
+ successfulLiveStepCallIds.add(owner.callId);
7875
+ }
7826
7876
  resolveLiveFollowers(owner, result);
7827
7877
  recordToolStep([owner]);
7828
7878
  this.#options.onBatchComplete?.(this.checkpoint);
@@ -8110,7 +8160,9 @@ export class PlayContextImpl {
8110
8160
  index += 1
8111
8161
  ) {
8112
8162
  const request = entry.request.memberRequests[index]!;
8113
- liveStepResults.set(request.callId, resolvedResults[index]);
8163
+ if (resolvedResults[index] != null) {
8164
+ successfulLiveStepCallIds.add(request.callId);
8165
+ }
8114
8166
  resolveLiveFollowers(request, resolvedResults[index]);
8115
8167
  }
8116
8168
  }
@@ -8150,7 +8202,9 @@ export class PlayContextImpl {
8150
8202
  for (let index = 0; index < entries.length; index += 1) {
8151
8203
  const entry = entries[index]!;
8152
8204
  const result = resolvedResults[index];
8153
- liveStepResults.set(entry.request.callId, result);
8205
+ if (result != null) {
8206
+ successfulLiveStepCallIds.add(entry.request.callId);
8207
+ }
8154
8208
  resolveLiveFollowers(entry.request, result);
8155
8209
  entry.resolve(result);
8156
8210
  }
package/dist/cli/index.js CHANGED
@@ -718,7 +718,7 @@ var SDK_RELEASE = {
718
718
  // 0.1.253 makes play-page browser opening opt-in and retires --no-open.
719
719
  // 0.1.254 removes the internal operations tree from the published SDK CLI.
720
720
  // Operators use the checkout-local deepline-admin binary instead.
721
- version: "0.1.277",
721
+ version: "0.1.279",
722
722
  contracts: {
723
723
  api: {
724
724
  name: "sdk-http-api",
@@ -5831,7 +5831,21 @@ function readCsvRows(csvPath) {
5831
5831
  });
5832
5832
  }
5833
5833
  function csvStringFromRows(rows, columns) {
5834
- return (0, import_sync2.stringify)(rows.map(csvSafeRow), {
5834
+ const effectiveColumns = columns?.length ? columns : Object.keys(rows[0] ?? {});
5835
+ if (!effectiveColumns.length) {
5836
+ return (0, import_sync2.stringify)(
5837
+ rows.map(() => ({})),
5838
+ { header: true }
5839
+ );
5840
+ }
5841
+ const records = rows.map(
5842
+ (row) => effectiveColumns.map(
5843
+ (column) => csvSafeCell(
5844
+ Object.prototype.hasOwnProperty.call(row, column) ? row[column] : void 0
5845
+ )
5846
+ )
5847
+ );
5848
+ return (0, import_sync2.stringify)(records, {
5835
5849
  header: true,
5836
5850
  cast: {
5837
5851
  boolean: (value) => value ? "true" : "false",
@@ -5840,14 +5854,9 @@ function csvStringFromRows(rows, columns) {
5840
5854
  return typeof cell === "string" ? cell : null;
5841
5855
  }
5842
5856
  },
5843
- ...columns?.length ? { columns } : {}
5857
+ ...effectiveColumns.length ? { columns: effectiveColumns } : {}
5844
5858
  });
5845
5859
  }
5846
- function csvSafeRow(row) {
5847
- return Object.fromEntries(
5848
- Object.entries(row).map(([key, value]) => [key, csvSafeCell(value)])
5849
- );
5850
- }
5851
5860
  function csvSafeCell(value) {
5852
5861
  if (value === void 0) {
5853
5862
  return null;
@@ -27866,6 +27875,9 @@ function toolContractJsonForDescribe(tool, requestedToolId) {
27866
27875
  const inputFields = toolInputFieldsForDisplay(
27867
27876
  recordField2(tool, "inputSchema", "input_schema")
27868
27877
  );
27878
+ const inputSchema = publicToolInputSchemaForDescribe(
27879
+ recordField2(tool, "inputSchema", "input_schema")
27880
+ );
27869
27881
  const usageGuidance = recordField2(tool, "usageGuidance", "usage_guidance");
27870
27882
  const toolExecutionResult = recordField2(
27871
27883
  usageGuidance,
@@ -27911,6 +27923,7 @@ function toolContractJsonForDescribe(tool, requestedToolId) {
27911
27923
  ...field.description ? { description: field.description } : {},
27912
27924
  ...Object.prototype.hasOwnProperty.call(field, "default") ? { default: field.default } : {}
27913
27925
  })),
27926
+ inputSchema,
27914
27927
  cost: {
27915
27928
  pricingModel: stringField2(cost, "pricingModel", "pricing_model") || null,
27916
27929
  billingMode: stringField2(cost, "billingMode", "billing_mode") || null,
@@ -28034,7 +28047,9 @@ function printCompactToolContract(tool, requestedToolId) {
28034
28047
  const getters = isRecord9(contract.getters) ? contract.getters : {};
28035
28048
  const listGetters = Array.isArray(getters.extractedLists) ? getters.extractedLists : [];
28036
28049
  const valueGetters = Array.isArray(getters.extractedValues) ? getters.extractedValues : [];
28037
- const inputFields = Array.isArray(contract.inputFields) ? contract.inputFields : [];
28050
+ const inputFields = recursiveToolInputFieldsForDisplay(
28051
+ recordField2(contract, "inputSchema")
28052
+ );
28038
28053
  console.log(String(contract.toolId));
28039
28054
  if (contract.displayName) console.log(`Best for: ${contract.displayName}`);
28040
28055
  if (typeof contract.description === "string" && contract.description.trim()) {
@@ -28054,8 +28069,14 @@ function printCompactToolContract(tool, requestedToolId) {
28054
28069
  const required = field.required ? "*" : "";
28055
28070
  const type = stringField2(field, "type") || "unknown";
28056
28071
  const description = stringField2(field, "description");
28072
+ const enumValues = Array.isArray(field.enum) ? field.enum : [];
28073
+ const enumSuffix = enumValues.length ? ` enum=${enumValues.map(String).join("|")}` : "";
28074
+ const defaultSuffix = Object.prototype.hasOwnProperty.call(
28075
+ field,
28076
+ "default"
28077
+ ) ? ` default=${JSON.stringify(field.default)}` : "";
28057
28078
  console.log(
28058
- `- ${name}${required}: ${type}${description ? ` - ${description}` : ""}`
28079
+ `- ${name}${required}: ${type}${enumSuffix}${defaultSuffix}${description ? ` - ${description}` : ""}`
28059
28080
  );
28060
28081
  }
28061
28082
  }
@@ -28116,24 +28137,37 @@ function printToolSchemaOnly(tool, requestedToolId) {
28116
28137
  return;
28117
28138
  }
28118
28139
  const contract = toolContractJsonForDescribe(tool, requestedToolId);
28119
- const inputFields = Array.isArray(contract.inputFields) ? contract.inputFields : [];
28140
+ const inputFields = recursiveToolInputFieldsForDisplay(
28141
+ recordField2(contract, "inputSchema")
28142
+ );
28120
28143
  console.log(`Schema: ${contract.toolId}`);
28121
28144
  if (!inputFields.length) {
28122
28145
  console.log("Inputs: none");
28123
- return;
28146
+ } else {
28147
+ console.log("Inputs:");
28148
+ for (const field of inputFields) {
28149
+ const name = typeof field.name === "string" ? field.name : "";
28150
+ if (!name) continue;
28151
+ const required = field.required ? "*" : "";
28152
+ const type = typeof field.type === "string" ? field.type : "unknown";
28153
+ const description = typeof field.description === "string" ? field.description : "";
28154
+ const enumValues = Array.isArray(field.enum) ? field.enum : [];
28155
+ const enumSuffix = enumValues.length ? ` enum=${enumValues.map(String).join("|")}` : "";
28156
+ const defaultSuffix = Object.prototype.hasOwnProperty.call(
28157
+ field,
28158
+ "default"
28159
+ ) ? ` default=${JSON.stringify(field.default)}` : "";
28160
+ console.log(
28161
+ `- ${name}${required}: ${type}${enumSuffix}${defaultSuffix}${description ? ` - ${description}` : ""}`
28162
+ );
28163
+ }
28124
28164
  }
28125
- console.log("Inputs:");
28126
- for (const field of inputFields) {
28127
- if (!isRecord9(field)) continue;
28128
- const name = stringField2(field, "name");
28129
- if (!name) continue;
28130
- const required = field.required ? "*" : "";
28131
- const type = stringField2(field, "type") || "unknown";
28132
- const description = stringField2(field, "description");
28133
- const defaultSuffix = Object.prototype.hasOwnProperty.call(field, "default") ? ` default=${JSON.stringify(field.default)}` : "";
28134
- console.log(
28135
- `- ${name}${required}: ${type}${defaultSuffix}${description ? ` - ${description}` : ""}`
28136
- );
28165
+ const declaredSchema = declaredToolJsonSchema(
28166
+ recordField2(contract, "inputSchema")
28167
+ );
28168
+ if (declaredSchema) {
28169
+ console.log("Declared JSON Schema:");
28170
+ console.log(JSON.stringify(declaredSchema, null, 2));
28137
28171
  }
28138
28172
  }
28139
28173
  function printToolExamplesOnly(tool, requestedToolId, options = {}) {
@@ -28378,6 +28412,126 @@ function toolInputFieldsForDisplay(inputSchema) {
28378
28412
  };
28379
28413
  });
28380
28414
  }
28415
+ function canonicalToolJsonSchema(inputSchema) {
28416
+ return isRecord9(inputSchema.jsonSchema) ? inputSchema.jsonSchema : inputSchema;
28417
+ }
28418
+ function declaredToolJsonSchema(inputSchema) {
28419
+ if (isRecord9(inputSchema.jsonSchema)) {
28420
+ return inputSchema.jsonSchema;
28421
+ }
28422
+ return Array.isArray(inputSchema.fields) ? null : inputSchema;
28423
+ }
28424
+ function publicToolInputSchemaForDescribe(inputSchema) {
28425
+ const exposesProviderSpend = (description) => {
28426
+ const withoutDeeplineCredits = description.replace(
28427
+ /\bdeepline(?:-facing)?\s+credits?\b/gi,
28428
+ ""
28429
+ );
28430
+ return /\bcredits?\b/i.test(withoutDeeplineCredits) || /\bprovider\s+(?:cost|spend|price|pricing|usage)\b/i.test(
28431
+ withoutDeeplineCredits
28432
+ ) || /\b(?:costs?|charges?|priced at)\s+[$€£]\s*\d/i.test(
28433
+ withoutDeeplineCredits
28434
+ ) || /\b(?:costs?|charges?|priced at)\s+\d+(?:\.\d+)?\s*(?:usd|eur|gbp)\b/i.test(
28435
+ withoutDeeplineCredits
28436
+ ) || /\battribute-priced\b/i.test(withoutDeeplineCredits) || /\b(?:cost|price|pricing)\s+(?:grows?|increases?|scales?|varies?)\b/i.test(
28437
+ withoutDeeplineCredits
28438
+ ) || /\b(?:will be|are|is|be)\s+(?:billed|charged)\b/i.test(
28439
+ withoutDeeplineCredits
28440
+ ) || /\b(?:additional|extra)\s+charges?\b/i.test(withoutDeeplineCredits) || /\bcharg(?:e|ed)\s+(?:double|per)\b/i.test(withoutDeeplineCredits) || /\bpricing page\b/i.test(withoutDeeplineCredits);
28441
+ };
28442
+ const stripDescriptions = (value) => {
28443
+ if (Array.isArray(value)) return value.map(stripDescriptions);
28444
+ if (!isRecord9(value)) return value;
28445
+ return Object.fromEntries(
28446
+ Object.entries(value).flatMap(([key, nested]) => {
28447
+ if (key === "description" && typeof nested === "string" && exposesProviderSpend(nested)) {
28448
+ return [];
28449
+ }
28450
+ return [[key, stripDescriptions(nested)]];
28451
+ })
28452
+ );
28453
+ };
28454
+ return stripDescriptions(inputSchema);
28455
+ }
28456
+ function recursiveToolInputFieldsForDisplay(inputSchema) {
28457
+ const root = canonicalToolJsonSchema(inputSchema);
28458
+ const fields = /* @__PURE__ */ new Map();
28459
+ const schemasById = /* @__PURE__ */ new Map();
28460
+ const collectSchemaIds = (value) => {
28461
+ if (Array.isArray(value)) {
28462
+ for (const item of value) collectSchemaIds(item);
28463
+ return;
28464
+ }
28465
+ if (!isRecord9(value)) return;
28466
+ if (typeof value.$id === "string" && value.$id.trim()) {
28467
+ schemasById.set(value.$id.trim(), value);
28468
+ }
28469
+ for (const nested of Object.values(value)) collectSchemaIds(nested);
28470
+ };
28471
+ collectSchemaIds(root);
28472
+ const resolveRef = (schema) => {
28473
+ const ref = typeof schema.$ref === "string" ? schema.$ref : "";
28474
+ if (!ref.startsWith("#/")) return schemasById.get(ref) ?? schema;
28475
+ let current = root;
28476
+ for (const rawSegment of ref.slice(2).split("/")) {
28477
+ const segment = rawSegment.replace(/~1/g, "/").replace(/~0/g, "~");
28478
+ if (!isRecord9(current)) return schema;
28479
+ current = current[segment];
28480
+ }
28481
+ return isRecord9(current) ? current : schema;
28482
+ };
28483
+ const addField = (field) => {
28484
+ const name = typeof field.name === "string" ? field.name : "";
28485
+ if (!name) return;
28486
+ const existing = fields.get(name);
28487
+ if (!existing || existing.type === "unknown") {
28488
+ fields.set(name, field);
28489
+ }
28490
+ };
28491
+ const visit = (unresolvedSchema, path, required, activeRefs = /* @__PURE__ */ new Set()) => {
28492
+ const ref = typeof unresolvedSchema.$ref === "string" ? unresolvedSchema.$ref : "";
28493
+ if (ref && activeRefs.has(ref)) return;
28494
+ const schema = resolveRef(unresolvedSchema);
28495
+ const nextActiveRefs = ref ? /* @__PURE__ */ new Set([...activeRefs, ref]) : activeRefs;
28496
+ const type = Array.isArray(schema.type) ? schema.type.map(String).join("|") : typeof schema.type === "string" ? schema.type : isRecord9(schema.properties) ? "object" : schema.items ? "array" : "unknown";
28497
+ if (path) {
28498
+ addField({
28499
+ name: path,
28500
+ type,
28501
+ required,
28502
+ description: schema.description,
28503
+ ...Array.isArray(schema.enum) ? { enum: schema.enum } : {},
28504
+ ...Object.prototype.hasOwnProperty.call(schema, "default") ? { default: schema.default } : {}
28505
+ });
28506
+ }
28507
+ const properties = isRecord9(schema.properties) ? schema.properties : {};
28508
+ const requiredNames = new Set(
28509
+ Array.isArray(schema.required) ? schema.required.map(String) : []
28510
+ );
28511
+ for (const [name, value] of Object.entries(properties)) {
28512
+ if (!isRecord9(value)) continue;
28513
+ visit(
28514
+ value,
28515
+ path ? `${path}.${name}` : name,
28516
+ requiredNames.has(name),
28517
+ nextActiveRefs
28518
+ );
28519
+ }
28520
+ if (isRecord9(schema.items)) {
28521
+ visit(schema.items, `${path}[]`, false, nextActiveRefs);
28522
+ }
28523
+ for (const keyword of ["anyOf", "oneOf", "allOf"]) {
28524
+ const branches = Array.isArray(schema[keyword]) ? schema[keyword] : [];
28525
+ for (const branch of branches) {
28526
+ if (isRecord9(branch)) {
28527
+ visit(branch, path, required, nextActiveRefs);
28528
+ }
28529
+ }
28530
+ }
28531
+ };
28532
+ visit(root, "", false);
28533
+ return fields.size ? [...fields.values()] : toolInputFieldsForDisplay(inputSchema);
28534
+ }
28381
28535
  function printSamples(samples) {
28382
28536
  const requestPayload = samplePayload(samples, "request");
28383
28537
  const responsePayload = samplePayload(samples, "response");
@@ -703,7 +703,7 @@ var SDK_RELEASE = {
703
703
  // 0.1.253 makes play-page browser opening opt-in and retires --no-open.
704
704
  // 0.1.254 removes the internal operations tree from the published SDK CLI.
705
705
  // Operators use the checkout-local deepline-admin binary instead.
706
- version: "0.1.277",
706
+ version: "0.1.279",
707
707
  contracts: {
708
708
  api: {
709
709
  name: "sdk-http-api",
@@ -5828,7 +5828,21 @@ function readCsvRows(csvPath) {
5828
5828
  });
5829
5829
  }
5830
5830
  function csvStringFromRows(rows, columns) {
5831
- return stringify(rows.map(csvSafeRow), {
5831
+ const effectiveColumns = columns?.length ? columns : Object.keys(rows[0] ?? {});
5832
+ if (!effectiveColumns.length) {
5833
+ return stringify(
5834
+ rows.map(() => ({})),
5835
+ { header: true }
5836
+ );
5837
+ }
5838
+ const records = rows.map(
5839
+ (row) => effectiveColumns.map(
5840
+ (column) => csvSafeCell(
5841
+ Object.prototype.hasOwnProperty.call(row, column) ? row[column] : void 0
5842
+ )
5843
+ )
5844
+ );
5845
+ return stringify(records, {
5832
5846
  header: true,
5833
5847
  cast: {
5834
5848
  boolean: (value) => value ? "true" : "false",
@@ -5837,14 +5851,9 @@ function csvStringFromRows(rows, columns) {
5837
5851
  return typeof cell === "string" ? cell : null;
5838
5852
  }
5839
5853
  },
5840
- ...columns?.length ? { columns } : {}
5854
+ ...effectiveColumns.length ? { columns: effectiveColumns } : {}
5841
5855
  });
5842
5856
  }
5843
- function csvSafeRow(row) {
5844
- return Object.fromEntries(
5845
- Object.entries(row).map(([key, value]) => [key, csvSafeCell(value)])
5846
- );
5847
- }
5848
5857
  function csvSafeCell(value) {
5849
5858
  if (value === void 0) {
5850
5859
  return null;
@@ -27914,6 +27923,9 @@ function toolContractJsonForDescribe(tool, requestedToolId) {
27914
27923
  const inputFields = toolInputFieldsForDisplay(
27915
27924
  recordField2(tool, "inputSchema", "input_schema")
27916
27925
  );
27926
+ const inputSchema = publicToolInputSchemaForDescribe(
27927
+ recordField2(tool, "inputSchema", "input_schema")
27928
+ );
27917
27929
  const usageGuidance = recordField2(tool, "usageGuidance", "usage_guidance");
27918
27930
  const toolExecutionResult = recordField2(
27919
27931
  usageGuidance,
@@ -27959,6 +27971,7 @@ function toolContractJsonForDescribe(tool, requestedToolId) {
27959
27971
  ...field.description ? { description: field.description } : {},
27960
27972
  ...Object.prototype.hasOwnProperty.call(field, "default") ? { default: field.default } : {}
27961
27973
  })),
27974
+ inputSchema,
27962
27975
  cost: {
27963
27976
  pricingModel: stringField2(cost, "pricingModel", "pricing_model") || null,
27964
27977
  billingMode: stringField2(cost, "billingMode", "billing_mode") || null,
@@ -28082,7 +28095,9 @@ function printCompactToolContract(tool, requestedToolId) {
28082
28095
  const getters = isRecord9(contract.getters) ? contract.getters : {};
28083
28096
  const listGetters = Array.isArray(getters.extractedLists) ? getters.extractedLists : [];
28084
28097
  const valueGetters = Array.isArray(getters.extractedValues) ? getters.extractedValues : [];
28085
- const inputFields = Array.isArray(contract.inputFields) ? contract.inputFields : [];
28098
+ const inputFields = recursiveToolInputFieldsForDisplay(
28099
+ recordField2(contract, "inputSchema")
28100
+ );
28086
28101
  console.log(String(contract.toolId));
28087
28102
  if (contract.displayName) console.log(`Best for: ${contract.displayName}`);
28088
28103
  if (typeof contract.description === "string" && contract.description.trim()) {
@@ -28102,8 +28117,14 @@ function printCompactToolContract(tool, requestedToolId) {
28102
28117
  const required = field.required ? "*" : "";
28103
28118
  const type = stringField2(field, "type") || "unknown";
28104
28119
  const description = stringField2(field, "description");
28120
+ const enumValues = Array.isArray(field.enum) ? field.enum : [];
28121
+ const enumSuffix = enumValues.length ? ` enum=${enumValues.map(String).join("|")}` : "";
28122
+ const defaultSuffix = Object.prototype.hasOwnProperty.call(
28123
+ field,
28124
+ "default"
28125
+ ) ? ` default=${JSON.stringify(field.default)}` : "";
28105
28126
  console.log(
28106
- `- ${name}${required}: ${type}${description ? ` - ${description}` : ""}`
28127
+ `- ${name}${required}: ${type}${enumSuffix}${defaultSuffix}${description ? ` - ${description}` : ""}`
28107
28128
  );
28108
28129
  }
28109
28130
  }
@@ -28164,24 +28185,37 @@ function printToolSchemaOnly(tool, requestedToolId) {
28164
28185
  return;
28165
28186
  }
28166
28187
  const contract = toolContractJsonForDescribe(tool, requestedToolId);
28167
- const inputFields = Array.isArray(contract.inputFields) ? contract.inputFields : [];
28188
+ const inputFields = recursiveToolInputFieldsForDisplay(
28189
+ recordField2(contract, "inputSchema")
28190
+ );
28168
28191
  console.log(`Schema: ${contract.toolId}`);
28169
28192
  if (!inputFields.length) {
28170
28193
  console.log("Inputs: none");
28171
- return;
28194
+ } else {
28195
+ console.log("Inputs:");
28196
+ for (const field of inputFields) {
28197
+ const name = typeof field.name === "string" ? field.name : "";
28198
+ if (!name) continue;
28199
+ const required = field.required ? "*" : "";
28200
+ const type = typeof field.type === "string" ? field.type : "unknown";
28201
+ const description = typeof field.description === "string" ? field.description : "";
28202
+ const enumValues = Array.isArray(field.enum) ? field.enum : [];
28203
+ const enumSuffix = enumValues.length ? ` enum=${enumValues.map(String).join("|")}` : "";
28204
+ const defaultSuffix = Object.prototype.hasOwnProperty.call(
28205
+ field,
28206
+ "default"
28207
+ ) ? ` default=${JSON.stringify(field.default)}` : "";
28208
+ console.log(
28209
+ `- ${name}${required}: ${type}${enumSuffix}${defaultSuffix}${description ? ` - ${description}` : ""}`
28210
+ );
28211
+ }
28172
28212
  }
28173
- console.log("Inputs:");
28174
- for (const field of inputFields) {
28175
- if (!isRecord9(field)) continue;
28176
- const name = stringField2(field, "name");
28177
- if (!name) continue;
28178
- const required = field.required ? "*" : "";
28179
- const type = stringField2(field, "type") || "unknown";
28180
- const description = stringField2(field, "description");
28181
- const defaultSuffix = Object.prototype.hasOwnProperty.call(field, "default") ? ` default=${JSON.stringify(field.default)}` : "";
28182
- console.log(
28183
- `- ${name}${required}: ${type}${defaultSuffix}${description ? ` - ${description}` : ""}`
28184
- );
28213
+ const declaredSchema = declaredToolJsonSchema(
28214
+ recordField2(contract, "inputSchema")
28215
+ );
28216
+ if (declaredSchema) {
28217
+ console.log("Declared JSON Schema:");
28218
+ console.log(JSON.stringify(declaredSchema, null, 2));
28185
28219
  }
28186
28220
  }
28187
28221
  function printToolExamplesOnly(tool, requestedToolId, options = {}) {
@@ -28426,6 +28460,126 @@ function toolInputFieldsForDisplay(inputSchema) {
28426
28460
  };
28427
28461
  });
28428
28462
  }
28463
+ function canonicalToolJsonSchema(inputSchema) {
28464
+ return isRecord9(inputSchema.jsonSchema) ? inputSchema.jsonSchema : inputSchema;
28465
+ }
28466
+ function declaredToolJsonSchema(inputSchema) {
28467
+ if (isRecord9(inputSchema.jsonSchema)) {
28468
+ return inputSchema.jsonSchema;
28469
+ }
28470
+ return Array.isArray(inputSchema.fields) ? null : inputSchema;
28471
+ }
28472
+ function publicToolInputSchemaForDescribe(inputSchema) {
28473
+ const exposesProviderSpend = (description) => {
28474
+ const withoutDeeplineCredits = description.replace(
28475
+ /\bdeepline(?:-facing)?\s+credits?\b/gi,
28476
+ ""
28477
+ );
28478
+ return /\bcredits?\b/i.test(withoutDeeplineCredits) || /\bprovider\s+(?:cost|spend|price|pricing|usage)\b/i.test(
28479
+ withoutDeeplineCredits
28480
+ ) || /\b(?:costs?|charges?|priced at)\s+[$€£]\s*\d/i.test(
28481
+ withoutDeeplineCredits
28482
+ ) || /\b(?:costs?|charges?|priced at)\s+\d+(?:\.\d+)?\s*(?:usd|eur|gbp)\b/i.test(
28483
+ withoutDeeplineCredits
28484
+ ) || /\battribute-priced\b/i.test(withoutDeeplineCredits) || /\b(?:cost|price|pricing)\s+(?:grows?|increases?|scales?|varies?)\b/i.test(
28485
+ withoutDeeplineCredits
28486
+ ) || /\b(?:will be|are|is|be)\s+(?:billed|charged)\b/i.test(
28487
+ withoutDeeplineCredits
28488
+ ) || /\b(?:additional|extra)\s+charges?\b/i.test(withoutDeeplineCredits) || /\bcharg(?:e|ed)\s+(?:double|per)\b/i.test(withoutDeeplineCredits) || /\bpricing page\b/i.test(withoutDeeplineCredits);
28489
+ };
28490
+ const stripDescriptions = (value) => {
28491
+ if (Array.isArray(value)) return value.map(stripDescriptions);
28492
+ if (!isRecord9(value)) return value;
28493
+ return Object.fromEntries(
28494
+ Object.entries(value).flatMap(([key, nested]) => {
28495
+ if (key === "description" && typeof nested === "string" && exposesProviderSpend(nested)) {
28496
+ return [];
28497
+ }
28498
+ return [[key, stripDescriptions(nested)]];
28499
+ })
28500
+ );
28501
+ };
28502
+ return stripDescriptions(inputSchema);
28503
+ }
28504
+ function recursiveToolInputFieldsForDisplay(inputSchema) {
28505
+ const root = canonicalToolJsonSchema(inputSchema);
28506
+ const fields = /* @__PURE__ */ new Map();
28507
+ const schemasById = /* @__PURE__ */ new Map();
28508
+ const collectSchemaIds = (value) => {
28509
+ if (Array.isArray(value)) {
28510
+ for (const item of value) collectSchemaIds(item);
28511
+ return;
28512
+ }
28513
+ if (!isRecord9(value)) return;
28514
+ if (typeof value.$id === "string" && value.$id.trim()) {
28515
+ schemasById.set(value.$id.trim(), value);
28516
+ }
28517
+ for (const nested of Object.values(value)) collectSchemaIds(nested);
28518
+ };
28519
+ collectSchemaIds(root);
28520
+ const resolveRef = (schema) => {
28521
+ const ref = typeof schema.$ref === "string" ? schema.$ref : "";
28522
+ if (!ref.startsWith("#/")) return schemasById.get(ref) ?? schema;
28523
+ let current = root;
28524
+ for (const rawSegment of ref.slice(2).split("/")) {
28525
+ const segment = rawSegment.replace(/~1/g, "/").replace(/~0/g, "~");
28526
+ if (!isRecord9(current)) return schema;
28527
+ current = current[segment];
28528
+ }
28529
+ return isRecord9(current) ? current : schema;
28530
+ };
28531
+ const addField = (field) => {
28532
+ const name = typeof field.name === "string" ? field.name : "";
28533
+ if (!name) return;
28534
+ const existing = fields.get(name);
28535
+ if (!existing || existing.type === "unknown") {
28536
+ fields.set(name, field);
28537
+ }
28538
+ };
28539
+ const visit = (unresolvedSchema, path, required, activeRefs = /* @__PURE__ */ new Set()) => {
28540
+ const ref = typeof unresolvedSchema.$ref === "string" ? unresolvedSchema.$ref : "";
28541
+ if (ref && activeRefs.has(ref)) return;
28542
+ const schema = resolveRef(unresolvedSchema);
28543
+ const nextActiveRefs = ref ? /* @__PURE__ */ new Set([...activeRefs, ref]) : activeRefs;
28544
+ const type = Array.isArray(schema.type) ? schema.type.map(String).join("|") : typeof schema.type === "string" ? schema.type : isRecord9(schema.properties) ? "object" : schema.items ? "array" : "unknown";
28545
+ if (path) {
28546
+ addField({
28547
+ name: path,
28548
+ type,
28549
+ required,
28550
+ description: schema.description,
28551
+ ...Array.isArray(schema.enum) ? { enum: schema.enum } : {},
28552
+ ...Object.prototype.hasOwnProperty.call(schema, "default") ? { default: schema.default } : {}
28553
+ });
28554
+ }
28555
+ const properties = isRecord9(schema.properties) ? schema.properties : {};
28556
+ const requiredNames = new Set(
28557
+ Array.isArray(schema.required) ? schema.required.map(String) : []
28558
+ );
28559
+ for (const [name, value] of Object.entries(properties)) {
28560
+ if (!isRecord9(value)) continue;
28561
+ visit(
28562
+ value,
28563
+ path ? `${path}.${name}` : name,
28564
+ requiredNames.has(name),
28565
+ nextActiveRefs
28566
+ );
28567
+ }
28568
+ if (isRecord9(schema.items)) {
28569
+ visit(schema.items, `${path}[]`, false, nextActiveRefs);
28570
+ }
28571
+ for (const keyword of ["anyOf", "oneOf", "allOf"]) {
28572
+ const branches = Array.isArray(schema[keyword]) ? schema[keyword] : [];
28573
+ for (const branch of branches) {
28574
+ if (isRecord9(branch)) {
28575
+ visit(branch, path, required, nextActiveRefs);
28576
+ }
28577
+ }
28578
+ }
28579
+ };
28580
+ visit(root, "", false);
28581
+ return fields.size ? [...fields.values()] : toolInputFieldsForDisplay(inputSchema);
28582
+ }
28429
28583
  function printSamples(samples) {
28430
28584
  const requestPayload = samplePayload(samples, "request");
28431
28585
  const responsePayload = samplePayload(samples, "response");
package/dist/index.js CHANGED
@@ -438,7 +438,7 @@ var SDK_RELEASE = {
438
438
  // 0.1.253 makes play-page browser opening opt-in and retires --no-open.
439
439
  // 0.1.254 removes the internal operations tree from the published SDK CLI.
440
440
  // Operators use the checkout-local deepline-admin binary instead.
441
- version: "0.1.277",
441
+ version: "0.1.279",
442
442
  contracts: {
443
443
  api: {
444
444
  name: "sdk-http-api",
package/dist/index.mjs CHANGED
@@ -367,7 +367,7 @@ var SDK_RELEASE = {
367
367
  // 0.1.253 makes play-page browser opening opt-in and retires --no-open.
368
368
  // 0.1.254 removes the internal operations tree from the published SDK CLI.
369
369
  // Operators use the checkout-local deepline-admin binary instead.
370
- version: "0.1.277",
370
+ version: "0.1.279",
371
371
  contracts: {
372
372
  api: {
373
373
  name: "sdk-http-api",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deepline",
3
- "version": "0.1.277",
3
+ "version": "0.1.279",
4
4
  "description": "Deepline SDK + CLI — B2B data enrichment powered by durable cloud execution",
5
5
  "license": "MIT",
6
6
  "repository": {