deepline 0.3.58 → 0.3.59

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.
@@ -199,7 +199,7 @@ export const SDK_RELEASE = {
199
199
  // available at toolResponse.rawV2 while toolResponse.raw and all declared
200
200
  // getters keep their established compatibility behavior.
201
201
  // 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
202
- version: '0.3.58',
202
+ version: '0.3.59',
203
203
  updateSummary:
204
204
  'Automatic CLI updates are now enabled by default. To opt out, run `deepline settings autoupdate off`; use `deepline settings autoupdate on` to re-enable updates or `deepline settings autoupdate pin <version>` to hold an exact release. This release also adds raw-v2 tool responses at toolResponse.rawV2 while preserving existing toolResponse.raw and declared getters.',
205
205
  packageCapabilities: {
@@ -30,6 +30,7 @@ import {
30
30
  compileRequestsWithStrategy,
31
31
  executeChunkedRequests,
32
32
  } from './batch-runtime';
33
+ import type { CompiledRequestBatch } from './batch-runtime';
33
34
  import type { AnyBatchOperationStrategy } from './batching-types';
34
35
  import {
35
36
  PLAY_RUNTIME_WORK_RECEIPT_LEASE_TTL_MS,
@@ -169,10 +170,10 @@ import {
169
170
  import {
170
171
  buildDurableCtxCallCacheKey,
171
172
  buildDurableRunPlayInvocationScope,
172
- buildDurableToolAggregateProviderIdempotencyKey,
173
173
  buildDurableToolAggregateReceiptKey,
174
174
  buildDurableToolCallAuthScopeDigest,
175
175
  buildDurableToolCallCacheKey,
176
+ buildDurableToolPayloadProviderIdempotencyKey,
176
177
  buildDurableToolProviderIdempotencyKey,
177
178
  buildDurableToolReceiptPrefix,
178
179
  resolveDurableCallCachePolicy,
@@ -11273,6 +11274,21 @@ export class PlayContextImpl implements ScalarPlayAuthoringRuntimeContext {
11273
11274
  strategy,
11274
11275
  getPayload: (request: ToolCallRequest) => request.input,
11275
11276
  });
11277
+ const compileOwnedPhysicalBatch = (
11278
+ owned: ToolCallRequest[],
11279
+ ): CompiledRequestBatch<ToolCallRequest> => {
11280
+ const compiled = compileRequestsWithStrategy({
11281
+ requests: owned,
11282
+ strategy,
11283
+ getPayload: (request: ToolCallRequest) => request.input,
11284
+ });
11285
+ if (compiled.length !== 1) {
11286
+ throw new Error(
11287
+ 'Native batch owned members must compile into exactly one provider request.',
11288
+ );
11289
+ }
11290
+ return compiled[0]!;
11291
+ };
11276
11292
  const batchParallelismCeiling =
11277
11293
  this.governor.policy.pacing.workerToolBatchDefaultParallelism;
11278
11294
  const batchSize =
@@ -11282,6 +11298,9 @@ export class PlayContextImpl implements ScalarPlayAuthoringRuntimeContext {
11282
11298
  batchParallelismCeiling,
11283
11299
  )
11284
11300
  : batchParallelismCeiling;
11301
+ const batchProviderActionVersion =
11302
+ (await this.#options.getToolActionCacheVersion?.(toolId))?.trim() ??
11303
+ 'unversioned';
11285
11304
  const successful: ToolCallRequest[] = [];
11286
11305
 
11287
11306
  const deliver = (request: ToolCallRequest, result: ToolExecuteResult) => {
@@ -11332,6 +11351,7 @@ export class PlayContextImpl implements ScalarPlayAuthoringRuntimeContext {
11332
11351
  string,
11333
11352
  {
11334
11353
  members: ToolCallRequest[];
11354
+ compiled: CompiledRequestBatch<ToolCallRequest>;
11335
11355
  providerOperationKey: string;
11336
11356
  receiptLeaseExpiresAt: string | null;
11337
11357
  timeoutMs: number | undefined;
@@ -11380,26 +11400,7 @@ export class PlayContextImpl implements ScalarPlayAuthoringRuntimeContext {
11380
11400
  detail.members[0]?.executionAuthScopeDigest ?? null,
11381
11401
  providerIdempotencyReceiptKey:
11382
11402
  detail.providerOperationKey,
11383
- providerIdempotencyKey:
11384
- buildDurableToolAggregateProviderIdempotencyKey({
11385
- aggregateReceiptKey: detail.providerOperationKey,
11386
- receiptKeys: detail.members.map(
11387
- (member) =>
11388
- member.providerIdempotencyKeyBase ??
11389
- member.receiptKey!,
11390
- ),
11391
- providerIdempotencyKeys: detail.members.map(
11392
- (member) =>
11393
- this.providerIdempotencyKeyForToolCall({
11394
- cacheKey:
11395
- member.providerIdempotencyKeyBase ??
11396
- member.receiptKey!,
11397
- force: member.force === true,
11398
- leaseId: member.receiptLeaseId,
11399
- logicalCallId: member.logicalCallId,
11400
- }),
11401
- ),
11402
- }),
11403
+ providerIdempotencyKey: detail.providerOperationKey,
11403
11404
  receiptLeaseExpiresAt: detail.receiptLeaseExpiresAt,
11404
11405
  timeoutMs: detail.timeoutMs,
11405
11406
  },
@@ -11477,10 +11478,6 @@ export class PlayContextImpl implements ScalarPlayAuthoringRuntimeContext {
11477
11478
  (member) => batchRequestByCallId.get(member.memberId)!,
11478
11479
  );
11479
11480
  const receiptKeys = owned.map((request) => request.receiptKey!);
11480
- const providerReceiptKeys = owned.map(
11481
- (request) =>
11482
- request.providerIdempotencyKeyBase ?? request.receiptKey!,
11483
- );
11484
11481
  const aggregateReceiptKey = buildDurableToolAggregateReceiptKey({
11485
11482
  receiptKeys,
11486
11483
  prefix: 'batch',
@@ -11489,16 +11486,36 @@ export class PlayContextImpl implements ScalarPlayAuthoringRuntimeContext {
11489
11486
  toolId: batch.batchOperation,
11490
11487
  }),
11491
11488
  });
11492
- const providerOperationKey = buildDurableToolAggregateReceiptKey({
11493
- receiptKeys: providerReceiptKeys,
11494
- prefix: 'batch',
11495
- aggregateReceiptPrefix: buildDurableToolReceiptPrefix({
11489
+ const compiled = compileOwnedPhysicalBatch(owned);
11490
+ if (compiled.batchOperation !== batch.batchOperation) {
11491
+ throw new Error(
11492
+ 'Native batch owned members changed provider operation during compilation.',
11493
+ );
11494
+ }
11495
+ const providerOperationKey =
11496
+ buildDurableToolPayloadProviderIdempotencyKey({
11496
11497
  orgId: this.#options.orgId,
11497
11498
  toolId: batch.batchOperation,
11498
- }),
11499
- });
11499
+ executionAuthScopeDigest:
11500
+ owned[0]?.executionAuthScopeDigest ?? null,
11501
+ providerActionVersion: batchProviderActionVersion,
11502
+ payload: compiled.batchPayload,
11503
+ forceRefreshIdentities: owned
11504
+ .filter((request) => request.force === true)
11505
+ .map((request) =>
11506
+ this.providerIdempotencyKeyForToolCall({
11507
+ cacheKey:
11508
+ request.providerIdempotencyKeyBase ??
11509
+ request.receiptKey!,
11510
+ force: true,
11511
+ leaseId: request.receiptLeaseId,
11512
+ logicalCallId: request.logicalCallId,
11513
+ }),
11514
+ ),
11515
+ });
11500
11516
  dispatchDetails.set(aggregateReceiptKey, {
11501
11517
  members: owned,
11518
+ compiled,
11502
11519
  providerOperationKey,
11503
11520
  receiptLeaseExpiresAt: owned.reduce<string | null>(
11504
11521
  (earliest, request) => {
@@ -11523,7 +11540,7 @@ export class PlayContextImpl implements ScalarPlayAuthoringRuntimeContext {
11523
11540
  return {
11524
11541
  ...members[0]!.call,
11525
11542
  tool: { id: batch.batchOperation, providerActionVersion: '' },
11526
- payload: batch.batchPayload,
11543
+ payload: compiled.batchPayload,
11527
11544
  compatibility: {
11528
11545
  resultReceiptKey: aggregateReceiptKey,
11529
11546
  providerOperationKey,
@@ -11531,7 +11548,40 @@ export class PlayContextImpl implements ScalarPlayAuthoringRuntimeContext {
11531
11548
  };
11532
11549
  },
11533
11550
  splitResult: async ({ result: aggregate, members }) => {
11534
- const split = batch.splitResults(
11551
+ const receiptKeys = members.map((member) => {
11552
+ const request = batchRequestByCallId.get(member.memberId);
11553
+ if (!request?.receiptKey) {
11554
+ throw new Error(
11555
+ `Native batch Tool Call lost receipt for ${member.memberId}.`,
11556
+ );
11557
+ }
11558
+ return request.receiptKey;
11559
+ });
11560
+ const aggregateReceiptKey = buildDurableToolAggregateReceiptKey({
11561
+ receiptKeys,
11562
+ prefix: 'batch',
11563
+ aggregateReceiptPrefix: buildDurableToolReceiptPrefix({
11564
+ orgId: this.#options.orgId,
11565
+ toolId: batch.batchOperation,
11566
+ }),
11567
+ });
11568
+ const detail = dispatchDetails.get(aggregateReceiptKey);
11569
+ if (!detail) {
11570
+ throw new Error(
11571
+ 'Native batch Tool Call lost its split compilation details.',
11572
+ );
11573
+ }
11574
+ if (
11575
+ detail.members.length !== members.length ||
11576
+ !detail.members.every(
11577
+ (request, index) => request.callId === members[index]?.memberId,
11578
+ )
11579
+ ) {
11580
+ throw new Error(
11581
+ 'Native batch Tool Call split members changed in transit.',
11582
+ );
11583
+ }
11584
+ const split = detail.compiled.splitResults(
11535
11585
  legacyResultForBatchSplitter(aggregate),
11536
11586
  );
11537
11587
  return await Promise.all(
@@ -12573,11 +12623,6 @@ export class PlayContextImpl implements ScalarPlayAuthoringRuntimeContext {
12573
12623
  const receiptKeys = batch.memberRequests.map(
12574
12624
  (request) => request.cacheKey,
12575
12625
  );
12576
- const providerIdempotencyReceiptKeys =
12577
- batch.memberRequests.map(
12578
- (request) =>
12579
- request.providerIdempotencyKeyBase ?? request.cacheKey,
12580
- );
12581
12626
  const aggregateReceiptKey =
12582
12627
  buildDurableToolAggregateReceiptKey({
12583
12628
  receiptKeys,
@@ -12588,13 +12633,31 @@ export class PlayContextImpl implements ScalarPlayAuthoringRuntimeContext {
12588
12633
  }),
12589
12634
  });
12590
12635
  const aggregateProviderIdempotencyReceiptKey =
12591
- buildDurableToolAggregateReceiptKey({
12592
- receiptKeys: providerIdempotencyReceiptKeys,
12593
- prefix: 'batch',
12594
- aggregateReceiptPrefix: buildDurableToolReceiptPrefix({
12595
- orgId: this.#options.orgId,
12596
- toolId: batch.batchOperation,
12597
- }),
12636
+ buildDurableToolPayloadProviderIdempotencyKey({
12637
+ orgId: this.#options.orgId,
12638
+ toolId: batch.batchOperation,
12639
+ executionAuthScopeDigest:
12640
+ batch.memberRequests[0]?.executionAuthScopeDigest ??
12641
+ null,
12642
+ providerActionVersion:
12643
+ (
12644
+ await this.#options.getToolActionCacheVersion?.(
12645
+ batch.batchOperation,
12646
+ )
12647
+ )?.trim() ?? 'unversioned',
12648
+ payload: batch.batchPayload,
12649
+ forceRefreshIdentities: batch.memberRequests
12650
+ .filter((request) => request.force === true)
12651
+ .map((request) =>
12652
+ this.providerIdempotencyKeyForToolCall({
12653
+ cacheKey:
12654
+ request.providerIdempotencyKeyBase ??
12655
+ request.cacheKey,
12656
+ force: true,
12657
+ leaseId: request.receiptLeaseId,
12658
+ logicalCallId: request.logicalCallId,
12659
+ }),
12660
+ ),
12598
12661
  });
12599
12662
  let releaseToolSlot: () => void = () => undefined;
12600
12663
  try {
@@ -12621,22 +12684,7 @@ export class PlayContextImpl implements ScalarPlayAuthoringRuntimeContext {
12621
12684
  providerIdempotencyReceiptKey:
12622
12685
  aggregateProviderIdempotencyReceiptKey,
12623
12686
  providerIdempotencyKey:
12624
- buildDurableToolAggregateProviderIdempotencyKey({
12625
- aggregateReceiptKey:
12626
- aggregateProviderIdempotencyReceiptKey,
12627
- receiptKeys: providerIdempotencyReceiptKeys,
12628
- providerIdempotencyKeys: batch.memberRequests.map(
12629
- (request) =>
12630
- this.providerIdempotencyKeyForToolCall({
12631
- cacheKey:
12632
- request.providerIdempotencyKeyBase ??
12633
- request.cacheKey,
12634
- force: request.force === true,
12635
- leaseId: request.receiptLeaseId,
12636
- logicalCallId: request.logicalCallId,
12637
- }),
12638
- ),
12639
- }),
12687
+ aggregateProviderIdempotencyReceiptKey,
12640
12688
  receiptLeaseExpiresAt: batch.memberRequests.reduce<
12641
12689
  string | null
12642
12690
  >((earliest, request) => {
@@ -241,3 +241,42 @@ export function buildDurableToolAggregateProviderIdempotencyKey(input: {
241
241
  stableStringify({ receiptKeys, providerIdempotencyKeys }),
242
242
  )}`;
243
243
  }
244
+
245
+ /**
246
+ * Provider-native batch caching is keyed by the exact compiled provider
247
+ * payload. Receipt identities coordinate ownership and terminal results; they
248
+ * cannot stand in for request identity because cache hits and foreign leases
249
+ * can remove members after the original batch was planned.
250
+ *
251
+ * An explicit force refresh is deliberately a separate namespace: it asks for
252
+ * a fresh provider operation even when the payload itself is unchanged.
253
+ */
254
+ export function buildDurableToolPayloadProviderIdempotencyKey(input: {
255
+ orgId?: string | null;
256
+ toolId: string;
257
+ executionAuthScopeDigest?: string | null;
258
+ providerActionVersion?: string | null;
259
+ payload: Record<string, unknown>;
260
+ forceRefreshIdentities?: readonly string[];
261
+ }): string {
262
+ const toolId = input.toolId.trim();
263
+ if (!toolId) {
264
+ throw new Error(
265
+ 'Provider payload idempotency key needs a non-empty toolId.',
266
+ );
267
+ }
268
+ const forceRefreshIdentities = input.forceRefreshIdentities
269
+ ?.map((identity) => identity.trim())
270
+ .filter(Boolean);
271
+ return `${buildDurableToolReceiptPrefix({
272
+ orgId: input.orgId,
273
+ toolId,
274
+ })}payload-v1:${sha256Hex(
275
+ stableStringify({
276
+ executionAuthScopeDigest: input.executionAuthScopeDigest?.trim() || null,
277
+ providerActionVersion: input.providerActionVersion?.trim() || null,
278
+ payload: input.payload,
279
+ ...(forceRefreshIdentities?.length ? { forceRefreshIdentities } : {}),
280
+ }),
281
+ )}`;
282
+ }
package/dist/cli/index.js CHANGED
@@ -1075,7 +1075,7 @@ var SDK_RELEASE = {
1075
1075
  // available at toolResponse.rawV2 while toolResponse.raw and all declared
1076
1076
  // getters keep their established compatibility behavior.
1077
1077
  // 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
1078
- version: "0.3.58",
1078
+ version: "0.3.59",
1079
1079
  updateSummary: "Automatic CLI updates are now enabled by default. To opt out, run `deepline settings autoupdate off`; use `deepline settings autoupdate on` to re-enable updates or `deepline settings autoupdate pin <version>` to hold an exact release. This release also adds raw-v2 tool responses at toolResponse.rawV2 while preserving existing toolResponse.raw and declared getters.",
1080
1080
  packageCapabilities: {
1081
1081
  updatePreferences: 1
@@ -1060,7 +1060,7 @@ var SDK_RELEASE = {
1060
1060
  // available at toolResponse.rawV2 while toolResponse.raw and all declared
1061
1061
  // getters keep their established compatibility behavior.
1062
1062
  // 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
1063
- version: "0.3.58",
1063
+ version: "0.3.59",
1064
1064
  updateSummary: "Automatic CLI updates are now enabled by default. To opt out, run `deepline settings autoupdate off`; use `deepline settings autoupdate on` to re-enable updates or `deepline settings autoupdate pin <version>` to hold an exact release. This release also adds raw-v2 tool responses at toolResponse.rawV2 while preserving existing toolResponse.raw and declared getters.",
1065
1065
  packageCapabilities: {
1066
1066
  updatePreferences: 1
package/dist/index.js CHANGED
@@ -826,7 +826,7 @@ var SDK_RELEASE = {
826
826
  // available at toolResponse.rawV2 while toolResponse.raw and all declared
827
827
  // getters keep their established compatibility behavior.
828
828
  // 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
829
- version: "0.3.58",
829
+ version: "0.3.59",
830
830
  updateSummary: "Automatic CLI updates are now enabled by default. To opt out, run `deepline settings autoupdate off`; use `deepline settings autoupdate on` to re-enable updates or `deepline settings autoupdate pin <version>` to hold an exact release. This release also adds raw-v2 tool responses at toolResponse.rawV2 while preserving existing toolResponse.raw and declared getters.",
831
831
  packageCapabilities: {
832
832
  updatePreferences: 1
package/dist/index.mjs CHANGED
@@ -738,7 +738,7 @@ var SDK_RELEASE = {
738
738
  // available at toolResponse.rawV2 while toolResponse.raw and all declared
739
739
  // getters keep their established compatibility behavior.
740
740
  // 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
741
- version: "0.3.58",
741
+ version: "0.3.59",
742
742
  updateSummary: "Automatic CLI updates are now enabled by default. To opt out, run `deepline settings autoupdate off`; use `deepline settings autoupdate on` to re-enable updates or `deepline settings autoupdate pin <version>` to hold an exact release. This release also adds raw-v2 tool responses at toolResponse.rawV2 while preserving existing toolResponse.raw and declared getters.",
743
743
  packageCapabilities: {
744
744
  updatePreferences: 1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deepline",
3
- "version": "0.3.58",
3
+ "version": "0.3.59",
4
4
  "description": "GTM data CLI and TypeScript SDK for coding agents",
5
5
  "license": "MIT",
6
6
  "homepage": "https://code.deepline.com",