deepline 0.1.181 → 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 +1932 -1838
- 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/output-datasets.ts +124 -12
- 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 +48 -5
- package/dist/bundling-sources/sdk/src/http.ts +23 -8
- package/dist/bundling-sources/sdk/src/play.ts +200 -26
- 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 +1857 -314
- package/dist/bundling-sources/shared_libs/play-runtime/ctx-types.ts +106 -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/query-result-dataset.ts +120 -0
- 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/tool-result.ts +139 -17
- 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 +85 -23
- package/dist/cli/index.mjs +85 -23
- package/dist/index.d.mts +4 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +274 -35
- package/dist/index.mjs +274 -35
- 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>;
|
|
@@ -22,8 +26,12 @@ export interface RowState {
|
|
|
22
26
|
export interface ToolCallRequest {
|
|
23
27
|
callId: string;
|
|
24
28
|
cacheKey: string;
|
|
29
|
+
cacheable?: boolean;
|
|
25
30
|
receiptKey?: string | null;
|
|
31
|
+
executionAuthScopeDigest?: string | null;
|
|
32
|
+
receiptLeaseId?: string | null;
|
|
26
33
|
force?: boolean;
|
|
34
|
+
forceFailedRefresh?: boolean;
|
|
27
35
|
rowId: number;
|
|
28
36
|
fieldName?: string;
|
|
29
37
|
toolId: string;
|
|
@@ -45,7 +53,12 @@ export interface RuntimeStepReceipt {
|
|
|
45
53
|
status: 'pending' | 'running' | 'completed' | 'failed' | 'skipped';
|
|
46
54
|
output?: unknown;
|
|
47
55
|
error?: string;
|
|
56
|
+
failureKind?: WorkReceiptFailureKind | null;
|
|
48
57
|
runId?: string | null;
|
|
58
|
+
leaseId?: string | null;
|
|
59
|
+
leaseOwnerRunId?: string | null;
|
|
60
|
+
leaseOwnerAttempt?: number | null;
|
|
61
|
+
leaseExpiresAt?: string | null;
|
|
49
62
|
claimState?: 'claimed' | 'existing';
|
|
50
63
|
}
|
|
51
64
|
|
|
@@ -56,25 +69,42 @@ export interface GetRuntimeStepReceiptInput {
|
|
|
56
69
|
export interface ClaimRuntimeStepReceiptInput {
|
|
57
70
|
key: string;
|
|
58
71
|
runId: string;
|
|
72
|
+
runAttempt?: number | null;
|
|
73
|
+
leaseAware?: boolean;
|
|
59
74
|
reclaimRunning?: boolean;
|
|
60
75
|
forceRefresh?: boolean;
|
|
76
|
+
forceFailedRefresh?: boolean;
|
|
61
77
|
}
|
|
62
78
|
|
|
63
79
|
export interface CompleteRuntimeStepReceiptInput {
|
|
64
80
|
key: string;
|
|
65
81
|
runId: string;
|
|
82
|
+
runAttempt?: number | null;
|
|
83
|
+
leaseId?: string | null;
|
|
66
84
|
output: unknown | null;
|
|
67
85
|
}
|
|
68
86
|
|
|
87
|
+
export interface ReleaseRuntimeStepReceiptInput {
|
|
88
|
+
key: string;
|
|
89
|
+
runId: string;
|
|
90
|
+
runAttempt?: number | null;
|
|
91
|
+
leaseId?: string | null;
|
|
92
|
+
}
|
|
93
|
+
|
|
69
94
|
export interface FailRuntimeStepReceiptInput {
|
|
70
95
|
key: string;
|
|
71
96
|
runId: string;
|
|
97
|
+
runAttempt?: number | null;
|
|
98
|
+
leaseId?: string | null;
|
|
72
99
|
error: string;
|
|
100
|
+
failureKind?: WorkReceiptFailureKind | null;
|
|
73
101
|
}
|
|
74
102
|
|
|
75
103
|
export interface SkipRuntimeStepReceiptInput {
|
|
76
104
|
key: string;
|
|
77
105
|
runId: string;
|
|
106
|
+
runAttempt?: number | null;
|
|
107
|
+
leaseId?: string | null;
|
|
78
108
|
output?: unknown | null;
|
|
79
109
|
}
|
|
80
110
|
|
|
@@ -85,14 +115,19 @@ export interface GetRuntimeStepReceiptsInput {
|
|
|
85
115
|
export interface ClaimRuntimeStepReceiptsInput {
|
|
86
116
|
keys: string[];
|
|
87
117
|
runId: string;
|
|
118
|
+
runAttempt?: number | null;
|
|
119
|
+
leaseAware?: boolean;
|
|
88
120
|
reclaimRunning?: boolean;
|
|
89
121
|
forceRefresh?: boolean;
|
|
122
|
+
forceFailedRefresh?: boolean;
|
|
90
123
|
}
|
|
91
124
|
|
|
92
125
|
export interface CompleteRuntimeStepReceiptsInput {
|
|
93
126
|
receipts: Array<{
|
|
94
127
|
key: string;
|
|
95
128
|
runId: string;
|
|
129
|
+
runAttempt?: number | null;
|
|
130
|
+
leaseId?: string | null;
|
|
96
131
|
output: unknown | null;
|
|
97
132
|
}>;
|
|
98
133
|
}
|
|
@@ -101,10 +136,20 @@ export interface FailRuntimeStepReceiptsInput {
|
|
|
101
136
|
receipts: Array<{
|
|
102
137
|
key: string;
|
|
103
138
|
runId: string;
|
|
139
|
+
runAttempt?: number | null;
|
|
140
|
+
leaseId?: string | null;
|
|
104
141
|
error: string;
|
|
142
|
+
failureKind?: WorkReceiptFailureKind | null;
|
|
105
143
|
}>;
|
|
106
144
|
}
|
|
107
145
|
|
|
146
|
+
export interface HeartbeatRuntimeStepReceiptsInput {
|
|
147
|
+
keys: string[];
|
|
148
|
+
runId: string;
|
|
149
|
+
runAttempt?: number | null;
|
|
150
|
+
leaseId: string;
|
|
151
|
+
}
|
|
152
|
+
|
|
108
153
|
export interface CsvOptions {
|
|
109
154
|
description?: string;
|
|
110
155
|
columns?: Record<string, string | readonly string[]>;
|
|
@@ -270,6 +315,10 @@ export interface BatchRequest {
|
|
|
270
315
|
export interface MapStartResult {
|
|
271
316
|
/** Rows that need processing for this run. Previous values may be included for context. */
|
|
272
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>[];
|
|
273
322
|
/** Resolved table namespace. */
|
|
274
323
|
tableNamespace: string;
|
|
275
324
|
}
|
|
@@ -402,6 +451,7 @@ export interface ContextOptions {
|
|
|
402
451
|
graphHash?: string | null;
|
|
403
452
|
artifactHash?: string | null;
|
|
404
453
|
convexUrl?: string;
|
|
454
|
+
runtimeSchedulerSchema?: string | null;
|
|
405
455
|
staticPipeline?: PlayStaticPipeline | null;
|
|
406
456
|
workflowId?: string;
|
|
407
457
|
sessionId?: string;
|
|
@@ -410,9 +460,15 @@ export interface ContextOptions {
|
|
|
410
460
|
checkpoint?: PlayCheckpoint;
|
|
411
461
|
/** Enables durable boundary replay such as ctx.sleep() resumptions. */
|
|
412
462
|
durableBoundaries?: boolean;
|
|
413
|
-
/**
|
|
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
|
+
*/
|
|
414
469
|
cachePolicy?: {
|
|
415
470
|
forceToolRefresh?: boolean;
|
|
471
|
+
forceFailedToolRefresh?: boolean;
|
|
416
472
|
};
|
|
417
473
|
/** Called after each durable batch completes — for Temporal heartbeating. */
|
|
418
474
|
onBatchComplete?: (checkpoint: PlayCheckpoint) => void;
|
|
@@ -438,6 +494,7 @@ export interface ContextOptions {
|
|
|
438
494
|
playName?: string;
|
|
439
495
|
playId?: string;
|
|
440
496
|
runId?: string;
|
|
497
|
+
executorToken?: string;
|
|
441
498
|
staticPipeline?: PlayStaticPipeline | null;
|
|
442
499
|
forceRefresh?: boolean;
|
|
443
500
|
},
|
|
@@ -452,6 +509,7 @@ export interface ContextOptions {
|
|
|
452
509
|
playName?: string;
|
|
453
510
|
playId?: string;
|
|
454
511
|
runId?: string;
|
|
512
|
+
executorToken?: string;
|
|
455
513
|
tableNamespace: string;
|
|
456
514
|
rows: MapRowOutcome[];
|
|
457
515
|
outputFields: string[];
|
|
@@ -459,12 +517,25 @@ export interface ContextOptions {
|
|
|
459
517
|
}) => Promise<void>;
|
|
460
518
|
playId?: string;
|
|
461
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;
|
|
462
531
|
resolvePlay?: (playRef: string) => Promise<ResolvedPlayExecution | null>;
|
|
463
532
|
getToolQueueHints?: (toolId: string) => Promise<readonly PlayQueueHint[]>;
|
|
464
533
|
getToolRetryPolicy?: (toolId: string) => Promise<{
|
|
465
534
|
retrySafeTransientHttp?: boolean;
|
|
466
535
|
} | null>;
|
|
467
536
|
getToolActionCacheVersion?: (toolId: string) => Promise<string> | string;
|
|
537
|
+
getToolAuthScopeDigest?: (toolId: string) => Promise<string> | string;
|
|
538
|
+
invalidateToolAuthScopeDigest?: (toolId: string) => void;
|
|
468
539
|
getToolTargetGetters?: (
|
|
469
540
|
toolId: string,
|
|
470
541
|
output: string,
|
|
@@ -501,25 +572,41 @@ export interface ContextOptions {
|
|
|
501
572
|
) => Promise<RuntimeStepReceipt | null> | RuntimeStepReceipt | null;
|
|
502
573
|
getRuntimeStepReceipts?: (
|
|
503
574
|
input: GetRuntimeStepReceiptsInput,
|
|
504
|
-
) =>
|
|
575
|
+
) =>
|
|
576
|
+
| Promise<Array<RuntimeStepReceipt | null>>
|
|
577
|
+
| Array<RuntimeStepReceipt | null>;
|
|
505
578
|
claimRuntimeStepReceipt?: (
|
|
506
579
|
input: ClaimRuntimeStepReceiptInput,
|
|
507
580
|
) => Promise<RuntimeStepReceipt | null> | RuntimeStepReceipt | null;
|
|
508
581
|
claimRuntimeStepReceipts?: (
|
|
509
582
|
input: ClaimRuntimeStepReceiptsInput,
|
|
510
|
-
) =>
|
|
583
|
+
) =>
|
|
584
|
+
| Promise<Array<RuntimeStepReceipt | null>>
|
|
585
|
+
| Array<RuntimeStepReceipt | null>;
|
|
511
586
|
completeRuntimeStepReceipt?: (
|
|
512
587
|
input: CompleteRuntimeStepReceiptInput,
|
|
513
588
|
) => Promise<RuntimeStepReceipt | null> | RuntimeStepReceipt | null;
|
|
589
|
+
releaseRuntimeStepReceipt?: (
|
|
590
|
+
input: ReleaseRuntimeStepReceiptInput,
|
|
591
|
+
) => Promise<RuntimeStepReceipt | null> | RuntimeStepReceipt | null;
|
|
514
592
|
completeRuntimeStepReceipts?: (
|
|
515
593
|
input: CompleteRuntimeStepReceiptsInput,
|
|
516
|
-
) =>
|
|
594
|
+
) =>
|
|
595
|
+
| Promise<Array<RuntimeStepReceipt | null>>
|
|
596
|
+
| Array<RuntimeStepReceipt | null>;
|
|
517
597
|
failRuntimeStepReceipt?: (
|
|
518
598
|
input: FailRuntimeStepReceiptInput,
|
|
519
599
|
) => Promise<RuntimeStepReceipt | null> | RuntimeStepReceipt | null;
|
|
520
600
|
failRuntimeStepReceipts?: (
|
|
521
601
|
input: FailRuntimeStepReceiptsInput,
|
|
522
|
-
) =>
|
|
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>;
|
|
523
610
|
skipRuntimeStepReceipt?: (
|
|
524
611
|
input: SkipRuntimeStepReceiptInput,
|
|
525
612
|
) => Promise<RuntimeStepReceipt | null> | RuntimeStepReceipt | null;
|
|
@@ -579,6 +666,15 @@ export interface PlayCheckpoint {
|
|
|
579
666
|
output?: unknown;
|
|
580
667
|
completedAt?: number;
|
|
581
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
|
+
}
|
|
582
678
|
>;
|
|
583
679
|
/** Per-map execution frames keyed by invocation id. */
|
|
584
680
|
mapFrames?: Record<string, MapExecutionFrame>;
|
|
@@ -782,6 +878,10 @@ export interface PlayRowUpdate {
|
|
|
782
878
|
key: string;
|
|
783
879
|
rowId: number;
|
|
784
880
|
tableNamespace?: string | null;
|
|
881
|
+
attemptId?: string | null;
|
|
882
|
+
attemptOwnerRunId?: string | null;
|
|
883
|
+
attemptSeq?: number | null;
|
|
884
|
+
attemptExpiresAt?: string | null;
|
|
785
885
|
status?: 'running' | 'completed' | 'failed';
|
|
786
886
|
stage?: string | null;
|
|
787
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
|
+
}
|