deepline 0.3.409 → 0.3.410
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/agent-runtime.ts +18 -1
- package/dist/bundling-sources/sdk/src/client.ts +206 -333
- package/dist/bundling-sources/sdk/src/compat.ts +45 -2
- package/dist/bundling-sources/sdk/src/db/query.ts +9 -10
- package/dist/bundling-sources/sdk/src/http.ts +38 -20
- package/dist/bundling-sources/sdk/src/index.ts +4 -5
- package/dist/bundling-sources/sdk/src/play.ts +10 -10
- package/dist/bundling-sources/sdk/src/plays/bundle-play-file.ts +6 -4
- package/dist/bundling-sources/sdk/src/plays/check-local-play-graph.ts +114 -0
- package/dist/bundling-sources/sdk/src/plays/client.ts +431 -0
- package/dist/bundling-sources/sdk/src/plays/local-play-execution.ts +2 -2
- package/dist/bundling-sources/sdk/src/plays/run-request.ts +106 -16
- package/dist/bundling-sources/sdk/src/release.ts +13 -7
- package/dist/bundling-sources/sdk/src/runs/read-errors.ts +8 -0
- package/dist/bundling-sources/sdk/src/runs/watch-polling.ts +124 -13
- package/dist/bundling-sources/sdk/src/tool-calls.ts +108 -19
- package/dist/bundling-sources/sdk/src/types.ts +18 -0
- package/dist/bundling-sources/shared_libs/integration-contracts/execute-retry-contract.ts +37 -0
- package/dist/bundling-sources/shared_libs/integration-contracts/package.json +3 -0
- package/dist/bundling-sources/shared_libs/play-data-plane/r2.ts +3 -1
- package/dist/bundling-sources/shared_libs/play-runtime/context.ts +277 -76
- package/dist/bundling-sources/shared_libs/play-runtime/ctx-types.ts +6 -0
- package/dist/bundling-sources/shared_libs/play-runtime/dataset-row-input.ts +124 -0
- package/dist/bundling-sources/shared_libs/play-runtime/durable-call-cache.ts +6 -62
- package/dist/bundling-sources/shared_libs/play-runtime/durable-receipt-execution.ts +1 -0
- package/dist/bundling-sources/shared_libs/play-runtime/durable-tool-identity.ts +67 -0
- package/dist/bundling-sources/shared_libs/play-runtime/execute-server-timing.ts +64 -6
- package/dist/bundling-sources/shared_libs/play-runtime/freshness-receipt-execution.ts +1 -5
- package/dist/bundling-sources/shared_libs/play-runtime/ledger-safe-payload.ts +1 -1
- package/dist/bundling-sources/shared_libs/play-runtime/play-artifact-runtime-contract.ts +3 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-http-request.ts +10 -0
- package/dist/bundling-sources/shared_libs/play-runtime/query-result-dataset.ts +3 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-app/egress-probe.ts +3 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-app/index.ts +26 -16
- package/dist/bundling-sources/shared_libs/play-runtime/runner-app/runtime-heartbeat.ts +36 -11
- package/dist/bundling-sources/shared_libs/play-runtime/runner-app/runtime-terminal-push.ts +35 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-launch-transport.ts +21 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-payload-transport.ts +21 -6
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-session-execution.ts +11 -2
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona.ts +85 -20
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-api.ts +71 -13
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-execution-queries.ts +100 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-pool.ts +9 -5
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-runtime-worker.ts +337 -146
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-shared.ts +26 -12
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-rate-state.ts +3 -1
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres.ts +425 -102
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/run-ledger-dispatch-authority.ts +4 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/run-ledger-outbox-recovery.ts +4 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-event-search.ts +9 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-sandbox-capacity.ts +181 -124
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-worker-wake.ts +152 -0
- package/dist/bundling-sources/shared_libs/play-runtime/test-runtime-seams.ts +5 -3
- package/dist/bundling-sources/shared_libs/play-runtime/tool-cache-policy.ts +31 -0
- package/dist/bundling-sources/shared_libs/play-runtime/transient-service-error.ts +10 -0
- package/dist/bundling-sources/shared_libs/plays/ambiguous-write-error.ts +25 -0
- package/dist/bundling-sources/shared_libs/plays/artifact-types.ts +4 -0
- package/dist/bundling-sources/shared_libs/plays/authoring-contract.ts +63 -68
- package/dist/bundling-sources/shared_libs/plays/bundling/index.ts +129 -63
- package/dist/bundling-sources/shared_libs/plays/contracts.ts +14 -0
- package/dist/bundling-sources/shared_libs/plays/enrich-play-compiler.ts +58 -16
- package/dist/bundling-sources/shared_libs/plays/fetch-http-error.ts +50 -0
- package/dist/bundling-sources/shared_libs/plays/source-authoring-edition.ts +351 -0
- package/dist/bundling-sources/shared_libs/plays/tool-list-getter-mode.ts +9 -0
- package/dist/bundling-sources/shared_libs/plays/tool-result-types.ts +1 -1
- package/dist/cli/{auth-5HIIACF7.mjs → auth-LLXLIILR.mjs} +6 -6
- package/dist/cli/auth-UG4WOYGL.js +40 -0
- package/dist/cli/{billing-EVZ3ZWKC.mjs → billing-5FVXZYAC.mjs} +8 -8
- package/dist/cli/{billing-4275N7FL.js → billing-NFPK7GYP.js} +84 -84
- package/dist/cli/{chunk-ZAAKSJAS.js → chunk-27GJKC5Q.js} +17 -10
- package/dist/cli/{chunk-UHNDVD3P.js → chunk-2H4EY7KH.js} +100 -41
- package/dist/cli/{chunk-TQNHMWUR.mjs → chunk-2YR7BIIC.mjs} +5 -2
- package/dist/cli/{chunk-AU4OFDFX.js → chunk-36AHOWVS.js} +26 -26
- package/dist/cli/{chunk-OSDXE27V.mjs → chunk-4PG4ARL2.mjs} +17 -10
- package/dist/cli/{chunk-PBZYY7VZ.mjs → chunk-4XQLVUC7.mjs} +734 -511
- package/dist/cli/chunk-5TUGWDEB.js +313 -0
- package/dist/cli/{chunk-DEC3JECC.js → chunk-5UUQAGJS.js} +5 -2
- package/dist/cli/{chunk-JRAVVJ3T.mjs → chunk-5V5Y37BC.mjs} +2 -2
- package/dist/cli/{chunk-PMVFAYL7.mjs → chunk-63ILLN5H.mjs} +2 -2
- package/dist/cli/{chunk-V76R6HMV.js → chunk-63S7X326.js} +1029 -806
- package/dist/cli/{chunk-VWBTTJYQ.mjs → chunk-6PGATQ6L.mjs} +6 -3
- package/dist/cli/{chunk-6BJK4EJ3.mjs → chunk-AARWVK4C.mjs} +2132 -65
- package/dist/cli/{chunk-FERRDNMO.js → chunk-AD47BXN2.js} +5 -5
- package/dist/cli/{chunk-GAICVLKL.js → chunk-D37FEBES.js} +2 -2
- package/dist/cli/{chunk-S6R3OX7B.js → chunk-E4CABWXL.js} +25 -2
- package/dist/cli/{chunk-NXGCO4JB.mjs → chunk-E4IXDAZI.mjs} +5 -0
- package/dist/cli/chunk-EQ4Z7RJW.mjs +35 -0
- package/dist/cli/chunk-FR2ILQ4G.mjs +8 -0
- package/dist/cli/{chunk-FJCIUF34.js → chunk-FVLNYDI4.js} +128 -376
- package/dist/cli/{chunk-O3VSXP2F.js → chunk-FZJAM576.js} +50 -50
- package/dist/cli/{chunk-BZAMOCPA.mjs → chunk-IMZ56EOH.mjs} +3 -3
- package/dist/cli/{chunk-N44JHMKY.mjs → chunk-IPG42SD2.mjs} +452 -138
- package/dist/cli/chunk-J33TSWO5.js +8 -0
- package/dist/cli/{chunk-BEVLCKXG.mjs → chunk-JNXJZ577.mjs} +1 -1
- package/dist/cli/{chunk-JI2B4RZP.mjs → chunk-KCC3FKIW.mjs} +71 -12
- package/dist/cli/{chunk-6IKARAYD.mjs → chunk-L2VKAASU.mjs} +23 -0
- package/dist/cli/{chunk-WLOCMJWV.js → chunk-LTFL4JRN.js} +426 -721
- package/dist/cli/{chunk-YHPYUZZX.mjs → chunk-MAMVGOSC.mjs} +1 -1
- package/dist/cli/{chunk-NZSF57UO.mjs → chunk-MN2OWLFA.mjs} +2 -2
- package/dist/cli/{chunk-YD7B53RW.js → chunk-NF4V5DTY.js} +12 -12
- package/dist/cli/{chunk-Q2E4E4FJ.js → chunk-NPBJI7RE.js} +8 -8
- package/dist/cli/chunk-NTVLGHFM.js +501 -0
- package/dist/cli/{chunk-HQXL5526.mjs → chunk-NUX2QHNC.mjs} +1 -1
- package/dist/cli/{chunk-JGHG4NBA.js → chunk-OBB4QXHA.js} +19 -4
- package/dist/cli/{chunk-SEFMGO3Z.js → chunk-OQQOXSYA.js} +2184 -117
- package/dist/cli/chunk-OZ6E3IRZ.js +6084 -0
- package/dist/cli/{chunk-7P5AA3SN.js → chunk-PPDBRJRW.js} +6 -1
- package/dist/cli/{chunk-FHPCKULR.mjs → chunk-PZSLPBDA.mjs} +2 -2
- package/dist/cli/{chunk-ILHRA7AD.js → chunk-QADCFSGH.js} +7 -7
- package/dist/cli/{chunk-RTCDW2GU.js → chunk-QJI5FIOW.js} +170 -49
- package/dist/cli/{chunk-WYQO2CBS.mjs → chunk-QL22Y56M.mjs} +149 -28
- package/dist/cli/{chunk-2PRO2JTX.mjs → chunk-RFB25DSQ.mjs} +36 -284
- package/dist/cli/chunk-T44IIOT6.mjs +501 -0
- package/dist/cli/chunk-VK2LZ5IP.js +35 -0
- package/dist/cli/chunk-VKKVSFRD.js +62 -0
- package/dist/cli/{chunk-2GI3QD3L.js → chunk-VYKV5XHL.js} +644 -330
- package/dist/cli/{chunk-GSK6NHVM.js → chunk-WU4U6VSB.js} +5 -5
- package/dist/cli/chunk-XHLKJOTN.mjs +313 -0
- package/dist/cli/{chunk-IT3XBJQR.mjs → chunk-XIHWSXSV.mjs} +330 -625
- package/dist/cli/chunk-XNZJKRJA.mjs +6084 -0
- package/dist/cli/chunk-ZCALLYF6.mjs +62 -0
- package/dist/cli/{chunk-WHG43Z67.js → chunk-ZFZ427HN.js} +11 -8
- package/dist/cli/{chunk-J6DCKJNM.mjs → chunk-ZKYEW55U.mjs} +16 -1
- package/dist/cli/{csv-BBOTCGQY.js → csv-7U3FJYKZ.js} +14 -14
- package/dist/cli/{csv-A2MP6EFV.mjs → csv-ZWLDMM4A.mjs} +5 -5
- package/dist/cli/{db-G4CODDCA.js → db-DNCGV5PC.js} +42 -47
- package/dist/cli/{db-3W5DMTUX.mjs → db-IMYXVMGI.mjs} +15 -20
- package/dist/cli/{describe-XYJ2ZT4M.mjs → describe-Q23DWJUK.mjs} +20 -15
- package/dist/cli/{describe-PQTQ5B6F.js → describe-S34JUX5W.js} +27 -22
- package/dist/cli/describe-core.d.mts +2 -2
- package/dist/cli/describe-core.d.ts +2 -2
- package/dist/cli/describe-core.js +6 -6
- package/dist/cli/describe-core.mjs +5 -5
- package/dist/cli/{executions-UR67CA5H.mjs → executions-A73EUGSI.mjs} +8 -8
- package/dist/cli/{executions-TLANVR7Y.js → executions-XOMPX2YJ.js} +10 -10
- package/dist/cli/{feedback-WHCMGEIL.mjs → feedback-N4GJ2POI.mjs} +11 -7
- package/dist/cli/{feedback-6C2YTRJL.js → feedback-QTCHNJJH.js} +13 -9
- package/dist/cli/{git-GWLB6VSA.mjs → git-4Q3JIQYZ.mjs} +6 -6
- package/dist/cli/git-I6CPBEVG.js +24 -0
- package/dist/cli/index.js +236 -348
- package/dist/cli/index.mjs +162 -274
- package/dist/cli/{legacy-noops-KF4XIFEF.mjs → legacy-noops-3SOVGFF7.mjs} +6 -6
- package/dist/cli/{legacy-noops-ZUFA7RWI.js → legacy-noops-4OSHZM34.js} +9 -9
- package/dist/cli/{monitors-TB3K2IVE.js → monitors-LVE2KZNG.js} +94 -94
- package/dist/cli/{monitors-6UOIDIMB.mjs → monitors-QP2XID2B.mjs} +8 -8
- package/dist/cli/{org-WGHHMVDZ.mjs → org-IVRETVQA.mjs} +8 -8
- package/dist/cli/{org-CKWMBPIR.js → org-XFLK5IAP.js} +68 -68
- package/dist/cli/{play-LYPAXCLD.mjs → play-DE7VH6NU.mjs} +533 -98
- package/dist/cli/{play-N2B3KAVS.js → play-XXTPPP23.js} +1067 -632
- package/dist/cli/{providers-UR42MD6Z.js → providers-DLD3I4JF.js} +11 -11
- package/dist/cli/{providers-6DI5BVZJ.mjs → providers-GX2NIZQQ.mjs} +8 -8
- package/dist/cli/{quickstart-MNA2S6PO.mjs → quickstart-72B4L4PK.mjs} +5 -5
- package/dist/cli/{quickstart-FCJG4XGB.js → quickstart-XNS3HSWC.js} +7 -7
- package/dist/cli/search-6NCH4HB5.js +30 -0
- package/dist/cli/{search-VPPYUJ2M.mjs → search-SUTRANJI.mjs} +9 -9
- package/dist/cli/{secrets-QOSMVO36.js → secrets-6OBLOVEV.js} +17 -17
- package/dist/cli/{secrets-DRI4W7Z5.mjs → secrets-FPFXXNUH.mjs} +8 -8
- package/dist/cli/sessions-235532DR.js +16 -0
- package/dist/cli/{sessions-DQNUKP43.mjs → sessions-R25I4QKN.mjs} +6 -6
- package/dist/cli/{settings-DWDK3Y2R.mjs → settings-AOP6F5PZ.mjs} +12 -12
- package/dist/cli/{settings-JUGGCOPS.js → settings-VL5FOFPN.js} +79 -79
- package/dist/cli/{setup-AWBHNYXK.js → setup-BSC67YT3.js} +45 -44
- package/dist/cli/{setup-D5DWVNY4.mjs → setup-ZMPHBHVJ.mjs} +11 -10
- package/dist/cli/skills-3IWLYYRL.js +29 -0
- package/dist/cli/{skills-YV2XR35J.mjs → skills-KF65TVFO.mjs} +7 -7
- package/dist/cli/tools-LR66SPYU.js +44 -0
- package/dist/cli/{tools-VFJYHNV2.mjs → tools-SX4XIPM7.mjs} +19 -14
- package/dist/cli/{update-IM6VOTGL.mjs → update-QRMFRAQQ.mjs} +11 -9
- package/dist/cli/update-SP7UEO53.js +31 -0
- package/dist/cli/{workflow-26URBWPV.mjs → workflow-FOEEEB7G.mjs} +44 -20
- package/dist/cli/{workflow-3BS6U6SL.js → workflow-KOCK2FLW.js} +54 -30
- package/dist/{client-BfInrZPB.d.mts → client-74k4IPh6.d.mts} +135 -54
- package/dist/{client-BMjJFpan.d.ts → client-C1IK1f8c.d.ts} +135 -54
- package/dist/{compiler-manifest-Ycx-hoAr.d.mts → compiler-manifest-lzWpbV3w.d.mts} +83 -66
- package/dist/{compiler-manifest-Ycx-hoAr.d.ts → compiler-manifest-lzWpbV3w.d.ts} +83 -66
- package/dist/{index-CZXgiN3E.d.mts → index-C8Cy-YTm.d.ts} +5 -1
- package/dist/{index-NPG5pqxQ.d.ts → index-CtNK-0nI.d.mts} +5 -1
- package/dist/index.d.mts +47 -9
- package/dist/index.d.ts +47 -9
- package/dist/index.js +17 -14
- package/dist/index.mjs +13 -10
- package/dist/install-integrity.json +118 -102
- package/dist/plays/bundle-play-file.d.mts +3 -3
- package/dist/plays/bundle-play-file.d.ts +3 -3
- package/dist/plays/bundle-play-file.mjs +5 -4
- package/dist/plays/csv-data-input.js +3 -3
- package/dist/plays/csv-data-input.mjs +2 -2
- package/dist/plays/play-description.d.mts +2 -2
- package/dist/plays/play-description.d.ts +2 -2
- package/dist/plays/run-request.d.mts +2 -2
- package/dist/plays/run-request.d.ts +2 -2
- package/dist/plays/run-request.js +11 -3
- package/dist/plays/run-request.mjs +10 -2
- package/dist/release.d.mts +15 -6
- package/dist/release.d.ts +15 -6
- package/dist/release.js +2 -2
- package/dist/release.mjs +1 -1
- package/package.json +2 -2
- package/dist/cli/auth-F6BX32XZ.js +0 -40
- package/dist/cli/chunk-264PC2RN.mjs +0 -83
- package/dist/cli/chunk-44ZTYHMQ.mjs +0 -155
- package/dist/cli/chunk-53HN7WZN.js +0 -392
- package/dist/cli/chunk-7AALNGTA.mjs +0 -392
- package/dist/cli/chunk-ALD4COBH.js +0 -155
- package/dist/cli/chunk-CLJGSOVM.mjs +0 -1716
- package/dist/cli/chunk-WNUR6VP5.js +0 -83
- package/dist/cli/chunk-Z4VNJOF7.js +0 -1716
- package/dist/cli/git-VQFF6D7C.js +0 -24
- package/dist/cli/search-NCEEONMQ.js +0 -30
- package/dist/cli/sessions-3WYKQABW.js +0 -16
- package/dist/cli/skills-AKPAJVSO.js +0 -29
- package/dist/cli/tools-RBKEK6PM.js +0 -39
- package/dist/cli/update-VFNUBLDA.js +0 -29
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import { DeeplineError } from '../errors';
|
|
2
2
|
|
|
3
3
|
export function isTransientPlayRunReadError(error: unknown): boolean {
|
|
4
|
+
// The HTTP failure is diagnostic; an unconfirmed admission has no identity
|
|
5
|
+
// that makes repeating it safe, even when its response was a 5xx.
|
|
6
|
+
if (
|
|
7
|
+
error instanceof DeeplineError &&
|
|
8
|
+
error.code === 'PLAY_START_OUTCOME_UNKNOWN'
|
|
9
|
+
) {
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
4
12
|
if (
|
|
5
13
|
error instanceof DeeplineError &&
|
|
6
14
|
error.code === 'PLAY_STREAM_NETWORK_ABORTED'
|
|
@@ -9,21 +9,37 @@ import {
|
|
|
9
9
|
} from '../../../shared_libs/play-runtime/run-snapshot-stream.js';
|
|
10
10
|
import { isTransientPlayRunReadError } from './read-errors';
|
|
11
11
|
|
|
12
|
-
/**
|
|
12
|
+
/** Steady-state cadence for the small authenticated REST snapshot. */
|
|
13
13
|
export const RUN_WATCH_POLL_INTERVAL_MS = 2_000;
|
|
14
|
+
const RUN_WATCH_STARTUP_POLL_INTERVAL_MS = 500;
|
|
15
|
+
const RUN_WATCH_STARTUP_WINDOW_MS = 6_000;
|
|
14
16
|
|
|
15
17
|
type WatchHttp = {
|
|
16
18
|
get<T = unknown>(
|
|
17
19
|
path: string,
|
|
18
|
-
options?: {
|
|
20
|
+
options?: {
|
|
21
|
+
signal?: AbortSignal;
|
|
22
|
+
onResponse?: (response: Response) => void;
|
|
23
|
+
},
|
|
19
24
|
): Promise<T>;
|
|
20
25
|
};
|
|
21
26
|
|
|
27
|
+
export type WatchPollObservation = {
|
|
28
|
+
poll: number;
|
|
29
|
+
durationMs: number;
|
|
30
|
+
status?: number;
|
|
31
|
+
serverTiming?: string;
|
|
32
|
+
};
|
|
33
|
+
|
|
22
34
|
export type WatchRunEventsOptions = {
|
|
23
35
|
http: WatchHttp;
|
|
24
36
|
runId: string;
|
|
25
37
|
signal?: AbortSignal;
|
|
26
|
-
/**
|
|
38
|
+
/** Defer log-store reads until the run is terminal; the final log tail is unchanged. */
|
|
39
|
+
deferLogs?: boolean;
|
|
40
|
+
/** Skip log-store reads entirely for consumers that never render run logs. */
|
|
41
|
+
omitTerminalLogs?: boolean;
|
|
42
|
+
/** @internal Test seam; overrides the entire adaptive cadence. */
|
|
27
43
|
pollIntervalMs?: number;
|
|
28
44
|
onNotice?: (message: string) => void;
|
|
29
45
|
onRetry?: (info: {
|
|
@@ -31,11 +47,24 @@ export type WatchRunEventsOptions = {
|
|
|
31
47
|
delayMs: number;
|
|
32
48
|
reason: string;
|
|
33
49
|
}) => void;
|
|
50
|
+
/** @internal Exposes bounded request timing for CLI diagnostics. */
|
|
51
|
+
onPoll?: (observation: WatchPollObservation) => void;
|
|
52
|
+
/** @internal Request the existing status response on the terminal poll. */
|
|
53
|
+
terminalStatus?: {
|
|
54
|
+
full?: boolean;
|
|
55
|
+
billing?: boolean;
|
|
56
|
+
runStatus?: boolean;
|
|
57
|
+
onStatus: (
|
|
58
|
+
response: Record<string, unknown>,
|
|
59
|
+
status: string,
|
|
60
|
+
) => void | Promise<void>;
|
|
61
|
+
};
|
|
34
62
|
};
|
|
35
63
|
|
|
36
64
|
type WatchSnapshotResponse = {
|
|
37
65
|
runId: string;
|
|
38
66
|
snapshot: PlayRunLiveSnapshot;
|
|
67
|
+
terminalStatus?: Record<string, unknown>;
|
|
39
68
|
};
|
|
40
69
|
|
|
41
70
|
type WatchRunLogPage = {
|
|
@@ -83,7 +112,24 @@ function readSnapshotResponse(
|
|
|
83
112
|
) {
|
|
84
113
|
throw new Error(`Run watch returned an invalid snapshot for ${runId}.`);
|
|
85
114
|
}
|
|
86
|
-
|
|
115
|
+
if (
|
|
116
|
+
record.terminalStatus !== undefined &&
|
|
117
|
+
(!record.terminalStatus ||
|
|
118
|
+
typeof record.terminalStatus !== 'object' ||
|
|
119
|
+
Array.isArray(record.terminalStatus) ||
|
|
120
|
+
!isTerminalPlayRunLiveStatus((snapshot as PlayRunLiveSnapshot).status))
|
|
121
|
+
) {
|
|
122
|
+
throw new Error(
|
|
123
|
+
`Run watch returned an invalid terminal status for ${runId}.`,
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
return {
|
|
127
|
+
runId,
|
|
128
|
+
snapshot: snapshot as PlayRunLiveSnapshot,
|
|
129
|
+
...(record.terminalStatus !== undefined
|
|
130
|
+
? { terminalStatus: record.terminalStatus as Record<string, unknown> }
|
|
131
|
+
: {}),
|
|
132
|
+
};
|
|
87
133
|
}
|
|
88
134
|
|
|
89
135
|
async function backfillRotatedLogTail(input: {
|
|
@@ -141,26 +187,85 @@ export async function* watchRunEvents(
|
|
|
141
187
|
options: WatchRunEventsOptions,
|
|
142
188
|
): AsyncGenerator<PlayRunStreamEvent> {
|
|
143
189
|
const { http, runId, signal } = options;
|
|
144
|
-
const
|
|
190
|
+
const params = new URLSearchParams({ watchSnapshot: 'true' });
|
|
191
|
+
if (options.deferLogs) params.set('deferLogs', 'true');
|
|
192
|
+
if (options.omitTerminalLogs) params.set('omitTerminalLogs', 'true');
|
|
193
|
+
if (options.terminalStatus) {
|
|
194
|
+
params.set(
|
|
195
|
+
'terminalStatus',
|
|
196
|
+
options.terminalStatus.full ? 'full' : 'compact',
|
|
197
|
+
);
|
|
198
|
+
if (options.terminalStatus.billing === false)
|
|
199
|
+
params.set('billing', 'false');
|
|
200
|
+
if (options.terminalStatus.runStatus)
|
|
201
|
+
params.set('terminalRunStatus', 'true');
|
|
202
|
+
}
|
|
203
|
+
const path = `/api/v2/runs/${encodeURIComponent(runId)}?${params}`;
|
|
145
204
|
const streamId = `play-run-watch:${runId}`;
|
|
146
|
-
const
|
|
205
|
+
const watchStartedAt = Date.now();
|
|
147
206
|
let previous: PlayRunStreamDiffState = EMPTY_PLAY_RUN_STREAM_DIFF_STATE;
|
|
148
207
|
let consecutiveFailures = 0;
|
|
149
208
|
let outageNoticeSent = false;
|
|
209
|
+
let pollCount = 0;
|
|
150
210
|
|
|
151
211
|
while (!signal?.aborted) {
|
|
152
212
|
const pollStartedAt = Date.now();
|
|
213
|
+
const poll = ++pollCount;
|
|
214
|
+
// Keep a moderate cadence through the sandbox startup window. This halves
|
|
215
|
+
// short-run snapshot reads while avoiding a two-second detection gap just
|
|
216
|
+
// after Daytona finishes starting a fresh sandbox.
|
|
217
|
+
const pollIntervalMs =
|
|
218
|
+
options.pollIntervalMs ??
|
|
219
|
+
(pollStartedAt - watchStartedAt < RUN_WATCH_STARTUP_WINDOW_MS
|
|
220
|
+
? RUN_WATCH_STARTUP_POLL_INTERVAL_MS
|
|
221
|
+
: RUN_WATCH_POLL_INTERVAL_MS);
|
|
153
222
|
let snapshot: PlayRunLiveSnapshot;
|
|
223
|
+
let terminalStatus: Record<string, unknown> | undefined;
|
|
224
|
+
let responseStatus: number | undefined;
|
|
225
|
+
let serverTiming: string | undefined;
|
|
226
|
+
let pollReported = false;
|
|
227
|
+
const reportPoll = () => {
|
|
228
|
+
if (!options.onPoll || pollReported) return;
|
|
229
|
+
pollReported = true;
|
|
230
|
+
try {
|
|
231
|
+
options.onPoll({
|
|
232
|
+
poll,
|
|
233
|
+
durationMs: Date.now() - pollStartedAt,
|
|
234
|
+
...(responseStatus !== undefined ? { status: responseStatus } : {}),
|
|
235
|
+
...(serverTiming ? { serverTiming } : {}),
|
|
236
|
+
});
|
|
237
|
+
} catch {
|
|
238
|
+
// Diagnostics must not turn a successful poll into a retry.
|
|
239
|
+
}
|
|
240
|
+
};
|
|
154
241
|
try {
|
|
155
|
-
const response = await http.get<unknown>(path, {
|
|
156
|
-
snapshot = await backfillRotatedLogTail({
|
|
157
|
-
http,
|
|
158
|
-
runId,
|
|
159
|
-
snapshot: readSnapshotResponse(response, runId).snapshot,
|
|
160
|
-
previous,
|
|
242
|
+
const response = await http.get<unknown>(path, {
|
|
161
243
|
signal,
|
|
244
|
+
...(options.onPoll
|
|
245
|
+
? {
|
|
246
|
+
onResponse: (response: Response) => {
|
|
247
|
+
responseStatus = response.status;
|
|
248
|
+
serverTiming =
|
|
249
|
+
response.headers.get('server-timing') ?? undefined;
|
|
250
|
+
},
|
|
251
|
+
}
|
|
252
|
+
: {}),
|
|
162
253
|
});
|
|
254
|
+
const parsed = readSnapshotResponse(response, runId);
|
|
255
|
+
terminalStatus = parsed.terminalStatus;
|
|
256
|
+
// Deferred watchers need the terminal tail, not a replay of every skipped log.
|
|
257
|
+
snapshot = options.deferLogs
|
|
258
|
+
? parsed.snapshot
|
|
259
|
+
: await backfillRotatedLogTail({
|
|
260
|
+
http,
|
|
261
|
+
runId,
|
|
262
|
+
snapshot: parsed.snapshot,
|
|
263
|
+
previous,
|
|
264
|
+
signal,
|
|
265
|
+
});
|
|
266
|
+
reportPoll();
|
|
163
267
|
} catch (error) {
|
|
268
|
+
reportPoll();
|
|
164
269
|
if (signal?.aborted) {
|
|
165
270
|
return;
|
|
166
271
|
}
|
|
@@ -176,7 +281,7 @@ export async function* watchRunEvents(
|
|
|
176
281
|
reason,
|
|
177
282
|
});
|
|
178
283
|
options.onNotice?.(
|
|
179
|
-
`[watch] run snapshot request failed; retrying
|
|
284
|
+
`[watch] run snapshot request failed; retrying snapshot polling (${reason})`,
|
|
180
285
|
);
|
|
181
286
|
outageNoticeSent = true;
|
|
182
287
|
}
|
|
@@ -196,6 +301,12 @@ export async function* watchRunEvents(
|
|
|
196
301
|
}
|
|
197
302
|
consecutiveFailures = 0;
|
|
198
303
|
|
|
304
|
+
// Give the consumer the same durable status it would otherwise fetch
|
|
305
|
+
// before emitting terminal events that cause that serial HTTP request.
|
|
306
|
+
if (terminalStatus) {
|
|
307
|
+
await options.terminalStatus?.onStatus(terminalStatus, snapshot.status);
|
|
308
|
+
}
|
|
309
|
+
|
|
199
310
|
const diff = diffPlayRunStreamEvents({
|
|
200
311
|
streamId,
|
|
201
312
|
snapshot,
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { resolveLookupClientTimeoutMs } from '../../shared_libs/integration-contracts/lookup-execution-policy.js';
|
|
2
2
|
import type { ToolResultBilling } from '../../shared_libs/plays/tool-result-types.js';
|
|
3
|
+
import {
|
|
4
|
+
parseExecuteServerTiming,
|
|
5
|
+
type ExecuteServerTiming,
|
|
6
|
+
} from '../../shared_libs/play-runtime/execute-server-timing';
|
|
3
7
|
import { resolveTheirstackClientTimeoutMs } from '../../shared_libs/integration-contracts/theirstack/execution-policy.js';
|
|
4
8
|
import { resolveWaterfallClientTimeoutMs } from '../../shared_libs/integration-contracts/waterfall/execution-policy.js';
|
|
5
9
|
import {
|
|
@@ -19,6 +23,7 @@ import {
|
|
|
19
23
|
import { DeeplineError, ToolExecutionError } from './errors';
|
|
20
24
|
import type { HttpClient } from './http';
|
|
21
25
|
import { validateCliInvocationId } from './cli-invocation-id';
|
|
26
|
+
import { ATOMIC_TOOL_EXECUTE_SUPPORTED_HEADER } from '../../shared_libs/integration-contracts/execute-retry-contract.js';
|
|
22
27
|
|
|
23
28
|
const INCLUDE_TOOL_METADATA_HEADER = 'x-deepline-include-tool-metadata';
|
|
24
29
|
const EXECUTE_RESPONSE_CONTRACT_HEADER = 'x-deepline-execute-response-contract';
|
|
@@ -117,6 +122,8 @@ const DEEPLINEAGENT_EXECUTE_TIMEOUT_MS = 15 * 60 * 1000;
|
|
|
117
122
|
|
|
118
123
|
export type ExecuteToolRawOptions = {
|
|
119
124
|
includeToolMetadata?: boolean;
|
|
125
|
+
/** Use the atomic-tools endpoint, which rejects Plays before charge admission. */
|
|
126
|
+
atomicToolOnly?: boolean;
|
|
120
127
|
responseIntent?: 'dataset' | 'raw' | 'row_artifact';
|
|
121
128
|
metadata?: Record<string, unknown>;
|
|
122
129
|
timeout?: number;
|
|
@@ -140,7 +147,9 @@ export type ExecuteToolRawOptions = {
|
|
|
140
147
|
receivedAtMs: number;
|
|
141
148
|
httpStatus: number;
|
|
142
149
|
state: 'completed' | 'failed' | 'cancelled';
|
|
143
|
-
}) => void
|
|
150
|
+
}) => void | Promise<void>;
|
|
151
|
+
/** Optional response-path diagnostics; does not affect execution or retries. */
|
|
152
|
+
onServerTiming?: (timing: ExecuteServerTiming | null) => void | Promise<void>;
|
|
144
153
|
};
|
|
145
154
|
|
|
146
155
|
/** Durable state returned for a keyed tool execution. */
|
|
@@ -376,13 +385,6 @@ export class ToolCalls {
|
|
|
376
385
|
inputSnapshot,
|
|
377
386
|
this.configuredRequestTimeoutMs,
|
|
378
387
|
);
|
|
379
|
-
if (idempotencyKey !== undefined) {
|
|
380
|
-
await this.lookupExecutionByKey(
|
|
381
|
-
idempotencyKey,
|
|
382
|
-
timeoutMs,
|
|
383
|
-
options?.cliInvocationId,
|
|
384
|
-
);
|
|
385
|
-
}
|
|
386
388
|
const isApifySync = toolId.trim().toLowerCase() === 'apify_run_actor_sync';
|
|
387
389
|
const headers = {
|
|
388
390
|
[EXECUTE_RESPONSE_CONTRACT_HEADER]: RAW_V2_EXECUTE_RESPONSE_CONTRACT,
|
|
@@ -436,18 +438,35 @@ export class ToolCalls {
|
|
|
436
438
|
: failure
|
|
437
439
|
? 'failed'
|
|
438
440
|
: null;
|
|
439
|
-
if (terminal)
|
|
440
|
-
|
|
441
|
+
if (!terminal || !options?.onResponseReceived) return;
|
|
442
|
+
const reportObservationFailure = () =>
|
|
443
|
+
console.error('[tools.execute] response observation failed');
|
|
444
|
+
try {
|
|
445
|
+
const notification = options.onResponseReceived({
|
|
441
446
|
receivedAtMs: lastResponse.receivedAtMs,
|
|
442
447
|
httpStatus: lastResponse.httpStatus,
|
|
443
448
|
state: terminal,
|
|
444
449
|
});
|
|
450
|
+
void Promise.resolve(notification).catch(reportObservationFailure);
|
|
451
|
+
} catch {
|
|
452
|
+
reportObservationFailure();
|
|
453
|
+
}
|
|
445
454
|
};
|
|
446
|
-
const
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
455
|
+
const legacyEndpoint = `/api/v2/integrations/${encodeURIComponent(toolId)}/execute`;
|
|
456
|
+
let useLegacyEndpoint = idempotencyKey === undefined;
|
|
457
|
+
const atomicToolOnly = options?.atomicToolOnly === true;
|
|
458
|
+
const dispatchRequest = async (
|
|
459
|
+
requestTimeoutMs: number | undefined,
|
|
460
|
+
): Promise<ToolExecution<TData, TMeta>> => {
|
|
461
|
+
let recoverySupported = false;
|
|
462
|
+
let atomicToolsSupported = false;
|
|
463
|
+
const post = () =>
|
|
464
|
+
this.http.post<ToolExecution<TData, TMeta>>(
|
|
465
|
+
atomicToolOnly
|
|
466
|
+
? `/api/v2/tools/${encodeURIComponent(toolId)}/execute`
|
|
467
|
+
: useLegacyEndpoint
|
|
468
|
+
? legacyEndpoint
|
|
469
|
+
: `/api/v2/executions/by-key/${encodeURIComponent(idempotencyKey!)}?tool_id=${encodeURIComponent(toolId)}`,
|
|
451
470
|
{
|
|
452
471
|
payload: inputSnapshot,
|
|
453
472
|
...(metadataSnapshot ? { metadata: metadataSnapshot } : {}),
|
|
@@ -456,21 +475,91 @@ export class ToolCalls {
|
|
|
456
475
|
{
|
|
457
476
|
timeout: requestTimeoutMs,
|
|
458
477
|
maxRetries: idempotencyKey ? 0 : (options?.maxRetries ?? 0),
|
|
459
|
-
|
|
478
|
+
...(atomicToolOnly &&
|
|
479
|
+
!idempotencyKey &&
|
|
480
|
+
options?.maxRetries === undefined
|
|
481
|
+
? { executePolicyMaxRetries: 2 }
|
|
482
|
+
: {}),
|
|
483
|
+
retryApiErrors: atomicToolOnly || options?.retryApiErrors === true,
|
|
484
|
+
retryFromExecutePolicy: atomicToolOnly,
|
|
460
485
|
exactUrlOnly: true,
|
|
461
486
|
toolId,
|
|
462
487
|
idempotencyKey,
|
|
463
|
-
onResponse: () => {
|
|
488
|
+
onResponse: (response) => {
|
|
464
489
|
lastResponse = null;
|
|
490
|
+
atomicToolsSupported =
|
|
491
|
+
response.headers.get(ATOMIC_TOOL_EXECUTE_SUPPORTED_HEADER) ===
|
|
492
|
+
'true';
|
|
493
|
+
recoverySupported =
|
|
494
|
+
response.headers.get('X-Deepline-Idempotency-Supported') ===
|
|
495
|
+
'true';
|
|
496
|
+
if (options?.onServerTiming) {
|
|
497
|
+
try {
|
|
498
|
+
const notification = options.onServerTiming(
|
|
499
|
+
parseExecuteServerTiming(
|
|
500
|
+
response.headers.get('server-timing'),
|
|
501
|
+
),
|
|
502
|
+
);
|
|
503
|
+
void Promise.resolve(notification).catch(() => undefined);
|
|
504
|
+
} catch {
|
|
505
|
+
// Diagnostic callbacks cannot turn a delivered mutation into
|
|
506
|
+
// an ambiguous failure or trigger execution recovery.
|
|
507
|
+
}
|
|
508
|
+
}
|
|
465
509
|
},
|
|
466
510
|
onResponseBody: (observation) => {
|
|
467
511
|
lastResponse = observation;
|
|
468
512
|
},
|
|
469
513
|
},
|
|
470
514
|
);
|
|
515
|
+
try {
|
|
516
|
+
return await post();
|
|
517
|
+
} catch (error) {
|
|
518
|
+
if (atomicToolOnly) {
|
|
519
|
+
if (
|
|
520
|
+
!atomicToolsSupported &&
|
|
521
|
+
!recoverySupported &&
|
|
522
|
+
!(error instanceof ToolExecutionError) &&
|
|
523
|
+
error instanceof DeeplineError &&
|
|
524
|
+
(error.statusCode === 404 || error.statusCode === 405)
|
|
525
|
+
) {
|
|
526
|
+
throw new DeeplineError(
|
|
527
|
+
'This server does not support atomic tool execution.',
|
|
528
|
+
error.statusCode,
|
|
529
|
+
'ATOMIC_TOOL_EXECUTE_UNSUPPORTED',
|
|
530
|
+
);
|
|
531
|
+
}
|
|
532
|
+
throw error;
|
|
533
|
+
}
|
|
534
|
+
// Older servers reject this named action before dispatch. Confirm their
|
|
535
|
+
// legacy recovery contract before sending a mutating request there.
|
|
536
|
+
// Supported tool failures, ambiguous delivery, and auth errors never
|
|
537
|
+
// trigger this fallback.
|
|
538
|
+
if (
|
|
539
|
+
useLegacyEndpoint ||
|
|
540
|
+
recoverySupported ||
|
|
541
|
+
!(error instanceof DeeplineError) ||
|
|
542
|
+
(error.statusCode !== 404 && error.statusCode !== 405)
|
|
543
|
+
)
|
|
544
|
+
throw error;
|
|
545
|
+
lastResponse = null;
|
|
546
|
+
await this.lookupExecutionByKey(
|
|
547
|
+
idempotencyKey!,
|
|
548
|
+
requestTimeoutMs,
|
|
549
|
+
options?.cliInvocationId,
|
|
550
|
+
);
|
|
551
|
+
useLegacyEndpoint = true;
|
|
552
|
+
return post();
|
|
553
|
+
}
|
|
554
|
+
};
|
|
555
|
+
const request = async (
|
|
556
|
+
requestTimeoutMs: number | undefined,
|
|
557
|
+
): Promise<ToolExecution<TData, TMeta>> => {
|
|
558
|
+
lastResponse = null;
|
|
559
|
+
try {
|
|
560
|
+
return await dispatchRequest(requestTimeoutMs);
|
|
471
561
|
} catch (error) {
|
|
472
|
-
//
|
|
473
|
-
// ambiguous network/cancellation failure, proves a response endpoint.
|
|
562
|
+
// Observe only the final rejection, after compatibility dispatch.
|
|
474
563
|
observeTerminal({ error });
|
|
475
564
|
throw error;
|
|
476
565
|
}
|
|
@@ -219,6 +219,18 @@ export interface ProviderDefinition {
|
|
|
219
219
|
*/
|
|
220
220
|
export type { DeeplineToolCategory };
|
|
221
221
|
|
|
222
|
+
/** Visible category membership count; a tool can belong to several categories. */
|
|
223
|
+
export interface ToolCategorySummary {
|
|
224
|
+
name: string;
|
|
225
|
+
count: number;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/** Selected tool definitions and all visible category counts. */
|
|
229
|
+
export interface ToolCategoryListing {
|
|
230
|
+
categories: ToolCategorySummary[];
|
|
231
|
+
tools: ToolDefinition[];
|
|
232
|
+
}
|
|
233
|
+
|
|
222
234
|
/**
|
|
223
235
|
* Summary definition of a callable provider-backed tool.
|
|
224
236
|
*
|
|
@@ -877,6 +889,8 @@ export interface PlayRunPackage {
|
|
|
877
889
|
warnings?: string[];
|
|
878
890
|
/** Step-level summaries emitted by the runtime. */
|
|
879
891
|
steps: Array<Record<string, unknown>>;
|
|
892
|
+
/** Whether the admitted graph or observed ledger expects public steps. */
|
|
893
|
+
stepsExpected?: boolean;
|
|
880
894
|
/** Named output summaries, including dataset handles and scalar outputs. */
|
|
881
895
|
outputs: Record<string, Record<string, unknown>>;
|
|
882
896
|
/** Every durable Dataset Handle explicitly registered by this run. */
|
|
@@ -1854,6 +1868,8 @@ export interface PlayRunStart {
|
|
|
1854
1868
|
dashboardUrl?: string;
|
|
1855
1869
|
/** Terminal status returned when the start request used a short completion wait. */
|
|
1856
1870
|
finalStatus?: unknown;
|
|
1871
|
+
/** Explicit full representation assembled by the canonical status reader. */
|
|
1872
|
+
finalStatusView?: 'full';
|
|
1857
1873
|
/** Canonical compact run package returned by current SDK/API responses. */
|
|
1858
1874
|
package?: PlayRunPackage;
|
|
1859
1875
|
}
|
|
@@ -2178,6 +2194,8 @@ export interface StartPlayRunRequest {
|
|
|
2178
2194
|
maxCredits?: number;
|
|
2179
2195
|
/** Optionally let the start request wait briefly and return a terminal result. */
|
|
2180
2196
|
waitForCompletionMs?: number;
|
|
2197
|
+
/** Request full terminal status within an optional start completion wait. */
|
|
2198
|
+
terminalStatus?: 'full';
|
|
2181
2199
|
/**
|
|
2182
2200
|
* Per-run execution profile override. The server defaults to absurd. The
|
|
2183
2201
|
* Only `absurd` is accepted; most callers should leave this unset.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Trusted app-to-execution-gateway contract for replaying a completed
|
|
3
|
+
* integration attempt. The app resolves provider policy while it has the
|
|
4
|
+
* executable integration catalog loaded; the gateway persists this value with
|
|
5
|
+
* the exact response bytes and never loads provider code itself.
|
|
6
|
+
*/
|
|
7
|
+
export const EXECUTE_RETRY_POLICY_HEADER = 'x-deepline-execute-retry-policy';
|
|
8
|
+
|
|
9
|
+
export const EXECUTE_RETRY_POLICY_VERSION = 1;
|
|
10
|
+
|
|
11
|
+
export type ExecuteRetryPolicy =
|
|
12
|
+
| 'transient-http-safe'
|
|
13
|
+
| 'transient-http-unsafe';
|
|
14
|
+
|
|
15
|
+
export function serializeExecuteRetryPolicy(
|
|
16
|
+
retrySafeTransientHttp: boolean,
|
|
17
|
+
): string {
|
|
18
|
+
return `v${EXECUTE_RETRY_POLICY_VERSION}:${
|
|
19
|
+
retrySafeTransientHttp ? 'transient-http-safe' : 'transient-http-unsafe'
|
|
20
|
+
}`;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function parseExecuteRetryPolicy(
|
|
24
|
+
value: string | null | undefined,
|
|
25
|
+
): ExecuteRetryPolicy | null {
|
|
26
|
+
if (value === `v${EXECUTE_RETRY_POLICY_VERSION}:transient-http-safe`) {
|
|
27
|
+
return 'transient-http-safe';
|
|
28
|
+
}
|
|
29
|
+
if (value === `v${EXECUTE_RETRY_POLICY_VERSION}:transient-http-unsafe`) {
|
|
30
|
+
return 'transient-http-unsafe';
|
|
31
|
+
}
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** Marks authoritative responses from the atomic-tools execution endpoint. */
|
|
36
|
+
export const ATOMIC_TOOL_EXECUTE_SUPPORTED_HEADER =
|
|
37
|
+
'x-deepline-atomic-tool-supported';
|
|
@@ -193,7 +193,7 @@ export async function uploadBufferToR2(input: {
|
|
|
193
193
|
logR2Perf('client', input.key, clientStartedAt, { kind: bucketKind });
|
|
194
194
|
|
|
195
195
|
const sendStartedAt = Date.now();
|
|
196
|
-
await client.send(
|
|
196
|
+
const result = await client.send(
|
|
197
197
|
new PutObjectCommand({
|
|
198
198
|
Bucket: config.bucket,
|
|
199
199
|
Key: input.key,
|
|
@@ -203,6 +203,8 @@ export async function uploadBufferToR2(input: {
|
|
|
203
203
|
}),
|
|
204
204
|
);
|
|
205
205
|
logR2Perf('put-send', input.key, sendStartedAt, {
|
|
206
|
+
attempts: result.$metadata.attempts ?? null,
|
|
207
|
+
retryDelayMs: result.$metadata.totalRetryDelay ?? null,
|
|
206
208
|
kind: bucketKind,
|
|
207
209
|
bytes: input.body.byteLength,
|
|
208
210
|
});
|