deepline 0.1.182 → 0.1.183
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/apps/play-runner-workers/src/child-play-await.ts +203 -6
- package/dist/bundling-sources/apps/play-runner-workers/src/child-play-submit.ts +8 -1
- package/dist/bundling-sources/apps/play-runner-workers/src/coordinator-entry.ts +633 -107
- package/dist/bundling-sources/apps/play-runner-workers/src/dedup-do.ts +3 -2
- package/dist/bundling-sources/apps/play-runner-workers/src/entry.ts +1747 -1890
- package/dist/bundling-sources/apps/play-runner-workers/src/runtime/harness-receipt-store.ts +116 -0
- package/dist/bundling-sources/apps/play-runner-workers/src/runtime/map-chunk-plan.ts +542 -78
- package/dist/bundling-sources/apps/play-runner-workers/src/runtime/receipts.ts +292 -11
- package/dist/bundling-sources/apps/play-runner-workers/src/runtime/run-work-dispatcher.ts +519 -0
- package/dist/bundling-sources/apps/play-runner-workers/src/runtime/tool-dispatch.ts +2381 -0
- package/dist/bundling-sources/apps/play-runner-workers/src/runtime/tool-receipts.ts +18 -5
- package/dist/bundling-sources/apps/play-runner-workers/src/runtime/work-budget.ts +130 -0
- package/dist/bundling-sources/apps/play-runner-workers/src/runtime/worker-platform-budget.ts +39 -0
- package/dist/bundling-sources/apps/play-runner-workers/src/workflow-retry-state.ts +2 -0
- package/dist/bundling-sources/sdk/src/client.ts +41 -0
- package/dist/bundling-sources/sdk/src/http.ts +23 -8
- package/dist/bundling-sources/sdk/src/plays/harness-stub.ts +56 -3
- package/dist/bundling-sources/sdk/src/release.ts +2 -2
- package/dist/bundling-sources/sdk/src/types.ts +2 -0
- package/dist/bundling-sources/shared_libs/play-runtime/app-runtime-api.ts +132 -10
- package/dist/bundling-sources/shared_libs/play-runtime/auth-scope-resolver.ts +92 -0
- package/dist/bundling-sources/shared_libs/play-runtime/batch-runtime.ts +4 -4
- package/dist/bundling-sources/shared_libs/play-runtime/batching-types.ts +8 -0
- package/dist/bundling-sources/shared_libs/play-runtime/child-run-id.ts +101 -0
- package/dist/bundling-sources/shared_libs/play-runtime/context.ts +1605 -281
- package/dist/bundling-sources/shared_libs/play-runtime/ctx-types.ts +105 -6
- package/dist/bundling-sources/shared_libs/play-runtime/dedup-backend.ts +0 -0
- package/dist/bundling-sources/shared_libs/play-runtime/default-batch-strategies.ts +1 -0
- package/dist/bundling-sources/shared_libs/play-runtime/durability-store.ts +4 -0
- package/dist/bundling-sources/shared_libs/play-runtime/durable-call-cache.ts +116 -16
- package/dist/bundling-sources/shared_libs/play-runtime/durable-receipt-execution.ts +186 -20
- package/dist/bundling-sources/shared_libs/play-runtime/dynamic-worker-version.ts +2 -0
- package/dist/bundling-sources/shared_libs/play-runtime/execution-ledger-store.ts +133 -0
- package/dist/bundling-sources/shared_libs/play-runtime/governor/app-runtime-rate-state-backend.ts +245 -0
- package/dist/bundling-sources/shared_libs/play-runtime/governor/governor.ts +5 -5
- package/dist/bundling-sources/shared_libs/play-runtime/governor/policy.ts +14 -0
- package/dist/bundling-sources/shared_libs/play-runtime/lease-policy.ts +52 -0
- package/dist/bundling-sources/shared_libs/play-runtime/protocol.ts +41 -0
- package/dist/bundling-sources/shared_libs/play-runtime/providers.ts +3 -2
- package/dist/bundling-sources/shared_libs/play-runtime/receipt-sql.ts +124 -0
- package/dist/bundling-sources/shared_libs/play-runtime/receipt-status.ts +6 -2
- package/dist/bundling-sources/shared_libs/play-runtime/row-isolation.ts +48 -2
- package/dist/bundling-sources/shared_libs/play-runtime/run-ledger.ts +158 -15
- package/dist/bundling-sources/shared_libs/play-runtime/run-terminal-source.ts +45 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-actions.ts +9 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-api.ts +2037 -262
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-contract.ts +42 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-sheet-attempt-state-machine.ts +183 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-sheet-errors.ts +88 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backend.ts +8 -1
- package/dist/bundling-sources/shared_libs/play-runtime/sheet-attempt-sql.ts +103 -0
- package/dist/bundling-sources/shared_libs/play-runtime/suspension.ts +19 -1
- package/dist/bundling-sources/shared_libs/play-runtime/test-runtime-seams.ts +343 -0
- package/dist/bundling-sources/shared_libs/play-runtime/tool-execute-retry-policy.ts +43 -0
- package/dist/bundling-sources/shared_libs/play-runtime/tool-http-errors.ts +11 -0
- package/dist/bundling-sources/shared_libs/play-runtime/work-receipt-state-machine.ts +437 -0
- package/dist/bundling-sources/shared_libs/play-runtime/work-receipts.ts +83 -6
- package/dist/bundling-sources/shared_libs/security/safe-outbound-fetch.ts +24 -17
- package/dist/cli/index.js +76 -17
- package/dist/cli/index.mjs +76 -17
- package/dist/index.d.mts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +63 -9
- package/dist/index.mjs +63 -9
- package/dist/plays/bundle-play-file.mjs +2 -2
- package/package.json +1 -1
|
@@ -8,12 +8,16 @@ import type {
|
|
|
8
8
|
PlayDatasetInput,
|
|
9
9
|
PlayDatasetRow,
|
|
10
10
|
} from '../plays/dataset';
|
|
11
|
-
import type {
|
|
11
|
+
import type {
|
|
12
|
+
PlayQueueHint,
|
|
13
|
+
RateStateBackend,
|
|
14
|
+
} from './governor/rate-state-backend';
|
|
12
15
|
import type { GovernanceSnapshot } from './governor/governor';
|
|
13
16
|
import type { AnyBatchOperationStrategy } from './batching-types';
|
|
14
17
|
import type { ToolResultMetadataInput } from './tool-result';
|
|
15
18
|
import type { PreviousCell } from './cell-staleness';
|
|
16
19
|
import type { MapRowOutcome } from './durability-store';
|
|
20
|
+
import type { WorkReceiptFailureKind } from './work-receipts';
|
|
17
21
|
|
|
18
22
|
export interface RowState {
|
|
19
23
|
results: Map<string, unknown>;
|
|
@@ -24,7 +28,10 @@ export interface ToolCallRequest {
|
|
|
24
28
|
cacheKey: string;
|
|
25
29
|
cacheable?: boolean;
|
|
26
30
|
receiptKey?: string | null;
|
|
31
|
+
executionAuthScopeDigest?: string | null;
|
|
32
|
+
receiptLeaseId?: string | null;
|
|
27
33
|
force?: boolean;
|
|
34
|
+
forceFailedRefresh?: boolean;
|
|
28
35
|
rowId: number;
|
|
29
36
|
fieldName?: string;
|
|
30
37
|
toolId: string;
|
|
@@ -46,7 +53,12 @@ export interface RuntimeStepReceipt {
|
|
|
46
53
|
status: 'pending' | 'running' | 'completed' | 'failed' | 'skipped';
|
|
47
54
|
output?: unknown;
|
|
48
55
|
error?: string;
|
|
56
|
+
failureKind?: WorkReceiptFailureKind | null;
|
|
49
57
|
runId?: string | null;
|
|
58
|
+
leaseId?: string | null;
|
|
59
|
+
leaseOwnerRunId?: string | null;
|
|
60
|
+
leaseOwnerAttempt?: number | null;
|
|
61
|
+
leaseExpiresAt?: string | null;
|
|
50
62
|
claimState?: 'claimed' | 'existing';
|
|
51
63
|
}
|
|
52
64
|
|
|
@@ -57,25 +69,42 @@ export interface GetRuntimeStepReceiptInput {
|
|
|
57
69
|
export interface ClaimRuntimeStepReceiptInput {
|
|
58
70
|
key: string;
|
|
59
71
|
runId: string;
|
|
72
|
+
runAttempt?: number | null;
|
|
73
|
+
leaseAware?: boolean;
|
|
60
74
|
reclaimRunning?: boolean;
|
|
61
75
|
forceRefresh?: boolean;
|
|
76
|
+
forceFailedRefresh?: boolean;
|
|
62
77
|
}
|
|
63
78
|
|
|
64
79
|
export interface CompleteRuntimeStepReceiptInput {
|
|
65
80
|
key: string;
|
|
66
81
|
runId: string;
|
|
82
|
+
runAttempt?: number | null;
|
|
83
|
+
leaseId?: string | null;
|
|
67
84
|
output: unknown | null;
|
|
68
85
|
}
|
|
69
86
|
|
|
87
|
+
export interface ReleaseRuntimeStepReceiptInput {
|
|
88
|
+
key: string;
|
|
89
|
+
runId: string;
|
|
90
|
+
runAttempt?: number | null;
|
|
91
|
+
leaseId?: string | null;
|
|
92
|
+
}
|
|
93
|
+
|
|
70
94
|
export interface FailRuntimeStepReceiptInput {
|
|
71
95
|
key: string;
|
|
72
96
|
runId: string;
|
|
97
|
+
runAttempt?: number | null;
|
|
98
|
+
leaseId?: string | null;
|
|
73
99
|
error: string;
|
|
100
|
+
failureKind?: WorkReceiptFailureKind | null;
|
|
74
101
|
}
|
|
75
102
|
|
|
76
103
|
export interface SkipRuntimeStepReceiptInput {
|
|
77
104
|
key: string;
|
|
78
105
|
runId: string;
|
|
106
|
+
runAttempt?: number | null;
|
|
107
|
+
leaseId?: string | null;
|
|
79
108
|
output?: unknown | null;
|
|
80
109
|
}
|
|
81
110
|
|
|
@@ -86,14 +115,19 @@ export interface GetRuntimeStepReceiptsInput {
|
|
|
86
115
|
export interface ClaimRuntimeStepReceiptsInput {
|
|
87
116
|
keys: string[];
|
|
88
117
|
runId: string;
|
|
118
|
+
runAttempt?: number | null;
|
|
119
|
+
leaseAware?: boolean;
|
|
89
120
|
reclaimRunning?: boolean;
|
|
90
121
|
forceRefresh?: boolean;
|
|
122
|
+
forceFailedRefresh?: boolean;
|
|
91
123
|
}
|
|
92
124
|
|
|
93
125
|
export interface CompleteRuntimeStepReceiptsInput {
|
|
94
126
|
receipts: Array<{
|
|
95
127
|
key: string;
|
|
96
128
|
runId: string;
|
|
129
|
+
runAttempt?: number | null;
|
|
130
|
+
leaseId?: string | null;
|
|
97
131
|
output: unknown | null;
|
|
98
132
|
}>;
|
|
99
133
|
}
|
|
@@ -102,10 +136,20 @@ export interface FailRuntimeStepReceiptsInput {
|
|
|
102
136
|
receipts: Array<{
|
|
103
137
|
key: string;
|
|
104
138
|
runId: string;
|
|
139
|
+
runAttempt?: number | null;
|
|
140
|
+
leaseId?: string | null;
|
|
105
141
|
error: string;
|
|
142
|
+
failureKind?: WorkReceiptFailureKind | null;
|
|
106
143
|
}>;
|
|
107
144
|
}
|
|
108
145
|
|
|
146
|
+
export interface HeartbeatRuntimeStepReceiptsInput {
|
|
147
|
+
keys: string[];
|
|
148
|
+
runId: string;
|
|
149
|
+
runAttempt?: number | null;
|
|
150
|
+
leaseId: string;
|
|
151
|
+
}
|
|
152
|
+
|
|
109
153
|
export interface CsvOptions {
|
|
110
154
|
description?: string;
|
|
111
155
|
columns?: Record<string, string | readonly string[]>;
|
|
@@ -271,6 +315,10 @@ export interface BatchRequest {
|
|
|
271
315
|
export interface MapStartResult {
|
|
272
316
|
/** Rows that need processing for this run. Previous values may be included for context. */
|
|
273
317
|
pendingRows: Record<string, unknown>[];
|
|
318
|
+
/** Rows already terminal for this run and safe to count as completed. */
|
|
319
|
+
completedRows?: Record<string, unknown>[];
|
|
320
|
+
/** Rows leased by another active attempt and not executable by this attempt. */
|
|
321
|
+
blockedRows?: Record<string, unknown>[];
|
|
274
322
|
/** Resolved table namespace. */
|
|
275
323
|
tableNamespace: string;
|
|
276
324
|
}
|
|
@@ -403,6 +451,7 @@ export interface ContextOptions {
|
|
|
403
451
|
graphHash?: string | null;
|
|
404
452
|
artifactHash?: string | null;
|
|
405
453
|
convexUrl?: string;
|
|
454
|
+
runtimeSchedulerSchema?: string | null;
|
|
406
455
|
staticPipeline?: PlayStaticPipeline | null;
|
|
407
456
|
workflowId?: string;
|
|
408
457
|
sessionId?: string;
|
|
@@ -411,9 +460,15 @@ export interface ContextOptions {
|
|
|
411
460
|
checkpoint?: PlayCheckpoint;
|
|
412
461
|
/** Enables durable boundary replay such as ctx.sleep() resumptions. */
|
|
413
462
|
durableBoundaries?: boolean;
|
|
414
|
-
/**
|
|
463
|
+
/**
|
|
464
|
+
* Run-level cache policy.
|
|
465
|
+
* forceToolRefresh bypasses all ctx.tools.execute receipts.
|
|
466
|
+
* forceFailedToolRefresh reclaims only failed receipts, preserving completed
|
|
467
|
+
* provider-call idempotency while allowing forced repair runs to make progress.
|
|
468
|
+
*/
|
|
415
469
|
cachePolicy?: {
|
|
416
470
|
forceToolRefresh?: boolean;
|
|
471
|
+
forceFailedToolRefresh?: boolean;
|
|
417
472
|
};
|
|
418
473
|
/** Called after each durable batch completes — for Temporal heartbeating. */
|
|
419
474
|
onBatchComplete?: (checkpoint: PlayCheckpoint) => void;
|
|
@@ -439,6 +494,7 @@ export interface ContextOptions {
|
|
|
439
494
|
playName?: string;
|
|
440
495
|
playId?: string;
|
|
441
496
|
runId?: string;
|
|
497
|
+
executorToken?: string;
|
|
442
498
|
staticPipeline?: PlayStaticPipeline | null;
|
|
443
499
|
forceRefresh?: boolean;
|
|
444
500
|
},
|
|
@@ -453,6 +509,7 @@ export interface ContextOptions {
|
|
|
453
509
|
playName?: string;
|
|
454
510
|
playId?: string;
|
|
455
511
|
runId?: string;
|
|
512
|
+
executorToken?: string;
|
|
456
513
|
tableNamespace: string;
|
|
457
514
|
rows: MapRowOutcome[];
|
|
458
515
|
outputFields: string[];
|
|
@@ -460,12 +517,25 @@ export interface ContextOptions {
|
|
|
460
517
|
}) => Promise<void>;
|
|
461
518
|
playId?: string;
|
|
462
519
|
runId?: string;
|
|
520
|
+
runAttempt?: number | null;
|
|
521
|
+
/**
|
|
522
|
+
* Optional shared provider-rate state for fleet substrates. Local/test
|
|
523
|
+
* contexts omit this and use the in-process backend.
|
|
524
|
+
*/
|
|
525
|
+
rateState?: RateStateBackend;
|
|
526
|
+
/**
|
|
527
|
+
* Loud guard for production Node substrates: when true, constructing a
|
|
528
|
+
* context without a shared rate-state backend is a configuration error.
|
|
529
|
+
*/
|
|
530
|
+
requireSharedRateState?: boolean;
|
|
463
531
|
resolvePlay?: (playRef: string) => Promise<ResolvedPlayExecution | null>;
|
|
464
532
|
getToolQueueHints?: (toolId: string) => Promise<readonly PlayQueueHint[]>;
|
|
465
533
|
getToolRetryPolicy?: (toolId: string) => Promise<{
|
|
466
534
|
retrySafeTransientHttp?: boolean;
|
|
467
535
|
} | null>;
|
|
468
536
|
getToolActionCacheVersion?: (toolId: string) => Promise<string> | string;
|
|
537
|
+
getToolAuthScopeDigest?: (toolId: string) => Promise<string> | string;
|
|
538
|
+
invalidateToolAuthScopeDigest?: (toolId: string) => void;
|
|
469
539
|
getToolTargetGetters?: (
|
|
470
540
|
toolId: string,
|
|
471
541
|
output: string,
|
|
@@ -502,25 +572,41 @@ export interface ContextOptions {
|
|
|
502
572
|
) => Promise<RuntimeStepReceipt | null> | RuntimeStepReceipt | null;
|
|
503
573
|
getRuntimeStepReceipts?: (
|
|
504
574
|
input: GetRuntimeStepReceiptsInput,
|
|
505
|
-
) =>
|
|
575
|
+
) =>
|
|
576
|
+
| Promise<Array<RuntimeStepReceipt | null>>
|
|
577
|
+
| Array<RuntimeStepReceipt | null>;
|
|
506
578
|
claimRuntimeStepReceipt?: (
|
|
507
579
|
input: ClaimRuntimeStepReceiptInput,
|
|
508
580
|
) => Promise<RuntimeStepReceipt | null> | RuntimeStepReceipt | null;
|
|
509
581
|
claimRuntimeStepReceipts?: (
|
|
510
582
|
input: ClaimRuntimeStepReceiptsInput,
|
|
511
|
-
) =>
|
|
583
|
+
) =>
|
|
584
|
+
| Promise<Array<RuntimeStepReceipt | null>>
|
|
585
|
+
| Array<RuntimeStepReceipt | null>;
|
|
512
586
|
completeRuntimeStepReceipt?: (
|
|
513
587
|
input: CompleteRuntimeStepReceiptInput,
|
|
514
588
|
) => Promise<RuntimeStepReceipt | null> | RuntimeStepReceipt | null;
|
|
589
|
+
releaseRuntimeStepReceipt?: (
|
|
590
|
+
input: ReleaseRuntimeStepReceiptInput,
|
|
591
|
+
) => Promise<RuntimeStepReceipt | null> | RuntimeStepReceipt | null;
|
|
515
592
|
completeRuntimeStepReceipts?: (
|
|
516
593
|
input: CompleteRuntimeStepReceiptsInput,
|
|
517
|
-
) =>
|
|
594
|
+
) =>
|
|
595
|
+
| Promise<Array<RuntimeStepReceipt | null>>
|
|
596
|
+
| Array<RuntimeStepReceipt | null>;
|
|
518
597
|
failRuntimeStepReceipt?: (
|
|
519
598
|
input: FailRuntimeStepReceiptInput,
|
|
520
599
|
) => Promise<RuntimeStepReceipt | null> | RuntimeStepReceipt | null;
|
|
521
600
|
failRuntimeStepReceipts?: (
|
|
522
601
|
input: FailRuntimeStepReceiptsInput,
|
|
523
|
-
) =>
|
|
602
|
+
) =>
|
|
603
|
+
| Promise<Array<RuntimeStepReceipt | null>>
|
|
604
|
+
| Array<RuntimeStepReceipt | null>;
|
|
605
|
+
heartbeatRuntimeStepReceipts?: (
|
|
606
|
+
input: HeartbeatRuntimeStepReceiptsInput,
|
|
607
|
+
) =>
|
|
608
|
+
| Promise<Array<RuntimeStepReceipt | null>>
|
|
609
|
+
| Array<RuntimeStepReceipt | null>;
|
|
524
610
|
skipRuntimeStepReceipt?: (
|
|
525
611
|
input: SkipRuntimeStepReceiptInput,
|
|
526
612
|
) => Promise<RuntimeStepReceipt | null> | RuntimeStepReceipt | null;
|
|
@@ -580,6 +666,15 @@ export interface PlayCheckpoint {
|
|
|
580
666
|
output?: unknown;
|
|
581
667
|
completedAt?: number;
|
|
582
668
|
}
|
|
669
|
+
| {
|
|
670
|
+
kind: 'child_play';
|
|
671
|
+
childRunId: string;
|
|
672
|
+
childPlayName: string;
|
|
673
|
+
status: 'completed' | 'failed' | 'cancelled';
|
|
674
|
+
output?: unknown;
|
|
675
|
+
error?: string;
|
|
676
|
+
completedAt?: number;
|
|
677
|
+
}
|
|
583
678
|
>;
|
|
584
679
|
/** Per-map execution frames keyed by invocation id. */
|
|
585
680
|
mapFrames?: Record<string, MapExecutionFrame>;
|
|
@@ -783,6 +878,10 @@ export interface PlayRowUpdate {
|
|
|
783
878
|
key: string;
|
|
784
879
|
rowId: number;
|
|
785
880
|
tableNamespace?: string | null;
|
|
881
|
+
attemptId?: string | null;
|
|
882
|
+
attemptOwnerRunId?: string | null;
|
|
883
|
+
attemptSeq?: number | null;
|
|
884
|
+
attemptExpiresAt?: string | null;
|
|
786
885
|
status?: 'running' | 'completed' | 'failed';
|
|
787
886
|
stage?: string | null;
|
|
788
887
|
provider?: string | null;
|
|
Binary file
|
|
@@ -81,6 +81,7 @@ const testRateLimitBatchStrategy: BatchOperationStrategy<
|
|
|
81
81
|
batchOperation: 'test_batch_rate_limit',
|
|
82
82
|
kind: 'identifier_batch',
|
|
83
83
|
maxBatchSize: 200,
|
|
84
|
+
bucketKeyPayloadFields: ['stage'],
|
|
84
85
|
canBatchWith(left, right) {
|
|
85
86
|
return String(left.stage || '') === String(right.stage || '');
|
|
86
87
|
},
|
|
@@ -3,6 +3,7 @@ import type {
|
|
|
3
3
|
CompleteRuntimeStepReceiptInput,
|
|
4
4
|
FailRuntimeStepReceiptInput,
|
|
5
5
|
GetRuntimeStepReceiptInput,
|
|
6
|
+
ReleaseRuntimeStepReceiptInput,
|
|
6
7
|
RuntimeStepReceipt,
|
|
7
8
|
SkipRuntimeStepReceiptInput,
|
|
8
9
|
} from './ctx-types';
|
|
@@ -50,6 +51,9 @@ export interface PlayDurabilityStore {
|
|
|
50
51
|
completeRuntimeStepReceipt(
|
|
51
52
|
input: CompleteRuntimeStepReceiptInput,
|
|
52
53
|
): Promise<RuntimeStepReceipt | null>;
|
|
54
|
+
releaseRuntimeStepReceipt(
|
|
55
|
+
input: ReleaseRuntimeStepReceiptInput,
|
|
56
|
+
): Promise<RuntimeStepReceipt | null>;
|
|
53
57
|
failRuntimeStepReceipt(
|
|
54
58
|
input: FailRuntimeStepReceiptInput,
|
|
55
59
|
): Promise<RuntimeStepReceipt | null>;
|
|
@@ -47,37 +47,36 @@ export const durableCallStaleBucket = durableCacheStaleBucket;
|
|
|
47
47
|
|
|
48
48
|
export function buildDurableToolCallCacheKey(input: {
|
|
49
49
|
orgId?: string | null;
|
|
50
|
-
playId: string;
|
|
51
50
|
toolId: string;
|
|
52
51
|
requestInput: Record<string, unknown>;
|
|
53
52
|
authScopeDigest?: string | null;
|
|
54
53
|
providerActionVersion?: string | null;
|
|
55
54
|
cachePolicyVersion?: string | null;
|
|
56
55
|
staleAfterSeconds?: number | null;
|
|
56
|
+
playLocalScope?: string | null;
|
|
57
57
|
}): string {
|
|
58
58
|
const orgId = input.orgId?.trim() || 'org';
|
|
59
|
-
const playId = input.playId.trim();
|
|
60
|
-
if (!playId) {
|
|
61
|
-
throw new Error('Missing durable tool play id.');
|
|
62
|
-
}
|
|
63
59
|
const toolId = input.toolId.trim();
|
|
64
60
|
if (!toolId) {
|
|
65
|
-
throw new Error('
|
|
61
|
+
throw new Error('Durable tool call cache key requires a non-empty toolId.');
|
|
66
62
|
}
|
|
67
|
-
const
|
|
68
|
-
if (!
|
|
69
|
-
throw new Error(
|
|
63
|
+
const providerActionVersion = input.providerActionVersion?.trim();
|
|
64
|
+
if (!providerActionVersion) {
|
|
65
|
+
throw new Error(
|
|
66
|
+
'Durable tool call cache key requires a provider action version.',
|
|
67
|
+
);
|
|
70
68
|
}
|
|
69
|
+
const playLocalScope = input.playLocalScope?.trim() || 'play';
|
|
71
70
|
const digest = sha256Hex(
|
|
72
71
|
stableStringify({
|
|
73
72
|
kind: 'tool' satisfies DurableCallKind,
|
|
74
73
|
orgId,
|
|
75
|
-
|
|
74
|
+
playLocalScope,
|
|
76
75
|
toolId,
|
|
77
76
|
normalizedToolId: normalizeTableNamespace(toolId),
|
|
78
77
|
requestInput: input.requestInput,
|
|
79
78
|
authScopeDigest: input.authScopeDigest ?? null,
|
|
80
|
-
providerActionVersion
|
|
79
|
+
providerActionVersion,
|
|
81
80
|
cachePolicyVersion:
|
|
82
81
|
input.cachePolicyVersion ?? DURABLE_CALL_CACHE_POLICY_VERSION,
|
|
83
82
|
staleBucket: durableCacheStaleBucket({
|
|
@@ -101,9 +100,7 @@ export function buildDurableCtxCallCacheKey(input: {
|
|
|
101
100
|
const playId = input.playId?.trim() || 'play';
|
|
102
101
|
const id = input.id.trim();
|
|
103
102
|
if (!id) {
|
|
104
|
-
throw new Error(
|
|
105
|
-
`Durable ${input.kind} call cache key requires a non-empty id.`,
|
|
106
|
-
);
|
|
103
|
+
throw new Error(`Durable ${input.kind} key needs id.`);
|
|
107
104
|
}
|
|
108
105
|
const normalizedId = normalizeTableNamespace(id);
|
|
109
106
|
const digest = sha256Hex(
|
|
@@ -124,16 +121,119 @@ export function buildDurableCtxCallCacheKey(input: {
|
|
|
124
121
|
return `ctx:${orgId}:call:${input.kind}:${normalizedId}:${digest}`;
|
|
125
122
|
}
|
|
126
123
|
|
|
124
|
+
export function buildDurableRunPlaySemanticKey(input: {
|
|
125
|
+
childPlayName: string;
|
|
126
|
+
input: Record<string, unknown>;
|
|
127
|
+
childRevisionFingerprint?: string | null;
|
|
128
|
+
rowScope?: Record<string, unknown> | null;
|
|
129
|
+
}): string {
|
|
130
|
+
return sha256Hex(
|
|
131
|
+
stableStringify({
|
|
132
|
+
childPlayName: input.childPlayName.trim(),
|
|
133
|
+
childRevisionFingerprint: input.childRevisionFingerprint ?? null,
|
|
134
|
+
input: input.input,
|
|
135
|
+
rowScope: input.rowScope ?? null,
|
|
136
|
+
}),
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
|
|
127
140
|
export function buildDurableToolCallAuthScopeDigest(input: {
|
|
128
141
|
orgId?: string | null;
|
|
129
|
-
userEmail?: string | null;
|
|
130
142
|
toolId: string;
|
|
143
|
+
executionAuthScopeDigest?: string | null;
|
|
131
144
|
}): string {
|
|
132
145
|
return sha256Hex(
|
|
133
146
|
stableStringify({
|
|
134
147
|
orgId: input.orgId?.trim() || 'org',
|
|
135
|
-
actor: input.userEmail?.trim().toLowerCase() || 'workspace',
|
|
136
148
|
toolId: input.toolId.trim(),
|
|
149
|
+
executionAuthScopeDigest: input.executionAuthScopeDigest?.trim() || null,
|
|
137
150
|
}),
|
|
138
151
|
);
|
|
139
152
|
}
|
|
153
|
+
|
|
154
|
+
export function buildDurableToolReceiptPrefix(input: {
|
|
155
|
+
orgId?: string | null;
|
|
156
|
+
toolId: string;
|
|
157
|
+
}): string {
|
|
158
|
+
const orgId = input.orgId?.trim() || 'org';
|
|
159
|
+
const toolId = input.toolId.trim();
|
|
160
|
+
if (!toolId) {
|
|
161
|
+
throw new Error('Durable tool receipt prefix requires a non-empty toolId.');
|
|
162
|
+
}
|
|
163
|
+
return `ctx:${orgId}:call:tool:${normalizeTableNamespace(toolId)}:`;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export function buildDurableToolProviderIdempotencyKey(input: {
|
|
167
|
+
receiptKey: string;
|
|
168
|
+
force?: boolean;
|
|
169
|
+
receiptLeaseId?: string | null;
|
|
170
|
+
fallbackAttemptId?: string | null;
|
|
171
|
+
}): string {
|
|
172
|
+
const receiptKey = input.receiptKey.trim();
|
|
173
|
+
if (!receiptKey) {
|
|
174
|
+
throw new Error('Need receipt key.');
|
|
175
|
+
}
|
|
176
|
+
if (input.force !== true) {
|
|
177
|
+
return receiptKey;
|
|
178
|
+
}
|
|
179
|
+
const attemptId =
|
|
180
|
+
input.receiptLeaseId?.trim() || input.fallbackAttemptId?.trim() || null;
|
|
181
|
+
if (!attemptId) {
|
|
182
|
+
throw new Error('Forced idempotency needs lease id.');
|
|
183
|
+
}
|
|
184
|
+
return `${receiptKey}:force:${attemptId}`;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
export function buildDurableToolAggregateReceiptKey(input: {
|
|
188
|
+
receiptKeys: string[];
|
|
189
|
+
prefix?: 'batch' | null;
|
|
190
|
+
aggregateReceiptPrefix?: string | null;
|
|
191
|
+
}): string {
|
|
192
|
+
const receiptKeys = input.receiptKeys.map((key) => key.trim()).sort();
|
|
193
|
+
const digest = sha256Hex(stableStringify(receiptKeys));
|
|
194
|
+
if (input.prefix !== 'batch') {
|
|
195
|
+
return digest;
|
|
196
|
+
}
|
|
197
|
+
const scopedPrefix =
|
|
198
|
+
input.aggregateReceiptPrefix?.trim() ||
|
|
199
|
+
commonDurableToolReceiptPrefix(receiptKeys);
|
|
200
|
+
if (!scopedPrefix) {
|
|
201
|
+
throw new Error('Batch receipt key needs same-tool members.');
|
|
202
|
+
}
|
|
203
|
+
return `${scopedPrefix}batch:${digest}`;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
function commonDurableToolReceiptPrefix(
|
|
207
|
+
receiptKeys: readonly string[],
|
|
208
|
+
): string {
|
|
209
|
+
let commonPrefix: string | null = null;
|
|
210
|
+
for (const receiptKey of receiptKeys) {
|
|
211
|
+
const match = /^(ctx:[^:]+:call:tool:[^:]+:)/.exec(receiptKey);
|
|
212
|
+
if (!match) {
|
|
213
|
+
return '';
|
|
214
|
+
}
|
|
215
|
+
const prefix = match[1] ?? '';
|
|
216
|
+
if (!commonPrefix) {
|
|
217
|
+
commonPrefix = prefix;
|
|
218
|
+
continue;
|
|
219
|
+
}
|
|
220
|
+
if (commonPrefix !== prefix) {
|
|
221
|
+
return '';
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
return commonPrefix ?? '';
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
export function buildDurableToolAggregateProviderIdempotencyKey(input: {
|
|
228
|
+
aggregateReceiptKey: string;
|
|
229
|
+
receiptKeys: string[];
|
|
230
|
+
providerIdempotencyKeys: string[];
|
|
231
|
+
}): string {
|
|
232
|
+
const receiptKeys = input.receiptKeys.map((key) => key.trim());
|
|
233
|
+
const providerIdempotencyKeys = input.providerIdempotencyKeys.map((key) =>
|
|
234
|
+
key.trim(),
|
|
235
|
+
);
|
|
236
|
+
return `${input.aggregateReceiptKey}:ordered:${sha256Hex(
|
|
237
|
+
stableStringify({ receiptKeys, providerIdempotencyKeys }),
|
|
238
|
+
)}`;
|
|
239
|
+
}
|