deepline 0.2.12 → 0.2.14
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/client.ts +159 -3
- package/dist/bundling-sources/sdk/src/index.ts +3 -0
- package/dist/bundling-sources/sdk/src/play.ts +150 -691
- package/dist/bundling-sources/sdk/src/release.ts +1 -1
- package/dist/bundling-sources/shared_libs/play-runtime/child-execution-strategy.ts +7 -1
- package/dist/bundling-sources/shared_libs/play-runtime/context.ts +319 -138
- package/dist/bundling-sources/shared_libs/play-runtime/csv-rename.ts +10 -6
- package/dist/bundling-sources/shared_libs/play-runtime/ctx-types.ts +34 -52
- package/dist/bundling-sources/shared_libs/play-runtime/durable-call-cache.ts +11 -22
- package/dist/bundling-sources/shared_libs/play-runtime/durable-call-policy.ts +34 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-call-execution.ts +2 -1
- package/dist/bundling-sources/shared_libs/play-runtime/run-ledger-projection-contract.ts +95 -0
- 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/bundling-sources/shared_libs/play-runtime/secret-capability.ts +23 -15
- package/dist/bundling-sources/shared_libs/plays/artifact-types.ts +3 -0
- package/dist/bundling-sources/shared_libs/plays/authoring-contract.ts +2222 -0
- package/dist/bundling-sources/shared_libs/plays/bundling/index.ts +3 -2
- package/dist/bundling-sources/shared_libs/plays/compiler-manifest.ts +2 -0
- package/dist/bundling-sources/shared_libs/plays/contracts.ts +16 -0
- package/dist/bundling-sources/shared_libs/plays/input-contract-definition.ts +28 -0
- package/dist/bundling-sources/shared_libs/plays/input-contract.ts +3 -3
- package/dist/cli/index.js +5231 -830
- package/dist/cli/index.mjs +5178 -762
- package/dist/compiler-manifest-xFkbJX2B.d.mts +2517 -0
- package/dist/compiler-manifest-xFkbJX2B.d.ts +2517 -0
- package/dist/index.d.mts +126 -1014
- package/dist/index.d.ts +126 -1014
- package/dist/index.js +88 -8
- package/dist/index.mjs +88 -8
- package/dist/plays/bundle-play-file.d.mts +5 -8
- package/dist/plays/bundle-play-file.d.ts +5 -8
- package/dist/plays/bundle-play-file.mjs +3844 -3
- package/package.json +1 -1
- package/dist/bundling-sources/shared_libs/plays/source-metadata.ts +0 -240
- package/dist/tool-execution-error-4-rhemLQ.d.mts +0 -446
- package/dist/tool-execution-error-4-rhemLQ.d.ts +0 -446
|
@@ -1,10 +1,14 @@
|
|
|
1
|
-
|
|
1
|
+
import type {
|
|
2
|
+
PlayAuthoringCsvOptions,
|
|
3
|
+
PlayAuthoringCsvRenameMap,
|
|
4
|
+
} from '../plays/authoring-contract';
|
|
2
5
|
|
|
3
|
-
export type
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
export type CsvRenameMap = PlayAuthoringCsvRenameMap;
|
|
7
|
+
|
|
8
|
+
export type CsvRenameOptions = Pick<
|
|
9
|
+
PlayAuthoringCsvOptions,
|
|
10
|
+
'columns' | 'rename' | 'required'
|
|
11
|
+
>;
|
|
8
12
|
|
|
9
13
|
const CSV_PROJECTED_FIELDS = Symbol.for('deepline.play.csv.projected_fields');
|
|
10
14
|
const CSV_PROJECTED_FIELDS_KEY = '__deeplineCsvProjectedFields';
|
|
@@ -3,6 +3,18 @@ import type { PlayBundleArtifact } from '../plays/artifact-types';
|
|
|
3
3
|
import type { PlayRunContractSnapshot } from '../plays/contracts';
|
|
4
4
|
import type { PlayStructuredDefinition } from '../plays/definition';
|
|
5
5
|
import type { PlayStaticPipeline } from '../plays/static-pipeline';
|
|
6
|
+
import type {
|
|
7
|
+
DurableCallStaleAfterSeconds,
|
|
8
|
+
PlayAuthoringCallOptions,
|
|
9
|
+
PlayAuthoringCsvOptions,
|
|
10
|
+
PlayAuthoringFetchOptions,
|
|
11
|
+
PlayAuthoringRuntimeStepOptions,
|
|
12
|
+
PlayAuthoringContractEdition,
|
|
13
|
+
PlayToolCallOptions,
|
|
14
|
+
PlayToolExecutionRequest,
|
|
15
|
+
PlayReceiptWaitMs,
|
|
16
|
+
PlayRuntimeTimeoutMs,
|
|
17
|
+
} from '../plays/authoring-contract';
|
|
6
18
|
import type {
|
|
7
19
|
PlayDataset,
|
|
8
20
|
PlayDatasetInput,
|
|
@@ -204,17 +216,13 @@ export interface HeartbeatRuntimeStepReceiptsInput {
|
|
|
204
216
|
keys: string[];
|
|
205
217
|
runId: string;
|
|
206
218
|
runAttempt?: number | null;
|
|
207
|
-
leaseId
|
|
219
|
+
leaseId?: string;
|
|
220
|
+
leaseIds?: string[];
|
|
208
221
|
}
|
|
209
222
|
|
|
210
|
-
export
|
|
211
|
-
description?: string;
|
|
212
|
-
columns?: Record<string, string | readonly string[]>;
|
|
213
|
-
rename?: Record<string, string | readonly string[]>;
|
|
214
|
-
required?: readonly string[];
|
|
215
|
-
}
|
|
223
|
+
export type CsvOptions = PlayAuthoringCsvOptions;
|
|
216
224
|
|
|
217
|
-
export interface
|
|
225
|
+
export interface RuntimeDatasetOptions<TItem = Record<string, unknown>> {
|
|
218
226
|
description?: string;
|
|
219
227
|
/**
|
|
220
228
|
* Optional relative cache window for intentional reruns.
|
|
@@ -269,58 +277,30 @@ export interface DatasetOptions<TItem = Record<string, unknown>> {
|
|
|
269
277
|
mode?: 'upsert' | 'net_new';
|
|
270
278
|
}
|
|
271
279
|
|
|
272
|
-
export type
|
|
273
|
-
|
|
274
|
-
'description'
|
|
275
|
-
>;
|
|
280
|
+
export type RuntimeDatasetDefinitionOptions<TItem = Record<string, unknown>> =
|
|
281
|
+
Omit<RuntimeDatasetOptions<TItem>, 'description'>;
|
|
276
282
|
|
|
277
|
-
export type
|
|
278
|
-
|
|
283
|
+
export type RuntimeDatasetRunOptions<TItem = Record<string, unknown>> = Pick<
|
|
284
|
+
RuntimeDatasetOptions<TItem>,
|
|
279
285
|
'description' | 'key' | 'onRowError' | 'mode'
|
|
280
286
|
>;
|
|
281
287
|
|
|
282
|
-
export
|
|
283
|
-
|
|
284
|
-
force?: boolean;
|
|
285
|
-
staleAfterSeconds?: number;
|
|
286
|
-
timeoutMs?: number;
|
|
287
|
-
receiptWaitMs?: number;
|
|
288
|
-
}
|
|
288
|
+
export type ToolCallOptions = PlayToolCallOptions;
|
|
289
|
+
export type ToolExecutionRequest = PlayToolExecutionRequest;
|
|
289
290
|
|
|
290
|
-
export
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
force?: boolean;
|
|
296
|
-
staleAfterSeconds?: number;
|
|
297
|
-
timeoutMs?: number;
|
|
298
|
-
receiptWaitMs?: number;
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
export interface PlayCallOptions {
|
|
302
|
-
description?: string;
|
|
303
|
-
/**
|
|
304
|
-
* `child-workflow` is accepted only so the checker/runtime can emit the
|
|
305
|
-
* canonical CTX_RUN_PLAY_INLINE_ONLY migration diagnostic. It never starts a
|
|
306
|
-
* child workflow.
|
|
307
|
-
*/
|
|
291
|
+
export type PlayCallOptions = Omit<
|
|
292
|
+
PlayAuthoringCallOptions,
|
|
293
|
+
'execution' | 'timeoutMs'
|
|
294
|
+
> & {
|
|
295
|
+
/** Legacy invalid spelling retained only for the stable migration error. */
|
|
308
296
|
execution?: PlayCallExecution | 'child-workflow';
|
|
309
|
-
/**
|
|
310
|
-
* Parsed so source preflight and an untyped runtime call can return the
|
|
311
|
-
* canonical CTX_RUN_PLAY_INLINE_ONLY migration error. It is never honored.
|
|
312
|
-
*/
|
|
297
|
+
/** Legacy invalid option retained only for the stable migration error. */
|
|
313
298
|
timeoutMs?: number;
|
|
314
|
-
}
|
|
299
|
+
};
|
|
315
300
|
|
|
316
|
-
export
|
|
317
|
-
semanticKey?: string;
|
|
318
|
-
staleAfterSeconds?: number;
|
|
319
|
-
}
|
|
301
|
+
export type RuntimeStepOptions = PlayAuthoringRuntimeStepOptions;
|
|
320
302
|
|
|
321
|
-
export
|
|
322
|
-
staleAfterSeconds?: number;
|
|
323
|
-
}
|
|
303
|
+
export type FetchOptions = PlayAuthoringFetchOptions;
|
|
324
304
|
|
|
325
305
|
export interface ResolvedPlayExecution {
|
|
326
306
|
playId: string;
|
|
@@ -501,6 +481,8 @@ export type IntegrationEventWaitHandler = {
|
|
|
501
481
|
export interface ContextOptions {
|
|
502
482
|
/** Immutable logical and physical execution identity for this context. */
|
|
503
483
|
executionScope?: RunExecutionScope;
|
|
484
|
+
/** Authoring semantics pinned by the immutable artifact. */
|
|
485
|
+
authoringContractEdition?: PlayAuthoringContractEdition;
|
|
504
486
|
/** Error shape pinned by the immutable play artifact; missing preserves legacy schema 0. */
|
|
505
487
|
toolErrorSchemaVersion?: ToolExecutionErrorSchemaVersion;
|
|
506
488
|
/** Short-lived HMAC-signed internal token for tool callbacks. Required for cloud execution. */
|
|
@@ -588,7 +570,7 @@ export interface ContextOptions {
|
|
|
588
570
|
staticPipeline?: PlayStaticPipeline | null;
|
|
589
571
|
forceRefresh?: boolean;
|
|
590
572
|
inputOffset?: number;
|
|
591
|
-
mode?:
|
|
573
|
+
mode?: RuntimeDatasetRunOptions['mode'];
|
|
592
574
|
},
|
|
593
575
|
) => Promise<MapStartResult>;
|
|
594
576
|
/**
|
|
@@ -6,40 +6,29 @@ import {
|
|
|
6
6
|
// packed SDK's dist/bundling-sources graph, where only relative imports
|
|
7
7
|
// resolve.
|
|
8
8
|
} from '../plays/row-identity';
|
|
9
|
+
import { resolveDurableCallCachePolicy } from './durable-call-policy';
|
|
10
|
+
|
|
11
|
+
export {
|
|
12
|
+
DURABLE_CALL_STALE_AFTER_SECONDS_ERROR,
|
|
13
|
+
resolveDurableCallCachePolicy,
|
|
14
|
+
} from './durable-call-policy';
|
|
15
|
+
export type { DurableCallCachePolicy } from './durable-call-policy';
|
|
9
16
|
|
|
10
17
|
export const DURABLE_CALL_CACHE_POLICY_VERSION = 'call-cache-v1';
|
|
11
18
|
|
|
12
19
|
export type DurableCallKind = 'tool' | 'step' | 'fetch';
|
|
13
20
|
|
|
14
|
-
function validateStaleAfterSeconds(staleAfterSeconds?: number | null): void {
|
|
15
|
-
if (staleAfterSeconds === undefined || staleAfterSeconds === null) {
|
|
16
|
-
return;
|
|
17
|
-
}
|
|
18
|
-
if (
|
|
19
|
-
!Number.isFinite(staleAfterSeconds) ||
|
|
20
|
-
!Number.isInteger(staleAfterSeconds) ||
|
|
21
|
-
staleAfterSeconds <= 0
|
|
22
|
-
) {
|
|
23
|
-
throw new Error(
|
|
24
|
-
'staleAfterSeconds must be a positive whole number of seconds.',
|
|
25
|
-
);
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
21
|
export function durableCacheStaleBucket(input: {
|
|
30
22
|
staleAfterSeconds?: number | null;
|
|
31
23
|
nowMs?: number;
|
|
32
24
|
}): string | null {
|
|
33
|
-
|
|
34
|
-
if (
|
|
35
|
-
input.staleAfterSeconds === undefined ||
|
|
36
|
-
input.staleAfterSeconds === null
|
|
37
|
-
) {
|
|
25
|
+
const policy = resolveDurableCallCachePolicy(input.staleAfterSeconds);
|
|
26
|
+
if (policy.staleAfterSeconds === null) {
|
|
38
27
|
return null;
|
|
39
28
|
}
|
|
40
29
|
const nowMs = input.nowMs ?? Date.now();
|
|
41
|
-
return `${
|
|
42
|
-
nowMs / (
|
|
30
|
+
return `${policy.staleAfterSeconds}:${Math.floor(
|
|
31
|
+
nowMs / (policy.staleAfterSeconds * 1000),
|
|
43
32
|
)}`;
|
|
44
33
|
}
|
|
45
34
|
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import {
|
|
2
|
+
PLAY_AUTHORING_FIELD_REGISTRY,
|
|
3
|
+
validatePlayAuthoringField,
|
|
4
|
+
type PlayAuthoringFieldPath,
|
|
5
|
+
} from '../plays/authoring-contract';
|
|
6
|
+
|
|
7
|
+
export const DURABLE_CALL_STALE_AFTER_SECONDS_ERROR =
|
|
8
|
+
PLAY_AUTHORING_FIELD_REGISTRY['ctx.tools.execute.staleAfterSeconds']
|
|
9
|
+
.errorMessage;
|
|
10
|
+
|
|
11
|
+
export type DurableCallCachePolicy = {
|
|
12
|
+
forceRefresh: boolean;
|
|
13
|
+
staleAfterSeconds: number | null;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
/** Normalize the public freshness contract shared by durable calls. */
|
|
17
|
+
export function resolveDurableCallCachePolicy(
|
|
18
|
+
staleAfterSeconds?: number | null,
|
|
19
|
+
path: Extract<
|
|
20
|
+
PlayAuthoringFieldPath,
|
|
21
|
+
| 'ctx.tools.execute.staleAfterSeconds'
|
|
22
|
+
| 'ctx.step.staleAfterSeconds'
|
|
23
|
+
| 'ctx.fetch.staleAfterSeconds'
|
|
24
|
+
> = 'ctx.tools.execute.staleAfterSeconds',
|
|
25
|
+
): DurableCallCachePolicy {
|
|
26
|
+
if (staleAfterSeconds === undefined || staleAfterSeconds === null) {
|
|
27
|
+
return { forceRefresh: false, staleAfterSeconds: null };
|
|
28
|
+
}
|
|
29
|
+
if (staleAfterSeconds === 0) {
|
|
30
|
+
return { forceRefresh: true, staleAfterSeconds: null };
|
|
31
|
+
}
|
|
32
|
+
validatePlayAuthoringField(path, staleAfterSeconds);
|
|
33
|
+
return { forceRefresh: false, staleAfterSeconds };
|
|
34
|
+
}
|
|
@@ -3,4 +3,5 @@
|
|
|
3
3
|
* recognizes the historical `child-workflow` spelling so preflight can return
|
|
4
4
|
* CTX_RUN_PLAY_INLINE_ONLY, but it is no longer a supported runtime option.
|
|
5
5
|
*/
|
|
6
|
-
export type PlayCallExecution = 'inline'
|
|
6
|
+
export type PlayCallExecution = Extract<PlayAuthoringCallExecution, 'inline'>;
|
|
7
|
+
import type { PlayAuthoringCallExecution } from '../plays/authoring-contract';
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wire contract for idempotent Runtime Postgres -> Convex Run Ledger delivery.
|
|
3
|
+
*
|
|
4
|
+
* Producers must use these builders and API boundaries must use these
|
|
5
|
+
* validators. Keeping the format here prevents the scheduler and runtime route
|
|
6
|
+
* from admitting different lifecycle-event keys.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const UUID_PATTERN =
|
|
10
|
+
/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
11
|
+
const SHA256_HEX_PATTERN = /^[0-9a-f]{64}$/i;
|
|
12
|
+
|
|
13
|
+
function requireRunId(runId: string): void {
|
|
14
|
+
if (!runId.trim()) {
|
|
15
|
+
throw new Error('Run Ledger projection idempotency key requires a run id.');
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function requireDeliveryKey(deliveryKey: string): void {
|
|
20
|
+
if (!UUID_PATTERN.test(deliveryKey)) {
|
|
21
|
+
throw new Error(
|
|
22
|
+
'Run Ledger projection delivery key must be a canonical UUID.',
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function buildRunLedgerStartIdempotencyKey(input: {
|
|
28
|
+
runId: string;
|
|
29
|
+
deliveryKey: string;
|
|
30
|
+
}): string {
|
|
31
|
+
requireRunId(input.runId);
|
|
32
|
+
requireDeliveryKey(input.deliveryKey);
|
|
33
|
+
return `run-started:${input.runId}:${input.deliveryKey}`;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function buildRunLedgerTerminalIdempotencyKey(input: {
|
|
37
|
+
runId: string;
|
|
38
|
+
deliveryKey: string;
|
|
39
|
+
}): string {
|
|
40
|
+
requireRunId(input.runId);
|
|
41
|
+
requireDeliveryKey(input.deliveryKey);
|
|
42
|
+
return `run-terminal:${input.runId}:${input.deliveryKey}`;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Compatibility key for the one-row projector. The `run-terminal` prefix was
|
|
47
|
+
* historically used for every non-start row, including lifecycle events, so
|
|
48
|
+
* changing it during a retry could append the same fact twice across deploys.
|
|
49
|
+
*/
|
|
50
|
+
export function buildRunLedgerSingleEventIdempotencyKey(input: {
|
|
51
|
+
runId: string;
|
|
52
|
+
deliveryKey: string;
|
|
53
|
+
}): string {
|
|
54
|
+
return buildRunLedgerTerminalIdempotencyKey(input);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function buildRunLedgerEventsIdempotencyKey(input: {
|
|
58
|
+
runId: string;
|
|
59
|
+
deliveryDigest: string;
|
|
60
|
+
}): string {
|
|
61
|
+
requireRunId(input.runId);
|
|
62
|
+
if (!SHA256_HEX_PATTERN.test(input.deliveryDigest)) {
|
|
63
|
+
throw new Error(
|
|
64
|
+
'Run Ledger projection delivery digest must be a SHA-256 hex value.',
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
return `run-events:${input.runId}:${input.deliveryDigest}`;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export function isValidRunLedgerStartIdempotencyKey(input: {
|
|
71
|
+
runId: string;
|
|
72
|
+
idempotencyKey: string;
|
|
73
|
+
}): boolean {
|
|
74
|
+
const prefix = `run-started:${input.runId}:`;
|
|
75
|
+
return (
|
|
76
|
+
input.idempotencyKey.startsWith(prefix) &&
|
|
77
|
+
UUID_PATTERN.test(input.idempotencyKey.slice(prefix.length))
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export function isValidRunLedgerAppendIdempotencyKey(input: {
|
|
82
|
+
runId: string;
|
|
83
|
+
idempotencyKey: string;
|
|
84
|
+
}): boolean {
|
|
85
|
+
const terminalPrefix = `run-terminal:${input.runId}:`;
|
|
86
|
+
if (input.idempotencyKey.startsWith(terminalPrefix)) {
|
|
87
|
+
return UUID_PATTERN.test(input.idempotencyKey.slice(terminalPrefix.length));
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const eventsPrefix = `run-events:${input.runId}:`;
|
|
91
|
+
return (
|
|
92
|
+
input.idempotencyKey.startsWith(eventsPrefix) &&
|
|
93
|
+
SHA256_HEX_PATTERN.test(input.idempotencyKey.slice(eventsPrefix.length))
|
|
94
|
+
);
|
|
95
|
+
}
|
|
@@ -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
|
}
|
|
@@ -1,28 +1,36 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
PlaySecretAuth,
|
|
3
|
+
PlaySecretAwareRequestInit,
|
|
4
|
+
PlaySecretHandle,
|
|
5
|
+
} from '../plays/authoring-contract';
|
|
6
|
+
|
|
1
7
|
const SECRET_HANDLE_BRAND = Symbol.for('deepline.secret.handle');
|
|
2
8
|
const SECRET_AUTH_BRAND = Symbol.for('deepline.secret.auth');
|
|
3
9
|
const SECRET_HANDLE_MARKER_RE = /\[secret:[A-Z0-9_ -]+\]/i;
|
|
4
10
|
|
|
5
|
-
export type SecretHandle = {
|
|
11
|
+
export type SecretHandle = PlaySecretHandle & {
|
|
6
12
|
readonly [SECRET_HANDLE_BRAND]: true;
|
|
7
13
|
readonly name: string;
|
|
8
14
|
toString(): string;
|
|
9
15
|
toJSON(): never;
|
|
10
16
|
};
|
|
11
17
|
|
|
12
|
-
export type SecretAuth =
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
18
|
+
export type SecretAuth = PlaySecretAuth &
|
|
19
|
+
(
|
|
20
|
+
| {
|
|
21
|
+
readonly [SECRET_AUTH_BRAND]: true;
|
|
22
|
+
readonly kind: 'bearer';
|
|
23
|
+
readonly secret: SecretHandle;
|
|
24
|
+
}
|
|
25
|
+
| {
|
|
26
|
+
readonly [SECRET_AUTH_BRAND]: true;
|
|
27
|
+
readonly kind: 'header';
|
|
28
|
+
readonly header: string;
|
|
29
|
+
readonly secret: SecretHandle;
|
|
30
|
+
}
|
|
31
|
+
);
|
|
24
32
|
|
|
25
|
-
export type SecretAwareRequestInit =
|
|
33
|
+
export type SecretAwareRequestInit = PlaySecretAwareRequestInit & {
|
|
26
34
|
auth?: SecretAuth;
|
|
27
35
|
};
|
|
28
36
|
|
|
@@ -70,7 +78,7 @@ export function createSecretHandle(name: string): SecretHandle {
|
|
|
70
78
|
`Secret ${name} cannot be serialized. Use an approved ctx.secrets helper.`,
|
|
71
79
|
);
|
|
72
80
|
},
|
|
73
|
-
};
|
|
81
|
+
} as unknown as SecretHandle;
|
|
74
82
|
}
|
|
75
83
|
|
|
76
84
|
export function createBearerSecretAuth(secret: SecretHandle): SecretAuth {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ToolExecutionErrorSchemaVersion } from '../tool-execution-error';
|
|
2
|
+
import type { PlayAuthoringContractEdition } from './authoring-contract';
|
|
2
3
|
|
|
3
4
|
export type PlayPackageImport = {
|
|
4
5
|
name: string;
|
|
@@ -25,6 +26,8 @@ export type PlayArtifactCompatibility = {
|
|
|
25
26
|
runtimeBackend?: string | null;
|
|
26
27
|
/** Missing preserves the legacy schema used before this field existed. */
|
|
27
28
|
toolErrorSchemaVersion?: ToolExecutionErrorSchemaVersion;
|
|
29
|
+
/** Missing preserves edition 1 for artifacts created before authoring contracts were pinned. */
|
|
30
|
+
authoringContractEdition?: PlayAuthoringContractEdition;
|
|
28
31
|
};
|
|
29
32
|
|
|
30
33
|
/** The only executable Play artifact contract. */
|