deepline 0.3.391 → 0.3.393
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 +156 -24
- package/dist/bundling-sources/sdk/src/compat.ts +9 -0
- package/dist/bundling-sources/sdk/src/http.ts +5 -1
- package/dist/bundling-sources/sdk/src/index.ts +5 -0
- package/dist/bundling-sources/sdk/src/plays/csv-data-input.ts +3 -0
- package/dist/bundling-sources/sdk/src/plays/run-request.ts +182 -6
- package/dist/bundling-sources/sdk/src/release.ts +4 -1
- package/dist/bundling-sources/sdk/src/types.ts +15 -0
- package/dist/bundling-sources/shared_libs/integration-contracts/request-warnings.ts +64 -0
- package/dist/bundling-sources/shared_libs/play-data-plane/runtime-sheet-storage-contract.ts +315 -0
- package/dist/bundling-sources/shared_libs/play-runtime/async-operation.ts +41 -8
- package/dist/bundling-sources/shared_libs/play-runtime/context.ts +418 -44
- package/dist/bundling-sources/shared_libs/play-runtime/ctx-types.ts +36 -3
- package/dist/bundling-sources/shared_libs/play-runtime/durable-invocation-fence.ts +36 -0
- package/dist/bundling-sources/shared_libs/play-runtime/map-execution-frame.ts +11 -3
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/projection/gateway-adapter.ts +1 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runtime-semantics.ts +19 -1
- package/dist/bundling-sources/shared_libs/play-runtime/run-identity.ts +26 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-app/index.ts +158 -10
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-api.ts +235 -2
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-runtime-worker.ts +92 -58
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-pool.ts +7 -1
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-progress.ts +30 -7
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres.ts +1161 -316
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-event-search.ts +28 -15
- package/dist/bundling-sources/shared_libs/play-runtime/tool-execute-retry-policy.ts +24 -3
- package/dist/bundling-sources/shared_libs/play-runtime/tool-result.ts +31 -0
- package/dist/bundling-sources/shared_libs/plays/authoring-contract.ts +37 -4
- package/dist/bundling-sources/shared_libs/plays/dataset.ts +172 -79
- package/dist/bundling-sources/shared_libs/plays/extension-bridge.ts +57 -0
- package/dist/bundling-sources/shared_libs/plays/run-summary-types.ts +1 -0
- package/dist/bundling-sources/shared_libs/plays/static-pipeline.ts +173 -1
- package/dist/cli/{auth-6QET7NFP.mjs → auth-5PXHA232.mjs} +4 -4
- package/dist/cli/auth-P3MVDTXM.js +39 -0
- package/dist/cli/{billing-KJAGTCFR.js → billing-JFB2XLSO.js} +101 -74
- package/dist/cli/{billing-HAQ2VDQX.mjs → billing-Z2N7ZAGM.mjs} +32 -5
- package/dist/cli/{chunk-556BMGEB.js → chunk-2HAD745V.js} +242 -183
- package/dist/cli/{chunk-HFTOOZGN.mjs → chunk-2LGC4EFT.mjs} +3 -3
- package/dist/cli/{chunk-QCWIORKR.mjs → chunk-4PT2VA3A.mjs} +2 -2
- package/dist/cli/{chunk-KA7X75HC.js → chunk-4XX6443T.js} +176 -87
- package/dist/cli/{chunk-YBZY3EZF.mjs → chunk-5KWKZIQR.mjs} +4 -4
- package/dist/cli/{chunk-VH4B5OYM.mjs → chunk-5PRVMXKB.mjs} +27 -2
- package/dist/cli/{chunk-DSWSEHRX.mjs → chunk-6I73X254.mjs} +1 -1
- package/dist/cli/{chunk-6L4P7Z6C.mjs → chunk-7HR7BGZL.mjs} +13 -3
- package/dist/cli/{chunk-4S6X74A3.js → chunk-AARX5L4B.js} +2 -2
- package/dist/cli/{chunk-MHLCMJ2E.js → chunk-CDFH2DYL.js} +20 -19
- package/dist/cli/{chunk-PFPP4BKS.mjs → chunk-FQ6VHPW4.mjs} +2 -2
- package/dist/cli/{chunk-5JLQPVNX.js → chunk-GSK6NHVM.js} +1 -0
- package/dist/cli/{chunk-TLHF54VX.mjs → chunk-HLEESTCH.mjs} +1 -1
- package/dist/cli/{chunk-EDWJY6T4.mjs → chunk-HQXL5526.mjs} +1 -0
- package/dist/cli/{chunk-Q6EOHNRH.mjs → chunk-JI2B4RZP.mjs} +119 -6
- package/dist/cli/{chunk-I3MKXASV.mjs → chunk-KIYU2TGL.mjs} +2 -2
- package/dist/cli/{chunk-Y6VOGHF2.mjs → chunk-KZZC33PY.mjs} +0 -181
- package/dist/cli/{chunk-XBPLTHGB.js → chunk-L2SYLGRP.js} +8 -8
- package/dist/cli/{chunk-K3ODOHOI.mjs → chunk-LMMEAMA7.mjs} +3 -2
- package/dist/cli/{chunk-KWF4HJF7.mjs → chunk-LZPCDB7U.mjs} +3 -2
- package/dist/cli/{chunk-I7EVBLTW.js → chunk-M7Y7JYZX.js} +32 -7
- package/dist/cli/{chunk-QGKPTBRR.js → chunk-MS6GUPBB.js} +3 -3
- package/dist/cli/{chunk-ME2DZAHC.js → chunk-OXNOAD6Y.js} +26 -26
- package/dist/cli/{chunk-XEV5LMS2.js → chunk-PTDECJGP.js} +50 -50
- package/dist/cli/{chunk-5O4B6AUN.js → chunk-PWSWAN7Q.js} +25 -2
- package/dist/cli/{chunk-DRZFTRZJ.mjs → chunk-Q26LUSQ2.mjs} +79 -20
- package/dist/cli/{chunk-3VN4FTE3.js → chunk-RDXFGPJU.js} +1 -182
- package/dist/cli/{chunk-7E66A24V.mjs → chunk-RKMB3N7K.mjs} +25 -2
- package/dist/cli/{chunk-WLODHQ7S.js → chunk-RWHWF5ZJ.js} +3 -2
- package/dist/cli/{chunk-H3DCZOXR.mjs → chunk-STNYIMIV.mjs} +97 -8
- package/dist/cli/chunk-UBKA33KY.mjs +310 -0
- package/dist/cli/{chunk-PAIMOGCM.js → chunk-UHNDVD3P.js} +125 -12
- package/dist/cli/{chunk-H2ER7QWR.mjs → chunk-UOGZUA24.mjs} +180 -18
- package/dist/cli/{chunk-RTH26NF3.js → chunk-VIQJIX2P.js} +73 -63
- package/dist/cli/{chunk-ED42XCOW.js → chunk-VIWE6WRK.js} +629 -467
- package/dist/cli/{chunk-RA2SDTSX.js → chunk-W4WOMXR3.js} +15 -15
- package/dist/cli/chunk-XDVT3GOM.js +310 -0
- package/dist/cli/{chunk-UOSKJIXE.js → chunk-Z3OOZM5L.js} +8 -8
- package/dist/cli/{csv-V7UHOBFE.mjs → csv-KJWZHKCH.mjs} +3 -3
- package/dist/cli/{csv-2WSF5TEM.js → csv-P3Z3YE7H.js} +12 -12
- package/dist/cli/{db-TD375E4N.mjs → db-NCM4CQIS.mjs} +6 -5
- package/dist/cli/{db-42RL4FZD.js → db-NUZGJNQC.js} +31 -30
- package/dist/cli/{describe-GPUKAWOZ.mjs → describe-WT6MM2GO.mjs} +18 -17
- package/dist/cli/{describe-7WFCBZUY.js → describe-YGSEN5WC.js} +25 -24
- package/dist/cli/{executions-LGVG3FPH.js → executions-PCOLHN7Q.js} +8 -7
- package/dist/cli/{executions-M7O63JNA.mjs → executions-XS2IPJ4W.mjs} +6 -5
- package/dist/cli/{feedback-PZZA2M4S.js → feedback-4MSH7TFU.js} +7 -7
- package/dist/cli/{feedback-6PBSKVB2.mjs → feedback-CCLTS5SV.mjs} +3 -3
- package/dist/cli/{git-2VIFM5DI.mjs → git-K2DHPMPC.mjs} +4 -4
- package/dist/cli/git-RNM45FX4.js +23 -0
- package/dist/cli/index.js +96 -92
- package/dist/cli/index.mjs +46 -42
- package/dist/cli/{legacy-noops-DPUBZI7N.mjs → legacy-noops-B5S4AR3P.mjs} +4 -4
- package/dist/cli/{legacy-noops-IQ6QTZNZ.js → legacy-noops-GPNOPFXV.js} +7 -7
- package/dist/cli/{monitors-KBZVQG2U.mjs → monitors-JLMAIPRG.mjs} +6 -5
- package/dist/cli/{monitors-6GWAZFYV.js → monitors-ZAWD7NSN.js} +87 -86
- package/dist/cli/{org-JKGTHXOZ.js → org-P2KN4CES.js} +66 -65
- package/dist/cli/{org-CP3VSJBX.mjs → org-T3JTHP4G.mjs} +6 -5
- package/dist/cli/{play-DD2ME4L4.mjs → play-NK6BLRGL.mjs} +12 -11
- package/dist/cli/play-PDXR6JFB.js +158 -0
- package/dist/cli/{providers-JUNOFKI7.mjs → providers-3NQRA7IT.mjs} +6 -5
- package/dist/cli/{providers-P34QYYG6.js → providers-5QRZN3DT.js} +9 -8
- package/dist/cli/{quickstart-N6SWOK7E.mjs → quickstart-PIA2JGPV.mjs} +3 -3
- package/dist/cli/{quickstart-UL3DEFA4.js → quickstart-R7NUZGNW.js} +5 -5
- package/dist/cli/run-identity-G257GQED.js +25 -0
- package/dist/cli/run-identity-MRNCEGV2.mjs +25 -0
- package/dist/cli/{search-SC7I56HX.mjs → search-AIDIIGLY.mjs} +7 -6
- package/dist/cli/search-QRWL7MFM.js +27 -0
- package/dist/cli/{secrets-6ZJE7ZPM.js → secrets-BT3PGMWN.js} +15 -14
- package/dist/cli/{secrets-RTARNYF5.mjs → secrets-OQNHL45O.mjs} +6 -5
- package/dist/cli/{sessions-6IZ2XHGW.js → sessions-EYXWOSWK.js} +5 -5
- package/dist/cli/{sessions-7RKV2T3O.mjs → sessions-SF7WJPJP.mjs} +4 -4
- package/dist/cli/{settings-YX3XJDXE.js → settings-BA3GHBOD.js} +76 -75
- package/dist/cli/{settings-V6PXA6HY.mjs → settings-Y57JTFDD.mjs} +9 -8
- package/dist/cli/{setup-V2O4UJNT.mjs → setup-7GR5GBHA.mjs} +6 -6
- package/dist/cli/{setup-CQ5VRNNU.js → setup-RERXYC66.js} +41 -41
- package/dist/cli/{skills-VHJZWEHA.mjs → skills-SJWIQAV5.mjs} +4 -4
- package/dist/cli/skills-V7EY75HB.js +28 -0
- package/dist/cli/tools-H5HLBCHH.js +41 -0
- package/dist/cli/{tools-OD5WKEWY.mjs → tools-ZF3JXPNL.mjs} +10 -9
- package/dist/cli/update-472HA3LT.js +28 -0
- package/dist/cli/{update-CRMNOMJ3.mjs → update-FFFYQAOJ.mjs} +6 -6
- package/dist/cli/{workflow-XHORSD5T.js → workflow-SZJVQH4T.js} +17 -16
- package/dist/cli/{workflow-EVDYNCDD.mjs → workflow-XVFEEGAS.mjs} +7 -6
- package/dist/{client-DpzZi4fU.d.mts → client-DU5dtHDy.d.mts} +157 -4
- package/dist/{client-BhK9kix9.d.ts → client-mCE88hC4.d.ts} +157 -4
- package/dist/{compiler-manifest-CY2v8ab0.d.ts → compiler-manifest-DE4RdAiY.d.mts} +61 -1
- package/dist/{compiler-manifest-CY2v8ab0.d.mts → compiler-manifest-DE4RdAiY.d.ts} +61 -1
- package/dist/{index-B9fBZH1g.d.mts → index-BI6nWgaV.d.mts} +1 -1
- package/dist/{index-BZ6uzZJl.d.ts → index-Bi-f7HFT.d.ts} +1 -1
- package/dist/index.d.mts +5 -5
- package/dist/index.d.ts +5 -5
- package/dist/index.js +120 -29
- package/dist/index.mjs +111 -20
- package/dist/install-integrity.json +94 -88
- 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 +2 -2
- package/dist/plays/csv-data-input.d.mts +2 -0
- package/dist/plays/csv-data-input.d.ts +2 -0
- package/dist/plays/csv-data-input.js +2 -2
- package/dist/plays/csv-data-input.mjs +1 -1
- package/dist/plays/run-request.d.mts +2 -2
- package/dist/plays/run-request.d.ts +2 -2
- package/dist/plays/run-request.js +5 -2
- package/dist/plays/run-request.mjs +4 -1
- package/dist/release.d.mts +4 -1
- package/dist/release.d.ts +4 -1
- package/dist/release.js +2 -2
- package/dist/release.mjs +1 -1
- package/package.json +1 -1
- package/dist/cli/auth-6ZUH42ZA.js +0 -39
- package/dist/cli/git-ZSJD3BID.js +0 -23
- package/dist/cli/play-G5GVMIBN.js +0 -157
- package/dist/cli/search-W4GXWTOM.js +0 -26
- package/dist/cli/skills-LBZPJTPI.js +0 -28
- package/dist/cli/tools-TQNM473H.js +0 -40
- package/dist/cli/update-QY6GAK6B.js +0 -28
package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-event-search.ts
CHANGED
|
@@ -2040,7 +2040,7 @@ export async function attachRuntimeEventSearchTriggers(
|
|
|
2040
2040
|
await client.query(`
|
|
2041
2041
|
CREATE OR REPLACE FUNCTION ${schema}.project_origin_log_batch(observation ${schema}.outbox, item jsonb, run_org text, play text, compact_logs boolean, canonical_events boolean, at_time timestamptz, doc jsonb, closed boolean)
|
|
2042
2042
|
RETURNS text[] LANGUAGE plpgsql SECURITY DEFINER SET search_path = pg_catalog AS $function$
|
|
2043
|
-
DECLARE fresh text[]; mismatches bigint;
|
|
2043
|
+
DECLARE fresh text[]; mismatches bigint; expected_keys jsonb; existing_identities jsonb;
|
|
2044
2044
|
batch_lines jsonb := item->'lines';
|
|
2045
2045
|
batch_ids jsonb := item->'lineIds';
|
|
2046
2046
|
batch_contexts jsonb := item->'lineContexts';
|
|
@@ -2110,24 +2110,33 @@ export async function attachRuntimeEventSearchTriggers(
|
|
|
2110
2110
|
-- Resolve the whole key set once. A per-line LATERAL lookup can choose
|
|
2111
2111
|
-- a non-leading event_id index scan when scope/org statistics are skewed,
|
|
2112
2112
|
-- re-reading the same history for every ID even though the PK is unique.
|
|
2113
|
-
|
|
2114
|
-
|
|
2113
|
+
-- Generic plans may scan the scope/org prefix and test ANY(text[]) for
|
|
2114
|
+
-- every row. Use the indexed run prefix and a once-built JSON key set.
|
|
2115
|
+
SELECT jsonb_object_agg('log-origin:' || observation.run_id || ':' || (id #>> '{}'), true)
|
|
2116
|
+
INTO expected_keys FROM jsonb_array_elements(batch_ids) AS ids(id);
|
|
2115
2117
|
SELECT jsonb_object_agg(event.event_id, jsonb_build_object(
|
|
2116
2118
|
'runId', event.run_id, 'kind', event.kind, 'digest', event.source_digest))
|
|
2117
2119
|
INTO existing_identities
|
|
2118
2120
|
FROM runtime_observability.events event
|
|
2119
2121
|
WHERE event.runtime_scope = ${quoteLiteral(scope)} AND event.org_id = run_org
|
|
2120
|
-
AND event.
|
|
2122
|
+
AND event.run_id = observation.run_id AND expected_keys ? event.event_id;
|
|
2121
2123
|
-- JSON key lookups preserve one proof per identity without a join whose
|
|
2122
2124
|
-- generic plan can multiply the two variable-size sets. Tombstones keep
|
|
2123
2125
|
-- their digest/identity: retry never restores an expired body.
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2126
|
+
-- Stream aligned IDs with their lines: positional text[] subscripting
|
|
2127
|
+
-- walks variable-width elements from the start on every lookup.
|
|
2128
|
+
WITH entries AS MATERIALIZED (
|
|
2129
|
+
SELECT body, 'log-origin:' || observation.run_id || ':' || id AS eid,
|
|
2130
|
+
NULLIF(batch_contexts->(ordinal-1)::int, 'null'::jsonb) AS ctx
|
|
2131
|
+
FROM ROWS FROM (jsonb_array_elements(batch_lines), jsonb_array_elements_text(batch_ids))
|
|
2132
|
+
WITH ORDINALITY AS aligned(body, id, ordinal)
|
|
2133
|
+
)
|
|
2134
|
+
SELECT count(*) INTO mismatches FROM entries
|
|
2135
|
+
WHERE existing_identities->eid->>'runId' IS DISTINCT FROM observation.run_id
|
|
2136
|
+
OR existing_identities->eid->>'kind' IS DISTINCT FROM ${RUN_EVENT_KIND_SQL_LITERAL.logAppended}
|
|
2137
|
+
OR existing_identities->eid->>'digest' IS DISTINCT FROM CASE WHEN ctx IS NULL
|
|
2129
2138
|
THEN encode(sha256(convert_to(body #>> '{}','UTF8')),'hex')
|
|
2130
|
-
ELSE encode(sha256(convert_to(jsonb_build_array(body #>> '{}',
|
|
2139
|
+
ELSE encode(sha256(convert_to(jsonb_build_array(body #>> '{}',ctx)::text,'UTF8')),'hex') END;
|
|
2131
2140
|
IF mismatches > 0 THEN
|
|
2132
2141
|
RAISE EXCEPTION 'Origin log identity changed its content or ingress is closed after terminal acceptance';
|
|
2133
2142
|
END IF;
|
|
@@ -2796,8 +2805,9 @@ export async function attachRuntimeEventSearchTriggers(
|
|
|
2796
2805
|
RETURNING last_seq INTO assigned_seq;
|
|
2797
2806
|
-- Build ordinal lookup once. Generic plans estimate a run and unnest
|
|
2798
2807
|
-- as tiny, then compare every inserted line against the entire ID list
|
|
2799
|
-
-- in a nested loop. Fresh IDs came only from
|
|
2800
|
-
-- for this scope/org/run, so
|
|
2808
|
+
-- in a nested loop or a per-row ANY filter. Fresh IDs came only from
|
|
2809
|
+
-- this transaction's inserts for this scope/org/run, so JSON key
|
|
2810
|
+
-- membership preserves the complete target within the indexed run.
|
|
2801
2811
|
SELECT jsonb_object_agg(fresh.event_id, fresh.ordinality)
|
|
2802
2812
|
INTO fresh_positions
|
|
2803
2813
|
FROM unnest(fresh_event_ids) WITH ORDINALITY AS fresh(event_id, ordinality);
|
|
@@ -2805,7 +2815,8 @@ export async function attachRuntimeEventSearchTriggers(
|
|
|
2805
2815
|
SET log_seq = assigned_seq - line_count + (fresh_positions->>event.event_id)::bigint
|
|
2806
2816
|
WHERE event.runtime_scope = ${quoteLiteral(scope)}
|
|
2807
2817
|
AND event.org_id = run_org
|
|
2808
|
-
AND event.
|
|
2818
|
+
AND event.run_id = observation.run_id
|
|
2819
|
+
AND fresh_positions ? event.event_id;
|
|
2809
2820
|
END IF;
|
|
2810
2821
|
RETURN;
|
|
2811
2822
|
END
|
|
@@ -3730,11 +3741,13 @@ export async function prepareRuntimeEventRetentionIndex(
|
|
|
3730
3741
|
};
|
|
3731
3742
|
let ready = (await inspect()).rows[0];
|
|
3732
3743
|
if (ready) {
|
|
3744
|
+
// Even IF NOT EXISTS acquires a table lock. A fully proved existing index
|
|
3745
|
+
// needs no shared DDL; invalid or mismatched definitions still fail loudly.
|
|
3733
3746
|
assertReady(ready);
|
|
3734
3747
|
} else {
|
|
3735
3748
|
await client.query(`CREATE INDEX CONCURRENTLY IF NOT EXISTS ${input.name}
|
|
3736
|
-
|
|
3737
|
-
|
|
3749
|
+
ON runtime_observability.events (ingested_at, event_id)
|
|
3750
|
+
WHERE ${input.predicate}`);
|
|
3738
3751
|
ready = (await inspect()).rows[0];
|
|
3739
3752
|
if (!ready) {
|
|
3740
3753
|
throw new Error(
|
|
@@ -798,10 +798,28 @@ export function classifyToolExecuteHttpFailure(input: {
|
|
|
798
798
|
executionFenced,
|
|
799
799
|
explicitRetryable,
|
|
800
800
|
});
|
|
801
|
+
// A status GET may fail after a stateful provider operation was accepted.
|
|
802
|
+
// Provider pacing remains useful, but retrying the whole tool would repeat
|
|
803
|
+
// its POST. This explicit recovery proof is stronger than a rejected-call
|
|
804
|
+
// 429; ordinary pacing denials retain their established retry semantics.
|
|
805
|
+
const failureBody = parseJsonObject(input.bodyText);
|
|
806
|
+
const flatPublicDetails = failureBody?.details;
|
|
807
|
+
const acceptedOperationNeedsRecovery =
|
|
808
|
+
explicitRetryable === false &&
|
|
809
|
+
(error instanceof ToolExecutionError
|
|
810
|
+
? error.origin === 'provider'
|
|
811
|
+
: failureBody?.failure_origin === 'provider') &&
|
|
812
|
+
((error instanceof ToolExecutionError &&
|
|
813
|
+
error.publicDetails?.operationAccepted === true) ||
|
|
814
|
+
(flatPublicDetails !== null &&
|
|
815
|
+
typeof flatPublicDetails === 'object' &&
|
|
816
|
+
(flatPublicDetails as Record<string, unknown>).operationAccepted ===
|
|
817
|
+
true));
|
|
801
818
|
const shouldRetry =
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
819
|
+
!acceptedOperationNeedsRecovery &&
|
|
820
|
+
(providerOwnedRateLimit ||
|
|
821
|
+
attestedProviderDeadline ||
|
|
822
|
+
(retryDecision.retryable && input.attempt < retryDecision.attemptCap));
|
|
805
823
|
// In-attempt retry safety and later-run repairability are different
|
|
806
824
|
// decisions. A non-idempotent 5xx must not be repeated automatically inside
|
|
807
825
|
// this execution attempt, but an explicit later `plays run` must be able to
|
|
@@ -862,6 +880,9 @@ export function classifyToolExecuteHttpFailure(input: {
|
|
|
862
880
|
: TOOL_EXECUTE_RETRY_DELAY_FALLBACK_MS;
|
|
863
881
|
return {
|
|
864
882
|
...retryDecision,
|
|
883
|
+
...(acceptedOperationNeedsRecovery
|
|
884
|
+
? { retryable: false, reason: 'non_retryable_status' as const }
|
|
885
|
+
: {}),
|
|
865
886
|
error,
|
|
866
887
|
shouldRetry,
|
|
867
888
|
isRateLimit: input.status === 429,
|
|
@@ -710,7 +710,18 @@ function toV2RawToolOutputPathPreservingProviderData(path: string): string {
|
|
|
710
710
|
}
|
|
711
711
|
|
|
712
712
|
function candidateResultPaths(path: string): string[] {
|
|
713
|
+
// `result.data` is the public envelope. A following `data` belongs to the
|
|
714
|
+
// provider and must survive (e.g. QuickEnrich's result.data.data rows).
|
|
715
|
+
const normalized = String(path || '')
|
|
716
|
+
.trim()
|
|
717
|
+
.replace(/^\./, '');
|
|
718
|
+
const providerPath = normalized.startsWith('result.data.')
|
|
719
|
+
? `toolResponse.raw.${normalized.slice('result.data.'.length)}`
|
|
720
|
+
: normalized === 'result.data'
|
|
721
|
+
? 'toolResponse.raw'
|
|
722
|
+
: '';
|
|
713
723
|
const candidates = [
|
|
724
|
+
providerPath,
|
|
714
725
|
normalizeResultPath(path),
|
|
715
726
|
toV2RawToolOutputPathPreservingProviderData(path),
|
|
716
727
|
];
|
|
@@ -802,9 +813,29 @@ function acceptedTargetValue(
|
|
|
802
813
|
) {
|
|
803
814
|
return undefined;
|
|
804
815
|
}
|
|
816
|
+
if (target === 'email') return emailTargetValue(value) ?? undefined;
|
|
805
817
|
return isMeaningfulValue(value) ? value : undefined;
|
|
806
818
|
}
|
|
807
819
|
|
|
820
|
+
function emailTargetValue(value: unknown): string | null {
|
|
821
|
+
if (typeof value === 'string') {
|
|
822
|
+
const email = value.trim();
|
|
823
|
+
return /^[^\s@*]+@[^\s@*]+\.[^\s@*]+$/.test(email) ? email : null;
|
|
824
|
+
}
|
|
825
|
+
if (Array.isArray(value)) {
|
|
826
|
+
for (const entry of value) {
|
|
827
|
+
const email = emailTargetValue(entry);
|
|
828
|
+
if (email) return email;
|
|
829
|
+
}
|
|
830
|
+
} else if (isRecord(value)) {
|
|
831
|
+
for (const key of ['email', 'email_address', 'address', 'value']) {
|
|
832
|
+
const email = emailTargetValue(value[key]);
|
|
833
|
+
if (email) return email;
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
return null;
|
|
837
|
+
}
|
|
838
|
+
|
|
808
839
|
function getFirstMeaningfulValueAtPath(
|
|
809
840
|
root: unknown,
|
|
810
841
|
path: string,
|
|
@@ -12,12 +12,12 @@ import type { ToolExecutionErrorSchemaVersion } from './tool-execution-error';
|
|
|
12
12
|
import type { PlayDataset, PlayDatasetInput, PlayDatasetRow } from './dataset';
|
|
13
13
|
|
|
14
14
|
export const LEGACY_PLAY_AUTHORING_CONTRACT_EDITION = 1 as const;
|
|
15
|
-
//
|
|
16
|
-
//
|
|
15
|
+
// Edition 11 readers retain every CSV source row. Promote this writer in the
|
|
16
|
+
// follow-up PR after those readers are deployed everywhere.
|
|
17
17
|
export const PLAY_AUTHORING_CONTRACT_EDITION = 10 as const;
|
|
18
18
|
export const PLAY_AUTHORING_INPUT_SCHEMA_SNAPSHOT_EDITION = 3 as const;
|
|
19
19
|
export const SUPPORTED_PLAY_AUTHORING_CONTRACT_EDITIONS = [
|
|
20
|
-
1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
|
|
20
|
+
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
|
|
21
21
|
] as const;
|
|
22
22
|
|
|
23
23
|
export type PlayAuthoringContractEdition =
|
|
@@ -96,6 +96,13 @@ const PLAY_AUTHORING_CONTRACT_CHANGELOG_DETAILS = [
|
|
|
96
96
|
newWritesEnd: null,
|
|
97
97
|
readerRemoval: null,
|
|
98
98
|
},
|
|
99
|
+
{
|
|
100
|
+
changed:
|
|
101
|
+
'CSV datasets always use source row identity and process every input occurrence, even when key or rowIdentity: "key" is supplied. Editions 1–10 retain their admitted row identity and completed receipts; non-CSV datasets retain explicit key deduplication.',
|
|
102
|
+
compatibilityOwner: 'Plays Runtime',
|
|
103
|
+
newWritesEnd: null,
|
|
104
|
+
readerRemoval: null,
|
|
105
|
+
},
|
|
99
106
|
] as const;
|
|
100
107
|
|
|
101
108
|
/** Authoring types and runtime projection must select the same getter contract. */
|
|
@@ -105,6 +112,12 @@ export function playToolListGetterMode(
|
|
|
105
112
|
return edition >= 10 ? 'array' : 'dataset';
|
|
106
113
|
}
|
|
107
114
|
|
|
115
|
+
export function playCsvDatasetRowIdentity(
|
|
116
|
+
edition: PlayAuthoringContractEdition,
|
|
117
|
+
): 'source_row' | 'key' {
|
|
118
|
+
return edition >= 11 ? 'source_row' : 'key';
|
|
119
|
+
}
|
|
120
|
+
|
|
108
121
|
export const PLAY_AUTHORING_CONTRACT_CHANGELOG =
|
|
109
122
|
SUPPORTED_PLAY_AUTHORING_CONTRACT_EDITIONS.map((edition, index) => ({
|
|
110
123
|
edition,
|
|
@@ -1133,6 +1146,8 @@ export type PlayAuthoringDatasetDefinitionOptions<InputRow extends object> = {
|
|
|
1133
1146
|
export type PlayAuthoringDatasetRunOptions<InputRow extends object> = {
|
|
1134
1147
|
description?: string;
|
|
1135
1148
|
key?: PlayAuthoringDatasetRowKey<InputRow>;
|
|
1149
|
+
/** CSV defaults to source row identity. Use key only for intentional deduplication. */
|
|
1150
|
+
rowIdentity?: 'source_row' | 'key';
|
|
1136
1151
|
onRowError?: 'isolate' | 'fail';
|
|
1137
1152
|
mode?: 'upsert' | 'net_new';
|
|
1138
1153
|
/**
|
|
@@ -1147,6 +1162,7 @@ export type PlayAuthoringDatasetRunOptions<InputRow extends object> = {
|
|
|
1147
1162
|
export const PLAY_AUTHORING_DATASET_RUN_OPTION_FIELDS = [
|
|
1148
1163
|
'description',
|
|
1149
1164
|
'key',
|
|
1165
|
+
'rowIdentity',
|
|
1150
1166
|
'onRowError',
|
|
1151
1167
|
'mode',
|
|
1152
1168
|
'undrawnColumns',
|
|
@@ -2517,6 +2533,23 @@ export const PLAY_AUTHORING_FIELD_REGISTRY = {
|
|
|
2517
2533
|
errorMessage:
|
|
2518
2534
|
'ctx.dataset run key must be a non-empty field, field list, or key function.',
|
|
2519
2535
|
},
|
|
2536
|
+
'ctx.dataset.run.rowIdentity': {
|
|
2537
|
+
schema: Type.Union([Type.Literal('source_row'), Type.Literal('key')]),
|
|
2538
|
+
fixtures: {
|
|
2539
|
+
valid: 'source_row',
|
|
2540
|
+
invalid: 'dedupe',
|
|
2541
|
+
absent: undefined,
|
|
2542
|
+
unresolved: { expression: 'rowIdentity' },
|
|
2543
|
+
edition1: 'key',
|
|
2544
|
+
},
|
|
2545
|
+
referenceType: "'source_row' | 'key'",
|
|
2546
|
+
required: false,
|
|
2547
|
+
resolution: 'static-when-present',
|
|
2548
|
+
issueCode: 'play_authoring_dataset_option_invalid',
|
|
2549
|
+
description:
|
|
2550
|
+
'Select source_row to process every input occurrence. CSV datasets default to source_row in edition 11; earlier editions retain key identity. Select key only to intentionally deduplicate business keys.',
|
|
2551
|
+
errorMessage: 'ctx.dataset run rowIdentity must be "source_row" or "key".',
|
|
2552
|
+
},
|
|
2520
2553
|
'ctx.dataset.run.onRowError': {
|
|
2521
2554
|
schema: Type.Union([Type.Literal('isolate'), Type.Literal('fail')]),
|
|
2522
2555
|
fixtures: {
|
|
@@ -3315,7 +3348,7 @@ export const PLAY_AUTHORING_CLOUD_TYPE_DECLARATIONS = [
|
|
|
3315
3348
|
'export type StepProgramOutput<TProgram> = TProgram extends StepProgram<unknown, infer Output, unknown> ? Output : never;',
|
|
3316
3349
|
'export type DatasetRowKey<InputRow extends object> = (keyof InputRow & string) | readonly (keyof InputRow & string)[] | ((row: InputRow, index: number) => string | number | readonly unknown[]);',
|
|
3317
3350
|
'export type DatasetDefinitionOptions<InputRow extends object> = { key?: DatasetRowKey<InputRow> };',
|
|
3318
|
-
`export type DatasetRunOptions<InputRow extends object> = { description?: ${cloudReferenceType('ctx.dataset.run.description')}; key?: DatasetRowKey<InputRow>; onRowError?: ${cloudReferenceType('ctx.dataset.run.onRowError')}; mode?: ${cloudReferenceType('ctx.dataset.run.mode')}; undrawnColumns?: ${cloudReferenceType('ctx.dataset.run.undrawnColumns')} };`,
|
|
3351
|
+
`export type DatasetRunOptions<InputRow extends object> = { description?: ${cloudReferenceType('ctx.dataset.run.description')}; key?: DatasetRowKey<InputRow>; rowIdentity?: ${cloudReferenceType('ctx.dataset.run.rowIdentity')}; onRowError?: ${cloudReferenceType('ctx.dataset.run.onRowError')}; mode?: ${cloudReferenceType('ctx.dataset.run.mode')}; undrawnColumns?: ${cloudReferenceType('ctx.dataset.run.undrawnColumns')} };`,
|
|
3319
3352
|
'export type DatasetBuilder<InputRow extends object, OutputRow extends object> = {',
|
|
3320
3353
|
' withColumn<Name extends string, Value>(name: Name, resolver: ColumnResolver<OutputRow, Value>): DatasetBuilder<InputRow, OutputRow & Record<Name, Value>>;',
|
|
3321
3354
|
' withColumn<Name extends string, Value>(name: Name, definition: DatasetColumnDefinition<OutputRow, Value> & { readonly runIf: (row: OutputRow, index: number) => boolean | Promise<boolean> }): DatasetBuilder<InputRow, OutputRow & Record<Name, Value | null>>;',
|
|
@@ -4,6 +4,118 @@ import type { PlayDatasetColumnTypes } from '../play-data-plane/contracts';
|
|
|
4
4
|
const PLAY_DATASET_BRAND = Symbol.for('deepline.play.dataset');
|
|
5
5
|
const NODE_INSPECT_CUSTOM = Symbol.for('nodejs.util.inspect.custom');
|
|
6
6
|
const residentRowsByDataset = new WeakMap<object, readonly unknown[]>();
|
|
7
|
+
// Source ordinals are execution provenance, never customer columns. Weak
|
|
8
|
+
// references keep streaming sources bounded and transforms preserve ordinals.
|
|
9
|
+
type PlayDatasetSourceRowIdentity = Readonly<{
|
|
10
|
+
datasetId: string;
|
|
11
|
+
rowIndex: number;
|
|
12
|
+
}>;
|
|
13
|
+
const sourceRowIdentityByRow = new WeakMap<
|
|
14
|
+
object,
|
|
15
|
+
PlayDatasetSourceRowIdentity
|
|
16
|
+
>();
|
|
17
|
+
const sourceRowIdentitiesByRows = new WeakMap<
|
|
18
|
+
readonly unknown[],
|
|
19
|
+
readonly (PlayDatasetSourceRowIdentity | undefined)[]
|
|
20
|
+
>();
|
|
21
|
+
type PlayDatasetSourceOccurrence<T> = {
|
|
22
|
+
row: T;
|
|
23
|
+
sourceIdentity?: PlayDatasetSourceRowIdentity;
|
|
24
|
+
};
|
|
25
|
+
const sourceOccurrencesByDataset = new WeakMap<
|
|
26
|
+
object,
|
|
27
|
+
() => AsyncIterable<PlayDatasetSourceOccurrence<unknown>>
|
|
28
|
+
>();
|
|
29
|
+
|
|
30
|
+
export function setPlayDatasetSourceRowIdentity<T>(
|
|
31
|
+
row: T,
|
|
32
|
+
identity: Readonly<{ datasetId: string; rowIndex: number }>,
|
|
33
|
+
): T {
|
|
34
|
+
if (row && typeof row === 'object') sourceRowIdentityByRow.set(row, identity);
|
|
35
|
+
return row;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function getPlayDatasetSourceRowIdentity(
|
|
39
|
+
row: unknown,
|
|
40
|
+
): Readonly<{ datasetId: string; rowIndex: number }> | undefined {
|
|
41
|
+
return row && typeof row === 'object'
|
|
42
|
+
? sourceRowIdentityByRow.get(row)
|
|
43
|
+
: undefined;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Container provenance distinguishes occurrences even when a mapper returns a shared typed value. */
|
|
47
|
+
export function getPlayDatasetSourceRowIdentityAt(
|
|
48
|
+
rows: readonly unknown[],
|
|
49
|
+
index: number,
|
|
50
|
+
): PlayDatasetSourceRowIdentity | undefined {
|
|
51
|
+
const identities = sourceRowIdentitiesByRows.get(rows);
|
|
52
|
+
return identities
|
|
53
|
+
? identities[index]
|
|
54
|
+
: getPlayDatasetSourceRowIdentity(rows[index]);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function copyPlayDatasetSourceRowIdentity<T>(
|
|
58
|
+
source: unknown,
|
|
59
|
+
target: T,
|
|
60
|
+
): T {
|
|
61
|
+
const identity = getPlayDatasetSourceRowIdentity(source);
|
|
62
|
+
return identity ? setPlayDatasetSourceRowIdentity(target, identity) : target;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** A mapper may return the same object for several physical source records. */
|
|
66
|
+
function copySourceOccurrenceToMappedValue<T>(
|
|
67
|
+
identity: PlayDatasetSourceRowIdentity | undefined,
|
|
68
|
+
mapped: T,
|
|
69
|
+
): T {
|
|
70
|
+
if (!identity || !mapped || typeof mapped !== 'object') return mapped;
|
|
71
|
+
const prototype = Object.getPrototypeOf(mapped);
|
|
72
|
+
// Plain row values can carry provenance on a distinct execution object.
|
|
73
|
+
// Typed values retain their mapper result and internal slots; their distinct
|
|
74
|
+
// occurrences travel in the iterator/container sidecar instead.
|
|
75
|
+
const occurrence = (
|
|
76
|
+
Array.isArray(mapped)
|
|
77
|
+
? Object.defineProperties([], Object.getOwnPropertyDescriptors(mapped))
|
|
78
|
+
: prototype === Object.prototype || prototype === null
|
|
79
|
+
? Object.create(prototype, Object.getOwnPropertyDescriptors(mapped))
|
|
80
|
+
: mapped
|
|
81
|
+
) as T;
|
|
82
|
+
return setPlayDatasetSourceRowIdentity(occurrence, identity);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
async function* iterateSourceOccurrences<T>(
|
|
86
|
+
input: PlayDatasetInput<T>,
|
|
87
|
+
): AsyncIterable<PlayDatasetSourceOccurrence<T>> {
|
|
88
|
+
if (isPlayDataset(input)) {
|
|
89
|
+
const occurrences = sourceOccurrencesByDataset.get(input);
|
|
90
|
+
if (occurrences) {
|
|
91
|
+
yield* occurrences() as AsyncIterable<PlayDatasetSourceOccurrence<T>>;
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
for await (const row of input)
|
|
95
|
+
yield { row, sourceIdentity: getPlayDatasetSourceRowIdentity(row) };
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
if (Array.isArray(input)) {
|
|
99
|
+
for (let index = 0; index < input.length; index += 1) {
|
|
100
|
+
yield {
|
|
101
|
+
row: input[index]!,
|
|
102
|
+
sourceIdentity: getPlayDatasetSourceRowIdentityAt(input, index),
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
if (
|
|
108
|
+
input != null &&
|
|
109
|
+
typeof input === 'object' &&
|
|
110
|
+
Symbol.asyncIterator in input
|
|
111
|
+
) {
|
|
112
|
+
for await (const row of input as AsyncIterable<T>)
|
|
113
|
+
yield { row, sourceIdentity: getPlayDatasetSourceRowIdentity(row) };
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
for (const row of input as Iterable<T>)
|
|
117
|
+
yield { row, sourceIdentity: getPlayDatasetSourceRowIdentity(row) };
|
|
118
|
+
}
|
|
7
119
|
const DEFAULT_MATERIALIZE_LIMIT = 10_000;
|
|
8
120
|
export const PLAY_DATASET_EXECUTION_PAGE_ROWS = 1_000;
|
|
9
121
|
export const PLAY_DATASET_EXECUTION_PAGE_BYTES = 64 * 1024 * 1024;
|
|
@@ -32,6 +144,14 @@ export type PlayDatasetWorkProgressSummary = {
|
|
|
32
144
|
pending: number;
|
|
33
145
|
failed: number;
|
|
34
146
|
degraded?: boolean;
|
|
147
|
+
/** Fixed-shape source/output accounting; does not redefine legacy totals. */
|
|
148
|
+
cardinality?: {
|
|
149
|
+
sourceRows: number;
|
|
150
|
+
uniqueInputRows: number;
|
|
151
|
+
duplicateOccurrences: number;
|
|
152
|
+
outputRows: number;
|
|
153
|
+
rowIdentity: 'source_row' | 'key';
|
|
154
|
+
};
|
|
35
155
|
duplicates?: {
|
|
36
156
|
exact?: number;
|
|
37
157
|
semantic?: number;
|
|
@@ -658,7 +778,9 @@ function createTransformedPlayDataset<T, U>(
|
|
|
658
778
|
options?.sourceLabel ??
|
|
659
779
|
`${source.sourceLabel ?? source.tableNamespace ?? source.datasetId}.${transform.kind}`;
|
|
660
780
|
|
|
661
|
-
const
|
|
781
|
+
const iterateOccurrences = async function* (): AsyncIterable<
|
|
782
|
+
PlayDatasetSourceOccurrence<U>
|
|
783
|
+
> {
|
|
662
784
|
if (transform.kind === 'slice') {
|
|
663
785
|
const bounds = normalizeSliceBounds({
|
|
664
786
|
start: transform.start,
|
|
@@ -666,10 +788,10 @@ function createTransformedPlayDataset<T, U>(
|
|
|
666
788
|
count: await source.count(),
|
|
667
789
|
});
|
|
668
790
|
let index = 0;
|
|
669
|
-
for await (const
|
|
791
|
+
for await (const occurrence of iterateSourceOccurrences(source)) {
|
|
670
792
|
if (index >= bounds.end) break;
|
|
671
793
|
if (index >= bounds.start) {
|
|
672
|
-
yield
|
|
794
|
+
yield occurrence as unknown as PlayDatasetSourceOccurrence<U>;
|
|
673
795
|
}
|
|
674
796
|
index += 1;
|
|
675
797
|
}
|
|
@@ -678,27 +800,42 @@ function createTransformedPlayDataset<T, U>(
|
|
|
678
800
|
|
|
679
801
|
let inputIndex = 0;
|
|
680
802
|
let outputIndex = 0;
|
|
681
|
-
for await (const row of
|
|
803
|
+
for await (const { row, sourceIdentity } of iterateSourceOccurrences(
|
|
804
|
+
source,
|
|
805
|
+
)) {
|
|
682
806
|
if (transform.kind === 'filter') {
|
|
683
807
|
if (await transform.predicate(row, inputIndex)) {
|
|
684
|
-
yield row as unknown as U;
|
|
808
|
+
yield { row: row as unknown as U, sourceIdentity };
|
|
685
809
|
outputIndex += 1;
|
|
686
810
|
}
|
|
687
811
|
} else {
|
|
688
|
-
yield
|
|
812
|
+
yield {
|
|
813
|
+
row: copySourceOccurrenceToMappedValue(
|
|
814
|
+
sourceIdentity,
|
|
815
|
+
await transform.mapper(row, outputIndex),
|
|
816
|
+
),
|
|
817
|
+
sourceIdentity,
|
|
818
|
+
};
|
|
689
819
|
outputIndex += 1;
|
|
690
820
|
}
|
|
691
821
|
inputIndex += 1;
|
|
692
822
|
}
|
|
693
823
|
};
|
|
694
824
|
|
|
825
|
+
const iterate = async function* (): AsyncIterable<U> {
|
|
826
|
+
for await (const { row } of iterateOccurrences()) yield row;
|
|
827
|
+
};
|
|
828
|
+
|
|
695
829
|
const collect = async (limit?: number): Promise<U[]> => {
|
|
696
830
|
const rows: U[] = [];
|
|
831
|
+
const identities: (PlayDatasetSourceRowIdentity | undefined)[] = [];
|
|
832
|
+
sourceRowIdentitiesByRows.set(rows, identities);
|
|
697
833
|
const boundedLimit =
|
|
698
834
|
limit === undefined ? undefined : Math.max(0, Math.floor(limit));
|
|
699
835
|
if (boundedLimit === 0) return rows;
|
|
700
|
-
for await (const row of
|
|
836
|
+
for await (const { row, sourceIdentity } of iterateOccurrences()) {
|
|
701
837
|
rows.push(row);
|
|
838
|
+
identities.push(sourceIdentity);
|
|
702
839
|
if (boundedLimit !== undefined && rows.length >= boundedLimit) break;
|
|
703
840
|
}
|
|
704
841
|
return rows;
|
|
@@ -722,7 +859,7 @@ function createTransformedPlayDataset<T, U>(
|
|
|
722
859
|
return total;
|
|
723
860
|
};
|
|
724
861
|
|
|
725
|
-
|
|
862
|
+
const dataset = createDeferredPlayDataset({
|
|
726
863
|
datasetKind: source.datasetKind,
|
|
727
864
|
datasetId: transformDatasetId({
|
|
728
865
|
source: source as PlayDataset<unknown>,
|
|
@@ -747,6 +884,13 @@ function createTransformedPlayDataset<T, U>(
|
|
|
747
884
|
}) as AsyncIterable<U>,
|
|
748
885
|
},
|
|
749
886
|
});
|
|
887
|
+
sourceOccurrencesByDataset.set(
|
|
888
|
+
dataset,
|
|
889
|
+
iterateOccurrences as () => AsyncIterable<
|
|
890
|
+
PlayDatasetSourceOccurrence<unknown>
|
|
891
|
+
>,
|
|
892
|
+
);
|
|
893
|
+
return dataset;
|
|
750
894
|
}
|
|
751
895
|
|
|
752
896
|
export function createDeferredPlayDataset<T>(input: {
|
|
@@ -922,10 +1066,15 @@ export async function* iteratePlayDatasetInputPages<T>(
|
|
|
922
1066
|
: DATASET_UTF8_ENCODER.encode(serialized).byteLength;
|
|
923
1067
|
});
|
|
924
1068
|
let page: T[] = [];
|
|
1069
|
+
let pageIdentities: (PlayDatasetSourceRowIdentity | undefined)[] = [];
|
|
1070
|
+
sourceRowIdentitiesByRows.set(page, pageIdentities);
|
|
925
1071
|
let pageBytes = 0;
|
|
926
1072
|
let offset = 0;
|
|
927
1073
|
let index = 0;
|
|
928
|
-
const pushRow = (
|
|
1074
|
+
const pushRow = (
|
|
1075
|
+
row: T,
|
|
1076
|
+
sourceIdentity: PlayDatasetSourceRowIdentity | undefined,
|
|
1077
|
+
): Array<{ rows: T[]; offset: number }> => {
|
|
929
1078
|
options?.onRow?.(row, index);
|
|
930
1079
|
index += 1;
|
|
931
1080
|
const rowBytes = Math.max(0, Math.ceil(estimateRowBytes(row)));
|
|
@@ -934,14 +1083,19 @@ export async function* iteratePlayDatasetInputPages<T>(
|
|
|
934
1083
|
ready.push({ rows: page, offset });
|
|
935
1084
|
offset += page.length;
|
|
936
1085
|
page = [];
|
|
1086
|
+
pageIdentities = [];
|
|
1087
|
+
sourceRowIdentitiesByRows.set(page, pageIdentities);
|
|
937
1088
|
pageBytes = 0;
|
|
938
1089
|
}
|
|
939
1090
|
page.push(row);
|
|
1091
|
+
pageIdentities.push(sourceIdentity);
|
|
940
1092
|
pageBytes += rowBytes;
|
|
941
1093
|
if (page.length >= pageSize || pageBytes >= maxPageBytes) {
|
|
942
1094
|
ready.push({ rows: page, offset });
|
|
943
1095
|
offset += page.length;
|
|
944
1096
|
page = [];
|
|
1097
|
+
pageIdentities = [];
|
|
1098
|
+
sourceRowIdentitiesByRows.set(page, pageIdentities);
|
|
945
1099
|
pageBytes = 0;
|
|
946
1100
|
}
|
|
947
1101
|
return ready;
|
|
@@ -952,48 +1106,15 @@ export async function* iteratePlayDatasetInputPages<T>(
|
|
|
952
1106
|
const finalPage = page;
|
|
953
1107
|
const finalOffset = offset;
|
|
954
1108
|
page = [];
|
|
1109
|
+
pageIdentities = [];
|
|
1110
|
+
sourceRowIdentitiesByRows.set(page, pageIdentities);
|
|
955
1111
|
pageBytes = 0;
|
|
956
1112
|
offset += finalPage.length;
|
|
957
1113
|
return { rows: finalPage, offset: finalOffset };
|
|
958
1114
|
};
|
|
959
1115
|
|
|
960
|
-
const
|
|
961
|
-
for (const ready of pushRow(row)) yield ready;
|
|
962
|
-
};
|
|
963
|
-
|
|
964
|
-
if (isPlayDataset(input)) {
|
|
965
|
-
for await (const row of input) {
|
|
966
|
-
yield* emitRow(row);
|
|
967
|
-
}
|
|
968
|
-
const finalPage = flush();
|
|
969
|
-
if (finalPage) yield finalPage;
|
|
970
|
-
return;
|
|
971
|
-
}
|
|
972
|
-
|
|
973
|
-
if (Array.isArray(input)) {
|
|
974
|
-
for (const row of input) {
|
|
975
|
-
yield* emitRow(row);
|
|
976
|
-
}
|
|
977
|
-
const finalPage = flush();
|
|
978
|
-
if (finalPage) yield finalPage;
|
|
979
|
-
return;
|
|
980
|
-
}
|
|
981
|
-
|
|
982
|
-
if (
|
|
983
|
-
input != null &&
|
|
984
|
-
typeof input === 'object' &&
|
|
985
|
-
Symbol.asyncIterator in input
|
|
986
|
-
) {
|
|
987
|
-
for await (const row of input as AsyncIterable<T>) {
|
|
988
|
-
yield* emitRow(row);
|
|
989
|
-
}
|
|
990
|
-
const finalPage = flush();
|
|
991
|
-
if (finalPage) yield finalPage;
|
|
992
|
-
return;
|
|
993
|
-
}
|
|
994
|
-
|
|
995
|
-
for (const row of input as Iterable<T>) {
|
|
996
|
-
yield* emitRow(row);
|
|
1116
|
+
for await (const { row, sourceIdentity } of iterateSourceOccurrences(input)) {
|
|
1117
|
+
for (const ready of pushRow(row, sourceIdentity)) yield ready;
|
|
997
1118
|
}
|
|
998
1119
|
const finalPage = flush();
|
|
999
1120
|
if (finalPage) yield finalPage;
|
|
@@ -1003,41 +1124,13 @@ export async function materializePlayDatasetInput<T>(
|
|
|
1003
1124
|
input: PlayDatasetInput<T>,
|
|
1004
1125
|
options?: MaterializePlayDatasetInputOptions<T>,
|
|
1005
1126
|
): Promise<T[]> {
|
|
1006
|
-
const
|
|
1127
|
+
const rows: T[] = [];
|
|
1128
|
+
const identities: (PlayDatasetSourceRowIdentity | undefined)[] = [];
|
|
1129
|
+
sourceRowIdentitiesByRows.set(rows, identities);
|
|
1130
|
+
for await (const { row, sourceIdentity } of iterateSourceOccurrences(input)) {
|
|
1007
1131
|
options?.onRow?.(row, rows.length);
|
|
1008
1132
|
rows.push(row);
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
if (isPlayDataset(input)) {
|
|
1012
|
-
const rows: T[] = [];
|
|
1013
|
-
for await (const row of input) {
|
|
1014
|
-
pushRow(rows, row);
|
|
1015
|
-
}
|
|
1016
|
-
return rows;
|
|
1017
|
-
}
|
|
1018
|
-
|
|
1019
|
-
if (Array.isArray(input)) {
|
|
1020
|
-
const rows: T[] = [];
|
|
1021
|
-
for (const row of input) {
|
|
1022
|
-
pushRow(rows, row);
|
|
1023
|
-
}
|
|
1024
|
-
return rows;
|
|
1025
|
-
}
|
|
1026
|
-
|
|
1027
|
-
const rows: T[] = [];
|
|
1028
|
-
if (
|
|
1029
|
-
input != null &&
|
|
1030
|
-
typeof input === 'object' &&
|
|
1031
|
-
Symbol.asyncIterator in input
|
|
1032
|
-
) {
|
|
1033
|
-
for await (const row of input as AsyncIterable<T>) {
|
|
1034
|
-
pushRow(rows, row);
|
|
1035
|
-
}
|
|
1036
|
-
return rows;
|
|
1037
|
-
}
|
|
1038
|
-
|
|
1039
|
-
for (const row of input as Iterable<T>) {
|
|
1040
|
-
pushRow(rows, row);
|
|
1133
|
+
identities.push(sourceIdentity);
|
|
1041
1134
|
}
|
|
1042
1135
|
return rows;
|
|
1043
1136
|
}
|