deepline 0.2.11 → 0.2.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bundling-sources/sdk/src/release.ts +1 -1
- package/dist/bundling-sources/shared_libs/play-runtime/context.ts +70 -87
- package/dist/bundling-sources/shared_libs/play-runtime/ctx-types.ts +2 -1
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-actions.ts +2 -1
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-api.ts +24 -7
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-contract.ts +8 -1
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-receipt-store-adapter.ts +7 -4
- package/dist/cli/index.js +1 -1
- package/dist/cli/index.mjs +1 -1
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +1 -1
|
@@ -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.
|
|
163
|
+
version: '0.2.13',
|
|
164
164
|
contracts: {
|
|
165
165
|
api: {
|
|
166
166
|
name: 'sdk-http-api',
|
|
@@ -2276,23 +2276,16 @@ export class PlayContextImpl {
|
|
|
2276
2276
|
if (!this.#options.heartbeatRuntimeStepReceipts) {
|
|
2277
2277
|
return await this.assertRuntimeToolReceiptOwnership(requests);
|
|
2278
2278
|
}
|
|
2279
|
-
const
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
runAttempt: this.currentRunAttempt,
|
|
2290
|
-
leaseId,
|
|
2291
|
-
keys,
|
|
2292
|
-
});
|
|
2293
|
-
this.assertRuntimeToolReceiptHeartbeatResult(keys, leaseId, receipts);
|
|
2294
|
-
}),
|
|
2295
|
-
);
|
|
2279
|
+
const uniqueTargets = [
|
|
2280
|
+
...new Map(targets.map((target) => [target.receiptKey, target])).values(),
|
|
2281
|
+
];
|
|
2282
|
+
const receipts = await this.#options.heartbeatRuntimeStepReceipts({
|
|
2283
|
+
runId: this.currentReceiptOwnerRunId,
|
|
2284
|
+
runAttempt: this.currentRunAttempt,
|
|
2285
|
+
keys: uniqueTargets.map((target) => target.receiptKey),
|
|
2286
|
+
leaseIds: uniqueTargets.map((target) => target.leaseId),
|
|
2287
|
+
});
|
|
2288
|
+
this.assertRuntimeToolReceiptHeartbeatResults(uniqueTargets, receipts);
|
|
2296
2289
|
}
|
|
2297
2290
|
|
|
2298
2291
|
private async flushRuntimeToolOwnershipAssertionBatch(): Promise<void> {
|
|
@@ -2303,26 +2296,24 @@ export class PlayContextImpl {
|
|
|
2303
2296
|
|
|
2304
2297
|
if (this.#options.heartbeatRuntimeStepReceipts) {
|
|
2305
2298
|
try {
|
|
2306
|
-
const
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2299
|
+
const uniqueTargets = [
|
|
2300
|
+
...new Map(
|
|
2301
|
+
targets.map((target) => [target.receiptKey, target]),
|
|
2302
|
+
).values(),
|
|
2303
|
+
];
|
|
2304
|
+
const receipts = await this.#options.heartbeatRuntimeStepReceipts({
|
|
2305
|
+
runId: this.currentReceiptOwnerRunId,
|
|
2306
|
+
runAttempt: this.currentRunAttempt,
|
|
2307
|
+
keys: uniqueTargets.map((target) => target.receiptKey),
|
|
2308
|
+
leaseIds: uniqueTargets.map((target) => target.leaseId),
|
|
2309
|
+
});
|
|
2312
2310
|
const renewed = new Map<string, RuntimeStepReceipt | null>();
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
keys,
|
|
2320
|
-
});
|
|
2321
|
-
for (let index = 0; index < keys.length; index += 1) {
|
|
2322
|
-
renewed.set(keys[index]!, receipts[index] ?? null);
|
|
2323
|
-
}
|
|
2324
|
-
}),
|
|
2325
|
-
);
|
|
2311
|
+
for (let index = 0; index < uniqueTargets.length; index += 1) {
|
|
2312
|
+
renewed.set(
|
|
2313
|
+
uniqueTargets[index]!.receiptKey,
|
|
2314
|
+
receipts[index] ?? null,
|
|
2315
|
+
);
|
|
2316
|
+
}
|
|
2326
2317
|
for (const assertion of assertions) {
|
|
2327
2318
|
const lost = assertion.targets.find((target) => {
|
|
2328
2319
|
const receipt = renewed.get(target.receiptKey);
|
|
@@ -2385,21 +2376,21 @@ export class PlayContextImpl {
|
|
|
2385
2376
|
for (const assertion of assertions) assertion.reject(error);
|
|
2386
2377
|
}
|
|
2387
2378
|
|
|
2388
|
-
private
|
|
2389
|
-
|
|
2390
|
-
leaseId: string,
|
|
2379
|
+
private assertRuntimeToolReceiptHeartbeatResults(
|
|
2380
|
+
targets: Array<{ receiptKey: string; leaseId: string }>,
|
|
2391
2381
|
receipts: Array<RuntimeStepReceipt | null>,
|
|
2392
2382
|
): void {
|
|
2393
|
-
for (let index = 0; index <
|
|
2383
|
+
for (let index = 0; index < targets.length; index += 1) {
|
|
2384
|
+
const target = targets[index]!;
|
|
2394
2385
|
const receipt = this.normalizeRuntimeStepReceipt(
|
|
2395
|
-
|
|
2386
|
+
target.receiptKey,
|
|
2396
2387
|
receipts[index],
|
|
2397
2388
|
);
|
|
2398
|
-
if (!this.runtimeToolReceiptStillOwned(receipt, leaseId)) {
|
|
2389
|
+
if (!this.runtimeToolReceiptStillOwned(receipt, target.leaseId)) {
|
|
2399
2390
|
throw new RuntimeReceiptLeaseLostError({
|
|
2400
|
-
receiptKey:
|
|
2391
|
+
receiptKey: target.receiptKey,
|
|
2401
2392
|
runId: this.currentReceiptOwnerRunId,
|
|
2402
|
-
leaseId,
|
|
2393
|
+
leaseId: target.leaseId,
|
|
2403
2394
|
});
|
|
2404
2395
|
}
|
|
2405
2396
|
}
|
|
@@ -8040,58 +8031,50 @@ export class PlayContextImpl {
|
|
|
8040
8031
|
this.toolCallResolvers.has(request.callId),
|
|
8041
8032
|
);
|
|
8042
8033
|
if (unsettled.length === 0) return 'terminal';
|
|
8043
|
-
const
|
|
8034
|
+
const byReceiptKey = new Map<string, ToolCallRequest[]>();
|
|
8044
8035
|
for (const request of unsettled) {
|
|
8045
|
-
const leaseId = request.receiptLeaseId!;
|
|
8046
|
-
const byReceiptKey = byLeaseId.get(leaseId) ?? new Map();
|
|
8047
8036
|
const receiptKey = request.receiptKey!;
|
|
8048
8037
|
const group = byReceiptKey.get(receiptKey) ?? [];
|
|
8049
8038
|
group.push(request);
|
|
8050
8039
|
byReceiptKey.set(receiptKey, group);
|
|
8051
|
-
byLeaseId.set(leaseId, byReceiptKey);
|
|
8052
8040
|
}
|
|
8053
|
-
|
|
8054
|
-
|
|
8055
|
-
|
|
8056
|
-
|
|
8057
|
-
|
|
8058
|
-
|
|
8059
|
-
|
|
8060
|
-
|
|
8061
|
-
|
|
8062
|
-
|
|
8041
|
+
// One content-addressed receipt can have many same-run followers. The
|
|
8042
|
+
// store renews unique receipt rows, not request positions, so dedupe by
|
|
8043
|
+
// key while preserving the matching per-row lease id.
|
|
8044
|
+
const entries = [...byReceiptKey];
|
|
8045
|
+
const keys = entries.map(([receiptKey]) => receiptKey);
|
|
8046
|
+
const leaseIds = entries.map(
|
|
8047
|
+
([, requests]) => requests[0]!.receiptLeaseId!,
|
|
8048
|
+
);
|
|
8049
|
+
const receipts = await heartbeatReceipts({
|
|
8050
|
+
runId: this.currentReceiptOwnerRunId,
|
|
8051
|
+
runAttempt: this.currentRunAttempt,
|
|
8052
|
+
keys,
|
|
8053
|
+
leaseIds,
|
|
8054
|
+
});
|
|
8055
|
+
for (let index = 0; index < entries.length; index += 1) {
|
|
8056
|
+
const [receiptKey, requests] = entries[index]!;
|
|
8057
|
+
const leaseId = leaseIds[index]!;
|
|
8058
|
+
// Completion can race this bulk heartbeat response. A settled
|
|
8059
|
+
// receipt group no longer needs ownership and must not turn that
|
|
8060
|
+
// race into a false lease-loss failure.
|
|
8061
|
+
if (
|
|
8062
|
+
!requests.some((request) =>
|
|
8063
|
+
this.toolCallResolvers.has(request.callId),
|
|
8064
|
+
)
|
|
8065
|
+
) {
|
|
8066
|
+
continue;
|
|
8067
|
+
}
|
|
8068
|
+
if (
|
|
8069
|
+
!this.runtimeToolReceiptStillOwned(receipts[index] ?? null, leaseId)
|
|
8070
|
+
) {
|
|
8071
|
+
throw new RuntimeReceiptLeaseLostError({
|
|
8072
|
+
receiptKey,
|
|
8063
8073
|
runId: this.currentReceiptOwnerRunId,
|
|
8064
|
-
runAttempt: this.currentRunAttempt,
|
|
8065
8074
|
leaseId,
|
|
8066
|
-
keys,
|
|
8067
8075
|
});
|
|
8068
|
-
|
|
8069
|
-
|
|
8070
|
-
// Completion can race this bulk heartbeat response. A settled
|
|
8071
|
-
// receipt group no longer needs ownership and must not turn that
|
|
8072
|
-
// race into a false lease-loss failure.
|
|
8073
|
-
if (
|
|
8074
|
-
!requests.some((request) =>
|
|
8075
|
-
this.toolCallResolvers.has(request.callId),
|
|
8076
|
-
)
|
|
8077
|
-
) {
|
|
8078
|
-
continue;
|
|
8079
|
-
}
|
|
8080
|
-
if (
|
|
8081
|
-
!this.runtimeToolReceiptStillOwned(
|
|
8082
|
-
receipts[index] ?? null,
|
|
8083
|
-
leaseId,
|
|
8084
|
-
)
|
|
8085
|
-
) {
|
|
8086
|
-
throw new RuntimeReceiptLeaseLostError({
|
|
8087
|
-
receiptKey,
|
|
8088
|
-
runId: this.currentReceiptOwnerRunId,
|
|
8089
|
-
leaseId,
|
|
8090
|
-
});
|
|
8091
|
-
}
|
|
8092
|
-
}
|
|
8093
|
-
}),
|
|
8094
|
-
);
|
|
8076
|
+
}
|
|
8077
|
+
}
|
|
8095
8078
|
return 'active';
|
|
8096
8079
|
},
|
|
8097
8080
|
isLeaseLost: (error) => error instanceof RuntimeReceiptLeaseLostError,
|
|
@@ -5799,15 +5799,30 @@ export async function heartbeatRuntimeWorkReceipts(
|
|
|
5799
5799
|
playName: string;
|
|
5800
5800
|
runId: string;
|
|
5801
5801
|
runAttempt?: number | null;
|
|
5802
|
-
leaseId
|
|
5802
|
+
leaseId?: string;
|
|
5803
|
+
leaseIds?: string[];
|
|
5803
5804
|
keys: string[];
|
|
5804
5805
|
leaseTtlMs?: number | null;
|
|
5805
5806
|
},
|
|
5806
5807
|
): Promise<Array<WorkReceipt | null>> {
|
|
5807
|
-
|
|
5808
|
+
if (
|
|
5809
|
+
input.leaseIds !== undefined &&
|
|
5810
|
+
input.leaseIds.length !== input.keys.length
|
|
5811
|
+
) {
|
|
5812
|
+
throw new Error(
|
|
5813
|
+
`Runtime receipt bulk heartbeat requires one lease ID per key. Received ${input.leaseIds.length} lease IDs for ${input.keys.length} keys.`,
|
|
5814
|
+
);
|
|
5815
|
+
}
|
|
5816
|
+
const entries = input.keys
|
|
5817
|
+
.map((key, index) => ({
|
|
5818
|
+
key: key.trim(),
|
|
5819
|
+
leaseId: input.leaseIds?.[index]?.trim() || input.leaseId?.trim() || '',
|
|
5820
|
+
}))
|
|
5821
|
+
.filter((entry) => Boolean(entry.key));
|
|
5822
|
+
const keys = entries.map((entry) => entry.key);
|
|
5808
5823
|
if (keys.length === 0) return [];
|
|
5809
|
-
const
|
|
5810
|
-
if (!leaseId) return keys.map(() => null);
|
|
5824
|
+
const leaseIds = entries.map((entry) => entry.leaseId);
|
|
5825
|
+
if (leaseIds.some((leaseId) => !leaseId)) return keys.map(() => null);
|
|
5811
5826
|
const runAttempt = normalizeRuntimeRunAttempt(input.runAttempt);
|
|
5812
5827
|
const leaseTtlMs = normalizeRuntimeLeaseTtlMs(
|
|
5813
5828
|
input.leaseTtlMs,
|
|
@@ -5824,8 +5839,10 @@ export async function heartbeatRuntimeWorkReceipts(
|
|
|
5824
5839
|
const { rows } = await client.query<Record<string, unknown>>(
|
|
5825
5840
|
`
|
|
5826
5841
|
WITH input_keys AS (
|
|
5827
|
-
SELECT key_values.key_hex, key_values.ord
|
|
5842
|
+
SELECT key_values.key_hex, lease_values.lease_id, key_values.ord
|
|
5828
5843
|
FROM unnest($1::text[]) WITH ORDINALITY AS key_values(key_hex, ord)
|
|
5844
|
+
JOIN unnest($3::text[]) WITH ORDINALITY AS lease_values(lease_id, ord)
|
|
5845
|
+
ON lease_values.ord = key_values.ord
|
|
5829
5846
|
),
|
|
5830
5847
|
renewed AS (
|
|
5831
5848
|
UPDATE ${workReceiptTable(session)} AS target
|
|
@@ -5837,7 +5854,7 @@ export async function heartbeatRuntimeWorkReceipts(
|
|
|
5837
5854
|
receiptTable: 'target',
|
|
5838
5855
|
ownerRunIdSql: '$2::text',
|
|
5839
5856
|
ownerRunAttemptSql: '$5',
|
|
5840
|
-
leaseIdSql: '
|
|
5857
|
+
leaseIdSql: 'input_keys.lease_id',
|
|
5841
5858
|
})}
|
|
5842
5859
|
RETURNING target.k,
|
|
5843
5860
|
target.status,
|
|
@@ -5888,7 +5905,7 @@ export async function heartbeatRuntimeWorkReceipts(
|
|
|
5888
5905
|
[
|
|
5889
5906
|
keys.map(workReceiptKeyHex),
|
|
5890
5907
|
input.runId,
|
|
5891
|
-
|
|
5908
|
+
leaseIds,
|
|
5892
5909
|
leaseTtlMs,
|
|
5893
5910
|
runAttempt,
|
|
5894
5911
|
],
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export const PLAY_RUNTIME_CONTRACT =
|
|
1
|
+
export const PLAY_RUNTIME_CONTRACT = 4;
|
|
2
2
|
export const PLAY_RUNTIME_CONTRACT_MIN_SUPPORTED = 1;
|
|
3
3
|
export const PLAY_RUNTIME_CONTRACT_HEADER = 'x-deepline-runtime-contract';
|
|
4
4
|
/**
|
|
@@ -25,6 +25,13 @@ export function resolvePlayRuntimeTransportAttemptId(
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
export const RUNTIME_CONTRACT_CHANGELOG = [
|
|
28
|
+
{
|
|
29
|
+
contract: 4,
|
|
30
|
+
changed:
|
|
31
|
+
'Runtime receipt heartbeat requests can carry one positional lease ID per receipt key.',
|
|
32
|
+
compatOwner: 'runtime',
|
|
33
|
+
compatRemoval: 'contract 3 runtime lane drain',
|
|
34
|
+
},
|
|
28
35
|
{
|
|
29
36
|
contract: 3,
|
|
30
37
|
changed:
|
|
@@ -236,13 +236,13 @@ export class RuntimeReceiptStoreAdapter {
|
|
|
236
236
|
),
|
|
237
237
|
heartbeatRuntimeStepReceipts: (input) =>
|
|
238
238
|
writeMany(
|
|
239
|
-
input.keys.map((key) => ({
|
|
239
|
+
input.keys.map((key, index) => ({
|
|
240
240
|
kind: 'heartbeat' as const,
|
|
241
241
|
input: {
|
|
242
242
|
key,
|
|
243
243
|
runId: input.runId,
|
|
244
244
|
runAttempt: input.runAttempt,
|
|
245
|
-
leaseId: input.leaseId,
|
|
245
|
+
leaseId: input.leaseIds?.[index] ?? input.leaseId ?? '',
|
|
246
246
|
},
|
|
247
247
|
})),
|
|
248
248
|
),
|
|
@@ -387,7 +387,6 @@ function receiptCommandBatchKey(command: ReceiptCommand): string {
|
|
|
387
387
|
command.kind,
|
|
388
388
|
command.input.runId,
|
|
389
389
|
command.input.runAttempt ?? null,
|
|
390
|
-
command.input.leaseId,
|
|
391
390
|
]);
|
|
392
391
|
case 'acquire_execution_lock':
|
|
393
392
|
case 'release_execution_lock':
|
|
@@ -491,11 +490,15 @@ async function sendReceiptCommands(input: {
|
|
|
491
490
|
ReceiptCommand,
|
|
492
491
|
{ kind: 'heartbeat' }
|
|
493
492
|
>[];
|
|
493
|
+
const leaseIds = commands.map((command) => command.input.leaseId);
|
|
494
|
+
const sharedLeaseId = leaseIds.every((leaseId) => leaseId === leaseIds[0])
|
|
495
|
+
? leaseIds[0]
|
|
496
|
+
: undefined;
|
|
494
497
|
return await heartbeatRuntimeStepReceiptsViaAppRuntime(input.context, {
|
|
495
498
|
playName: input.playName,
|
|
496
499
|
runId: first.input.runId,
|
|
497
500
|
runAttempt: first.input.runAttempt,
|
|
498
|
-
leaseId:
|
|
501
|
+
...(sharedLeaseId ? { leaseId: sharedLeaseId } : { leaseIds }),
|
|
499
502
|
keys: commands.map((command) => command.input.key),
|
|
500
503
|
});
|
|
501
504
|
}
|
package/dist/cli/index.js
CHANGED
|
@@ -1040,7 +1040,7 @@ var SDK_RELEASE = {
|
|
|
1040
1040
|
// 0.2.0 makes Dataset Handles uniformly async-only after 0.1.320 briefly
|
|
1041
1041
|
// exposed storage-dependent synchronous access. This deliberate minor
|
|
1042
1042
|
// release keeps lazy paging semantics independent of row residency.
|
|
1043
|
-
version: "0.2.
|
|
1043
|
+
version: "0.2.13",
|
|
1044
1044
|
contracts: {
|
|
1045
1045
|
api: {
|
|
1046
1046
|
name: "sdk-http-api",
|
package/dist/cli/index.mjs
CHANGED
|
@@ -1025,7 +1025,7 @@ var SDK_RELEASE = {
|
|
|
1025
1025
|
// 0.2.0 makes Dataset Handles uniformly async-only after 0.1.320 briefly
|
|
1026
1026
|
// exposed storage-dependent synchronous access. This deliberate minor
|
|
1027
1027
|
// release keeps lazy paging semantics independent of row residency.
|
|
1028
|
-
version: "0.2.
|
|
1028
|
+
version: "0.2.13",
|
|
1029
1029
|
contracts: {
|
|
1030
1030
|
api: {
|
|
1031
1031
|
name: "sdk-http-api",
|
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.
|
|
766
|
+
version: "0.2.13",
|
|
767
767
|
contracts: {
|
|
768
768
|
api: {
|
|
769
769
|
name: "sdk-http-api",
|
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.
|
|
692
|
+
version: "0.2.13",
|
|
693
693
|
contracts: {
|
|
694
694
|
api: {
|
|
695
695
|
name: "sdk-http-api",
|