deepline 0.1.62 → 0.1.64
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/cli/index.js +702 -339
- package/dist/cli/index.mjs +727 -348
- package/dist/index.d.mts +7 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.js +77 -51
- package/dist/index.mjs +77 -51
- package/dist/repo/apps/play-runner-workers/src/coordinator-entry.ts +9 -10
- package/dist/repo/apps/play-runner-workers/src/entry.ts +55 -0
- package/dist/repo/apps/play-runner-workers/src/runtime/dataset-handles.ts +36 -27
- package/dist/repo/apps/play-runner-workers/src/runtime/tool-http-errors.ts +5 -2
- package/dist/repo/sdk/src/client.ts +71 -63
- package/dist/repo/sdk/src/errors.ts +5 -1
- package/dist/repo/sdk/src/http.ts +25 -17
- package/dist/repo/sdk/src/plays/local-file-discovery.ts +93 -24
- package/dist/repo/sdk/src/release.ts +2 -2
- package/dist/repo/sdk/src/tool-output.ts +40 -20
- package/dist/repo/shared_libs/play-runtime/batch-runtime.ts +10 -3
- package/dist/repo/shared_libs/play-runtime/batching-types.ts +15 -4
- package/dist/repo/shared_libs/play-runtime/coordinator-headers.ts +2 -1
- package/dist/repo/shared_libs/play-runtime/dedup-backend.ts +0 -0
- package/dist/repo/shared_libs/play-runtime/default-batch-strategies.ts +3 -4
- package/dist/repo/shared_libs/play-runtime/run-failure.ts +1 -3
- package/dist/repo/shared_libs/play-runtime/step-lifecycle-tracker.ts +4 -1
- package/dist/repo/shared_libs/play-runtime/tool-batch-executor.ts +4 -1
- package/dist/repo/shared_libs/play-runtime/tool-result.ts +28 -15
- package/dist/repo/shared_libs/plays/dataset.ts +10 -11
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -1206,7 +1206,7 @@ declare class DeeplineClient {
|
|
|
1206
1206
|
* artifactStorageKey: 'plays/v1/orgs/acme/plays/my-play/artifacts/playgraph_abc123.json',
|
|
1207
1207
|
* });
|
|
1208
1208
|
* ```
|
|
1209
|
-
|
|
1209
|
+
*/
|
|
1210
1210
|
startPlayRun(request: StartPlayRunRequest): Promise<PlayRunStart>;
|
|
1211
1211
|
startPlayRunStream(request: StartPlayRunRequest, options?: {
|
|
1212
1212
|
signal?: AbortSignal;
|
|
@@ -1881,6 +1881,12 @@ type ToolResultExtractorDescriptor = {
|
|
|
1881
1881
|
paths: readonly string[];
|
|
1882
1882
|
transforms?: readonly string[];
|
|
1883
1883
|
enum?: readonly string[];
|
|
1884
|
+
overrides?: readonly ToolResultExtractorOverride[];
|
|
1885
|
+
};
|
|
1886
|
+
type ToolResultExtractorOverride = {
|
|
1887
|
+
paths: readonly string[];
|
|
1888
|
+
equals?: string | number | boolean | null;
|
|
1889
|
+
value: string | number | boolean | null;
|
|
1884
1890
|
};
|
|
1885
1891
|
type ToolResultTargetAccessor<T = unknown> = ToolResultTargetMetadata & {
|
|
1886
1892
|
get(): T | null;
|
package/dist/index.d.ts
CHANGED
|
@@ -1206,7 +1206,7 @@ declare class DeeplineClient {
|
|
|
1206
1206
|
* artifactStorageKey: 'plays/v1/orgs/acme/plays/my-play/artifacts/playgraph_abc123.json',
|
|
1207
1207
|
* });
|
|
1208
1208
|
* ```
|
|
1209
|
-
|
|
1209
|
+
*/
|
|
1210
1210
|
startPlayRun(request: StartPlayRunRequest): Promise<PlayRunStart>;
|
|
1211
1211
|
startPlayRunStream(request: StartPlayRunRequest, options?: {
|
|
1212
1212
|
signal?: AbortSignal;
|
|
@@ -1881,6 +1881,12 @@ type ToolResultExtractorDescriptor = {
|
|
|
1881
1881
|
paths: readonly string[];
|
|
1882
1882
|
transforms?: readonly string[];
|
|
1883
1883
|
enum?: readonly string[];
|
|
1884
|
+
overrides?: readonly ToolResultExtractorOverride[];
|
|
1885
|
+
};
|
|
1886
|
+
type ToolResultExtractorOverride = {
|
|
1887
|
+
paths: readonly string[];
|
|
1888
|
+
equals?: string | number | boolean | null;
|
|
1889
|
+
value: string | number | boolean | null;
|
|
1884
1890
|
};
|
|
1885
1891
|
type ToolResultTargetAccessor<T = unknown> = ToolResultTargetMetadata & {
|
|
1886
1892
|
get(): T | null;
|
package/dist/index.js
CHANGED
|
@@ -88,7 +88,11 @@ var RateLimitError = class extends DeeplineError {
|
|
|
88
88
|
/** Milliseconds to wait before retrying, from the `Retry-After` response header. Defaults to 5000. */
|
|
89
89
|
retryAfterMs;
|
|
90
90
|
constructor(retryAfterMs = 5e3, message) {
|
|
91
|
-
super(
|
|
91
|
+
super(
|
|
92
|
+
message ?? `Rate limited. Retry after ${retryAfterMs}ms.`,
|
|
93
|
+
429,
|
|
94
|
+
"RATE_LIMIT"
|
|
95
|
+
);
|
|
92
96
|
this.name = "RateLimitError";
|
|
93
97
|
this.retryAfterMs = retryAfterMs;
|
|
94
98
|
}
|
|
@@ -232,10 +236,10 @@ function resolveConfig(options) {
|
|
|
232
236
|
|
|
233
237
|
// src/release.ts
|
|
234
238
|
var SDK_RELEASE = {
|
|
235
|
-
version: "0.1.
|
|
239
|
+
version: "0.1.64",
|
|
236
240
|
apiContract: "2026-05-play-bootstrap-dataset-summary",
|
|
237
241
|
supportPolicy: {
|
|
238
|
-
latest: "0.1.
|
|
242
|
+
latest: "0.1.64",
|
|
239
243
|
minimumSupported: "0.1.53",
|
|
240
244
|
deprecatedBelow: "0.1.53"
|
|
241
245
|
}
|
|
@@ -258,7 +262,7 @@ var HttpClient = class {
|
|
|
258
262
|
config;
|
|
259
263
|
authHeaders(extra) {
|
|
260
264
|
const headers = {
|
|
261
|
-
|
|
265
|
+
Authorization: `Bearer ${this.config.apiKey}`,
|
|
262
266
|
"User-Agent": `deepline-ts-sdk/${SDK_VERSION}`,
|
|
263
267
|
"X-Deepline-SDK-Version": SDK_VERSION,
|
|
264
268
|
"X-Deepline-API-Contract": SDK_API_CONTRACT,
|
|
@@ -941,31 +945,34 @@ var DeeplineClient = class {
|
|
|
941
945
|
* artifactStorageKey: 'plays/v1/orgs/acme/plays/my-play/artifacts/playgraph_abc123.json',
|
|
942
946
|
* });
|
|
943
947
|
* ```
|
|
944
|
-
|
|
948
|
+
*/
|
|
945
949
|
async startPlayRun(request) {
|
|
946
|
-
const response = await this.http.post(
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
950
|
+
const response = await this.http.post(
|
|
951
|
+
"/api/v2/plays/run",
|
|
952
|
+
{
|
|
953
|
+
...request.name ? { name: request.name } : {},
|
|
954
|
+
...request.revisionId ? { revisionId: request.revisionId } : {},
|
|
955
|
+
...request.artifactStorageKey ? { artifactStorageKey: request.artifactStorageKey } : {},
|
|
956
|
+
...request.sourceCode ? { sourceCode: request.sourceCode } : {},
|
|
957
|
+
...request.sourceFiles ? { sourceFiles: request.sourceFiles } : {},
|
|
958
|
+
..."staticPipeline" in request ? { staticPipeline: request.staticPipeline } : {},
|
|
959
|
+
...request.artifactHash ? { artifactHash: request.artifactHash } : {},
|
|
960
|
+
...request.graphHash ? { graphHash: request.graphHash } : {},
|
|
961
|
+
...request.runtimeArtifact ? { runtimeArtifact: request.runtimeArtifact } : {},
|
|
962
|
+
...request.compilerManifest ? { compilerManifest: request.compilerManifest } : {},
|
|
963
|
+
...request.inputFileUpload ? { inputFileUpload: request.inputFileUpload } : {},
|
|
964
|
+
...request.packagedFileUploads?.length ? { packagedFileUploads: request.packagedFileUploads } : {},
|
|
965
|
+
...request.input ? { input: request.input } : {},
|
|
966
|
+
...request.inputFile ? { inputFile: request.inputFile } : {},
|
|
967
|
+
...request.packagedFiles?.length ? { packagedFiles: request.packagedFiles } : {},
|
|
968
|
+
...request.force ? { force: true } : {},
|
|
969
|
+
...typeof request.waitForCompletionMs === "number" ? { waitForCompletionMs: request.waitForCompletionMs } : {},
|
|
970
|
+
// Profile selection is the API's job, not the CLI's. The server
|
|
971
|
+
// hardcodes workers_edge as the default; tests that want a
|
|
972
|
+
// different profile pass `request.profile` explicitly.
|
|
973
|
+
...request.profile ? { profile: request.profile } : {}
|
|
974
|
+
}
|
|
975
|
+
);
|
|
969
976
|
return normalizePlayRunStart(response);
|
|
970
977
|
}
|
|
971
978
|
async *startPlayRunStream(request, options) {
|
|
@@ -1217,10 +1224,7 @@ var DeeplineClient = class {
|
|
|
1217
1224
|
}
|
|
1218
1225
|
return formData;
|
|
1219
1226
|
};
|
|
1220
|
-
const response = await this.http.postFormData(
|
|
1221
|
-
"/api/v2/plays/files/stage",
|
|
1222
|
-
buildFormData
|
|
1223
|
-
);
|
|
1227
|
+
const response = await this.http.postFormData("/api/v2/plays/files/stage", buildFormData);
|
|
1224
1228
|
return response.files;
|
|
1225
1229
|
}
|
|
1226
1230
|
async resolveStagedPlayFiles(files) {
|
|
@@ -1667,7 +1671,9 @@ var DeeplineClient = class {
|
|
|
1667
1671
|
}
|
|
1668
1672
|
options?.onProgress?.(status);
|
|
1669
1673
|
if (TERMINAL_PLAY_STATUSES.has(status.status)) {
|
|
1670
|
-
const finalStatus = await this.getPlayStatus(
|
|
1674
|
+
const finalStatus = await this.getPlayStatus(
|
|
1675
|
+
status.runId || workflowId
|
|
1676
|
+
).catch(() => status);
|
|
1671
1677
|
return playRunResultFromStatus(finalStatus, start, workflowId);
|
|
1672
1678
|
}
|
|
1673
1679
|
}
|
|
@@ -2073,9 +2079,7 @@ function deriveListKeys(input) {
|
|
|
2073
2079
|
return keys;
|
|
2074
2080
|
}
|
|
2075
2081
|
const listPrefix = input.listPath.replace(/\[\d+\]$/, "");
|
|
2076
|
-
for (const [target, paths] of Object.entries(
|
|
2077
|
-
input.targetGetters ?? {}
|
|
2078
|
-
)) {
|
|
2082
|
+
for (const [target, paths] of Object.entries(input.targetGetters ?? {})) {
|
|
2079
2083
|
for (const rawPath of paths) {
|
|
2080
2084
|
const path = String(rawPath || "").trim().replace(/^\./, "");
|
|
2081
2085
|
if (!path) continue;
|
|
@@ -2121,21 +2125,20 @@ function buildTargets(result, extractors, targetGetters) {
|
|
|
2121
2125
|
for (const [target, descriptor] of Object.entries(extractors ?? {})) {
|
|
2122
2126
|
const fromExtractor = findFirstTargetByPath(result, descriptor.paths);
|
|
2123
2127
|
if (!fromExtractor) continue;
|
|
2128
|
+
const transformed = coerceToEnum(
|
|
2129
|
+
applyExtractorTransforms(fromExtractor.value, descriptor),
|
|
2130
|
+
descriptor
|
|
2131
|
+
);
|
|
2132
|
+
const override = findExtractorOverride(result, descriptor);
|
|
2124
2133
|
targets[target] = {
|
|
2125
2134
|
path: fromExtractor.path,
|
|
2126
|
-
value:
|
|
2127
|
-
applyExtractorTransforms(fromExtractor.value, descriptor),
|
|
2128
|
-
descriptor
|
|
2129
|
-
)
|
|
2135
|
+
value: override?.value ?? transformed
|
|
2130
2136
|
};
|
|
2131
2137
|
}
|
|
2132
2138
|
const metadataTargets = new Set(Object.keys(targetGetters ?? {}));
|
|
2133
2139
|
for (const target of metadataTargets) {
|
|
2134
2140
|
if (targets[target]) continue;
|
|
2135
|
-
const fromMetadata = findFirstTargetByPath(
|
|
2136
|
-
result,
|
|
2137
|
-
targetGetters?.[target]
|
|
2138
|
-
);
|
|
2141
|
+
const fromMetadata = findFirstTargetByPath(result, targetGetters?.[target]);
|
|
2139
2142
|
if (fromMetadata) {
|
|
2140
2143
|
targets[target] = fromMetadata;
|
|
2141
2144
|
continue;
|
|
@@ -2152,6 +2155,19 @@ function buildTargets(result, extractors, targetGetters) {
|
|
|
2152
2155
|
}
|
|
2153
2156
|
return targets;
|
|
2154
2157
|
}
|
|
2158
|
+
function findExtractorOverride(result, descriptor) {
|
|
2159
|
+
for (const override of descriptor.overrides ?? []) {
|
|
2160
|
+
const expected = Object.prototype.hasOwnProperty.call(override, "equals") ? override.equals : true;
|
|
2161
|
+
for (const path of override.paths) {
|
|
2162
|
+
const match = findFirstTargetByPath(result, [path]);
|
|
2163
|
+
if (!match) continue;
|
|
2164
|
+
if (match.value === expected) {
|
|
2165
|
+
return { value: override.value };
|
|
2166
|
+
}
|
|
2167
|
+
}
|
|
2168
|
+
}
|
|
2169
|
+
return null;
|
|
2170
|
+
}
|
|
2155
2171
|
function buildLists(resolved, metadata) {
|
|
2156
2172
|
const lists = {};
|
|
2157
2173
|
for (const [name, list] of Object.entries(resolved)) {
|
|
@@ -2709,7 +2725,9 @@ function normalizeRows2(value) {
|
|
|
2709
2725
|
});
|
|
2710
2726
|
}
|
|
2711
2727
|
function candidateRoots(payload) {
|
|
2712
|
-
const roots = [
|
|
2728
|
+
const roots = [
|
|
2729
|
+
{ path: null, value: payload }
|
|
2730
|
+
];
|
|
2713
2731
|
if (isPlainObject(payload) && isPlainObject(payload.toolResponse)) {
|
|
2714
2732
|
roots.push({ path: "toolResponse", value: payload.toolResponse });
|
|
2715
2733
|
if (Object.prototype.hasOwnProperty.call(payload.toolResponse, "raw")) {
|
|
@@ -2736,7 +2754,9 @@ function candidateRoots(payload) {
|
|
|
2736
2754
|
function findBestArrayCandidate(value, pathPrefix = "", depth = 0) {
|
|
2737
2755
|
if (depth > 5) return null;
|
|
2738
2756
|
const directRows = normalizeRows2(value);
|
|
2739
|
-
const hasObjectRow = directRows?.some(
|
|
2757
|
+
const hasObjectRow = directRows?.some(
|
|
2758
|
+
(row) => Object.keys(row).some((key) => key !== "value")
|
|
2759
|
+
) ?? false;
|
|
2740
2760
|
let best = directRows && directRows.length > 0 && hasObjectRow ? { path: pathPrefix, rows: directRows } : null;
|
|
2741
2761
|
if (!isPlainObject(value)) {
|
|
2742
2762
|
return best;
|
|
@@ -2752,7 +2772,9 @@ function findBestArrayCandidate(value, pathPrefix = "", depth = 0) {
|
|
|
2752
2772
|
return best;
|
|
2753
2773
|
}
|
|
2754
2774
|
function tryConvertToList(payload, options) {
|
|
2755
|
-
const listExtractorPaths = Array.isArray(options?.listExtractorPaths) ? options?.listExtractorPaths.filter(
|
|
2775
|
+
const listExtractorPaths = Array.isArray(options?.listExtractorPaths) ? options?.listExtractorPaths.filter(
|
|
2776
|
+
(entry) => typeof entry === "string" && entry.trim().length > 0
|
|
2777
|
+
) : [];
|
|
2756
2778
|
if (listExtractorPaths.length > 0) {
|
|
2757
2779
|
for (const root of candidateRoots(payload)) {
|
|
2758
2780
|
for (const extractorPath of listExtractorPaths) {
|
|
@@ -2818,7 +2840,9 @@ function writeCsvOutputFile(rows, stem) {
|
|
|
2818
2840
|
const previewColumns = columns.slice(0, 5);
|
|
2819
2841
|
const preview = [
|
|
2820
2842
|
previewColumns.join(","),
|
|
2821
|
-
...previewRows.map(
|
|
2843
|
+
...previewRows.map(
|
|
2844
|
+
(row) => previewColumns.map((column) => escapeCell(row[column])).join(",")
|
|
2845
|
+
)
|
|
2822
2846
|
].join("\n");
|
|
2823
2847
|
return {
|
|
2824
2848
|
path: outputPath,
|
|
@@ -2831,9 +2855,11 @@ function extractSummaryFields(payload) {
|
|
|
2831
2855
|
const candidates = candidateRoots(payload);
|
|
2832
2856
|
for (const candidate of candidates) {
|
|
2833
2857
|
if (!isPlainObject(candidate.value)) continue;
|
|
2834
|
-
const summaryEntries = Object.entries(candidate.value).filter(
|
|
2835
|
-
|
|
2836
|
-
|
|
2858
|
+
const summaryEntries = Object.entries(candidate.value).filter(
|
|
2859
|
+
([, value]) => {
|
|
2860
|
+
return value == null || typeof value === "string" || typeof value === "number" || typeof value === "boolean";
|
|
2861
|
+
}
|
|
2862
|
+
);
|
|
2837
2863
|
if (summaryEntries.length === 0) continue;
|
|
2838
2864
|
return Object.fromEntries(summaryEntries);
|
|
2839
2865
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -26,7 +26,11 @@ var RateLimitError = class extends DeeplineError {
|
|
|
26
26
|
/** Milliseconds to wait before retrying, from the `Retry-After` response header. Defaults to 5000. */
|
|
27
27
|
retryAfterMs;
|
|
28
28
|
constructor(retryAfterMs = 5e3, message) {
|
|
29
|
-
super(
|
|
29
|
+
super(
|
|
30
|
+
message ?? `Rate limited. Retry after ${retryAfterMs}ms.`,
|
|
31
|
+
429,
|
|
32
|
+
"RATE_LIMIT"
|
|
33
|
+
);
|
|
30
34
|
this.name = "RateLimitError";
|
|
31
35
|
this.retryAfterMs = retryAfterMs;
|
|
32
36
|
}
|
|
@@ -170,10 +174,10 @@ function resolveConfig(options) {
|
|
|
170
174
|
|
|
171
175
|
// src/release.ts
|
|
172
176
|
var SDK_RELEASE = {
|
|
173
|
-
version: "0.1.
|
|
177
|
+
version: "0.1.64",
|
|
174
178
|
apiContract: "2026-05-play-bootstrap-dataset-summary",
|
|
175
179
|
supportPolicy: {
|
|
176
|
-
latest: "0.1.
|
|
180
|
+
latest: "0.1.64",
|
|
177
181
|
minimumSupported: "0.1.53",
|
|
178
182
|
deprecatedBelow: "0.1.53"
|
|
179
183
|
}
|
|
@@ -196,7 +200,7 @@ var HttpClient = class {
|
|
|
196
200
|
config;
|
|
197
201
|
authHeaders(extra) {
|
|
198
202
|
const headers = {
|
|
199
|
-
|
|
203
|
+
Authorization: `Bearer ${this.config.apiKey}`,
|
|
200
204
|
"User-Agent": `deepline-ts-sdk/${SDK_VERSION}`,
|
|
201
205
|
"X-Deepline-SDK-Version": SDK_VERSION,
|
|
202
206
|
"X-Deepline-API-Contract": SDK_API_CONTRACT,
|
|
@@ -879,31 +883,34 @@ var DeeplineClient = class {
|
|
|
879
883
|
* artifactStorageKey: 'plays/v1/orgs/acme/plays/my-play/artifacts/playgraph_abc123.json',
|
|
880
884
|
* });
|
|
881
885
|
* ```
|
|
882
|
-
|
|
886
|
+
*/
|
|
883
887
|
async startPlayRun(request) {
|
|
884
|
-
const response = await this.http.post(
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
888
|
+
const response = await this.http.post(
|
|
889
|
+
"/api/v2/plays/run",
|
|
890
|
+
{
|
|
891
|
+
...request.name ? { name: request.name } : {},
|
|
892
|
+
...request.revisionId ? { revisionId: request.revisionId } : {},
|
|
893
|
+
...request.artifactStorageKey ? { artifactStorageKey: request.artifactStorageKey } : {},
|
|
894
|
+
...request.sourceCode ? { sourceCode: request.sourceCode } : {},
|
|
895
|
+
...request.sourceFiles ? { sourceFiles: request.sourceFiles } : {},
|
|
896
|
+
..."staticPipeline" in request ? { staticPipeline: request.staticPipeline } : {},
|
|
897
|
+
...request.artifactHash ? { artifactHash: request.artifactHash } : {},
|
|
898
|
+
...request.graphHash ? { graphHash: request.graphHash } : {},
|
|
899
|
+
...request.runtimeArtifact ? { runtimeArtifact: request.runtimeArtifact } : {},
|
|
900
|
+
...request.compilerManifest ? { compilerManifest: request.compilerManifest } : {},
|
|
901
|
+
...request.inputFileUpload ? { inputFileUpload: request.inputFileUpload } : {},
|
|
902
|
+
...request.packagedFileUploads?.length ? { packagedFileUploads: request.packagedFileUploads } : {},
|
|
903
|
+
...request.input ? { input: request.input } : {},
|
|
904
|
+
...request.inputFile ? { inputFile: request.inputFile } : {},
|
|
905
|
+
...request.packagedFiles?.length ? { packagedFiles: request.packagedFiles } : {},
|
|
906
|
+
...request.force ? { force: true } : {},
|
|
907
|
+
...typeof request.waitForCompletionMs === "number" ? { waitForCompletionMs: request.waitForCompletionMs } : {},
|
|
908
|
+
// Profile selection is the API's job, not the CLI's. The server
|
|
909
|
+
// hardcodes workers_edge as the default; tests that want a
|
|
910
|
+
// different profile pass `request.profile` explicitly.
|
|
911
|
+
...request.profile ? { profile: request.profile } : {}
|
|
912
|
+
}
|
|
913
|
+
);
|
|
907
914
|
return normalizePlayRunStart(response);
|
|
908
915
|
}
|
|
909
916
|
async *startPlayRunStream(request, options) {
|
|
@@ -1155,10 +1162,7 @@ var DeeplineClient = class {
|
|
|
1155
1162
|
}
|
|
1156
1163
|
return formData;
|
|
1157
1164
|
};
|
|
1158
|
-
const response = await this.http.postFormData(
|
|
1159
|
-
"/api/v2/plays/files/stage",
|
|
1160
|
-
buildFormData
|
|
1161
|
-
);
|
|
1165
|
+
const response = await this.http.postFormData("/api/v2/plays/files/stage", buildFormData);
|
|
1162
1166
|
return response.files;
|
|
1163
1167
|
}
|
|
1164
1168
|
async resolveStagedPlayFiles(files) {
|
|
@@ -1605,7 +1609,9 @@ var DeeplineClient = class {
|
|
|
1605
1609
|
}
|
|
1606
1610
|
options?.onProgress?.(status);
|
|
1607
1611
|
if (TERMINAL_PLAY_STATUSES.has(status.status)) {
|
|
1608
|
-
const finalStatus = await this.getPlayStatus(
|
|
1612
|
+
const finalStatus = await this.getPlayStatus(
|
|
1613
|
+
status.runId || workflowId
|
|
1614
|
+
).catch(() => status);
|
|
1609
1615
|
return playRunResultFromStatus(finalStatus, start, workflowId);
|
|
1610
1616
|
}
|
|
1611
1617
|
}
|
|
@@ -2011,9 +2017,7 @@ function deriveListKeys(input) {
|
|
|
2011
2017
|
return keys;
|
|
2012
2018
|
}
|
|
2013
2019
|
const listPrefix = input.listPath.replace(/\[\d+\]$/, "");
|
|
2014
|
-
for (const [target, paths] of Object.entries(
|
|
2015
|
-
input.targetGetters ?? {}
|
|
2016
|
-
)) {
|
|
2020
|
+
for (const [target, paths] of Object.entries(input.targetGetters ?? {})) {
|
|
2017
2021
|
for (const rawPath of paths) {
|
|
2018
2022
|
const path = String(rawPath || "").trim().replace(/^\./, "");
|
|
2019
2023
|
if (!path) continue;
|
|
@@ -2059,21 +2063,20 @@ function buildTargets(result, extractors, targetGetters) {
|
|
|
2059
2063
|
for (const [target, descriptor] of Object.entries(extractors ?? {})) {
|
|
2060
2064
|
const fromExtractor = findFirstTargetByPath(result, descriptor.paths);
|
|
2061
2065
|
if (!fromExtractor) continue;
|
|
2066
|
+
const transformed = coerceToEnum(
|
|
2067
|
+
applyExtractorTransforms(fromExtractor.value, descriptor),
|
|
2068
|
+
descriptor
|
|
2069
|
+
);
|
|
2070
|
+
const override = findExtractorOverride(result, descriptor);
|
|
2062
2071
|
targets[target] = {
|
|
2063
2072
|
path: fromExtractor.path,
|
|
2064
|
-
value:
|
|
2065
|
-
applyExtractorTransforms(fromExtractor.value, descriptor),
|
|
2066
|
-
descriptor
|
|
2067
|
-
)
|
|
2073
|
+
value: override?.value ?? transformed
|
|
2068
2074
|
};
|
|
2069
2075
|
}
|
|
2070
2076
|
const metadataTargets = new Set(Object.keys(targetGetters ?? {}));
|
|
2071
2077
|
for (const target of metadataTargets) {
|
|
2072
2078
|
if (targets[target]) continue;
|
|
2073
|
-
const fromMetadata = findFirstTargetByPath(
|
|
2074
|
-
result,
|
|
2075
|
-
targetGetters?.[target]
|
|
2076
|
-
);
|
|
2079
|
+
const fromMetadata = findFirstTargetByPath(result, targetGetters?.[target]);
|
|
2077
2080
|
if (fromMetadata) {
|
|
2078
2081
|
targets[target] = fromMetadata;
|
|
2079
2082
|
continue;
|
|
@@ -2090,6 +2093,19 @@ function buildTargets(result, extractors, targetGetters) {
|
|
|
2090
2093
|
}
|
|
2091
2094
|
return targets;
|
|
2092
2095
|
}
|
|
2096
|
+
function findExtractorOverride(result, descriptor) {
|
|
2097
|
+
for (const override of descriptor.overrides ?? []) {
|
|
2098
|
+
const expected = Object.prototype.hasOwnProperty.call(override, "equals") ? override.equals : true;
|
|
2099
|
+
for (const path of override.paths) {
|
|
2100
|
+
const match = findFirstTargetByPath(result, [path]);
|
|
2101
|
+
if (!match) continue;
|
|
2102
|
+
if (match.value === expected) {
|
|
2103
|
+
return { value: override.value };
|
|
2104
|
+
}
|
|
2105
|
+
}
|
|
2106
|
+
}
|
|
2107
|
+
return null;
|
|
2108
|
+
}
|
|
2093
2109
|
function buildLists(resolved, metadata) {
|
|
2094
2110
|
const lists = {};
|
|
2095
2111
|
for (const [name, list] of Object.entries(resolved)) {
|
|
@@ -2647,7 +2663,9 @@ function normalizeRows2(value) {
|
|
|
2647
2663
|
});
|
|
2648
2664
|
}
|
|
2649
2665
|
function candidateRoots(payload) {
|
|
2650
|
-
const roots = [
|
|
2666
|
+
const roots = [
|
|
2667
|
+
{ path: null, value: payload }
|
|
2668
|
+
];
|
|
2651
2669
|
if (isPlainObject(payload) && isPlainObject(payload.toolResponse)) {
|
|
2652
2670
|
roots.push({ path: "toolResponse", value: payload.toolResponse });
|
|
2653
2671
|
if (Object.prototype.hasOwnProperty.call(payload.toolResponse, "raw")) {
|
|
@@ -2674,7 +2692,9 @@ function candidateRoots(payload) {
|
|
|
2674
2692
|
function findBestArrayCandidate(value, pathPrefix = "", depth = 0) {
|
|
2675
2693
|
if (depth > 5) return null;
|
|
2676
2694
|
const directRows = normalizeRows2(value);
|
|
2677
|
-
const hasObjectRow = directRows?.some(
|
|
2695
|
+
const hasObjectRow = directRows?.some(
|
|
2696
|
+
(row) => Object.keys(row).some((key) => key !== "value")
|
|
2697
|
+
) ?? false;
|
|
2678
2698
|
let best = directRows && directRows.length > 0 && hasObjectRow ? { path: pathPrefix, rows: directRows } : null;
|
|
2679
2699
|
if (!isPlainObject(value)) {
|
|
2680
2700
|
return best;
|
|
@@ -2690,7 +2710,9 @@ function findBestArrayCandidate(value, pathPrefix = "", depth = 0) {
|
|
|
2690
2710
|
return best;
|
|
2691
2711
|
}
|
|
2692
2712
|
function tryConvertToList(payload, options) {
|
|
2693
|
-
const listExtractorPaths = Array.isArray(options?.listExtractorPaths) ? options?.listExtractorPaths.filter(
|
|
2713
|
+
const listExtractorPaths = Array.isArray(options?.listExtractorPaths) ? options?.listExtractorPaths.filter(
|
|
2714
|
+
(entry) => typeof entry === "string" && entry.trim().length > 0
|
|
2715
|
+
) : [];
|
|
2694
2716
|
if (listExtractorPaths.length > 0) {
|
|
2695
2717
|
for (const root of candidateRoots(payload)) {
|
|
2696
2718
|
for (const extractorPath of listExtractorPaths) {
|
|
@@ -2756,7 +2778,9 @@ function writeCsvOutputFile(rows, stem) {
|
|
|
2756
2778
|
const previewColumns = columns.slice(0, 5);
|
|
2757
2779
|
const preview = [
|
|
2758
2780
|
previewColumns.join(","),
|
|
2759
|
-
...previewRows.map(
|
|
2781
|
+
...previewRows.map(
|
|
2782
|
+
(row) => previewColumns.map((column) => escapeCell(row[column])).join(",")
|
|
2783
|
+
)
|
|
2760
2784
|
].join("\n");
|
|
2761
2785
|
return {
|
|
2762
2786
|
path: outputPath,
|
|
@@ -2769,9 +2793,11 @@ function extractSummaryFields(payload) {
|
|
|
2769
2793
|
const candidates = candidateRoots(payload);
|
|
2770
2794
|
for (const candidate of candidates) {
|
|
2771
2795
|
if (!isPlainObject(candidate.value)) continue;
|
|
2772
|
-
const summaryEntries = Object.entries(candidate.value).filter(
|
|
2773
|
-
|
|
2774
|
-
|
|
2796
|
+
const summaryEntries = Object.entries(candidate.value).filter(
|
|
2797
|
+
([, value]) => {
|
|
2798
|
+
return value == null || typeof value === "string" || typeof value === "number" || typeof value === "boolean";
|
|
2799
|
+
}
|
|
2800
|
+
);
|
|
2775
2801
|
if (summaryEntries.length === 0) continue;
|
|
2776
2802
|
return Object.fromEntries(summaryEntries);
|
|
2777
2803
|
}
|
|
@@ -991,12 +991,13 @@ async function persistWorkflowRetryState(input: {
|
|
|
991
991
|
childPlayManifests: stripRetryChildManifestCode(
|
|
992
992
|
input.params.childPlayManifests,
|
|
993
993
|
),
|
|
994
|
-
packagedFiles:
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
994
|
+
packagedFiles:
|
|
995
|
+
input.params.packagedFiles?.map((file) => ({
|
|
996
|
+
playPath: file.playPath,
|
|
997
|
+
storageKey: file.storageKey,
|
|
998
|
+
contentType: file.contentType,
|
|
999
|
+
bytes: file.bytes,
|
|
1000
|
+
})) ?? null,
|
|
1000
1001
|
};
|
|
1001
1002
|
await callWorkflowPool<{ ok?: unknown }>(input.env, '/run-retry-state-put', {
|
|
1002
1003
|
method: 'POST',
|
|
@@ -1115,9 +1116,7 @@ async function restartWorkflowAfterPlatformReset(input: {
|
|
|
1115
1116
|
instanceId: retryInstance.id,
|
|
1116
1117
|
started: true,
|
|
1117
1118
|
});
|
|
1118
|
-
input.ctx?.waitUntil(
|
|
1119
|
-
input.oldInstance.terminate().catch(() => undefined),
|
|
1120
|
-
);
|
|
1119
|
+
input.ctx?.waitUntil(input.oldInstance.terminate().catch(() => undefined));
|
|
1121
1120
|
recordCoordinatorPerfTraceBuffered(input.env, input.ctx, {
|
|
1122
1121
|
runId: input.runId,
|
|
1123
1122
|
phase: 'coordinator.platform_deploy_retry',
|
|
@@ -3177,7 +3176,7 @@ async function handleWorkflowRoute(input: {
|
|
|
3177
3176
|
error: error instanceof Error ? error.message : String(error),
|
|
3178
3177
|
},
|
|
3179
3178
|
});
|
|
3180
|
-
|
|
3179
|
+
});
|
|
3181
3180
|
input.ctx?.waitUntil(prewarmPromise);
|
|
3182
3181
|
}
|
|
3183
3182
|
await persistWorkflowRetryState({
|
|
@@ -1330,6 +1330,7 @@ function parseExtractorMetadata(
|
|
|
1330
1330
|
if (paths.length === 0) return [];
|
|
1331
1331
|
const transforms = parseStringArray(record.transforms);
|
|
1332
1332
|
const enumValues = parseStringArray(record.enum);
|
|
1333
|
+
const overrides = parseExtractorOverrides(record.overrides);
|
|
1333
1334
|
return [
|
|
1334
1335
|
[
|
|
1335
1336
|
key,
|
|
@@ -1337,6 +1338,7 @@ function parseExtractorMetadata(
|
|
|
1337
1338
|
paths,
|
|
1338
1339
|
...(transforms.length > 0 ? { transforms } : {}),
|
|
1339
1340
|
...(enumValues.length > 0 ? { enum: enumValues } : {}),
|
|
1341
|
+
...(overrides.length > 0 ? { overrides } : {}),
|
|
1340
1342
|
},
|
|
1341
1343
|
],
|
|
1342
1344
|
] as const;
|
|
@@ -1345,6 +1347,39 @@ function parseExtractorMetadata(
|
|
|
1345
1347
|
return entries.length > 0 ? Object.fromEntries(entries) : undefined;
|
|
1346
1348
|
}
|
|
1347
1349
|
|
|
1350
|
+
function parseExtractorOverrides(
|
|
1351
|
+
value: unknown,
|
|
1352
|
+
): NonNullable<
|
|
1353
|
+
NonNullable<ToolResultMetadataInput['extractors']>[string]['overrides']
|
|
1354
|
+
> {
|
|
1355
|
+
if (!Array.isArray(value)) return [];
|
|
1356
|
+
return value.flatMap((entry) => {
|
|
1357
|
+
if (!entry || typeof entry !== 'object' || Array.isArray(entry)) {
|
|
1358
|
+
return [];
|
|
1359
|
+
}
|
|
1360
|
+
const record = entry as Record<string, unknown>;
|
|
1361
|
+
const paths = parseStringArray(record.paths);
|
|
1362
|
+
if (paths.length === 0) return [];
|
|
1363
|
+
const equals =
|
|
1364
|
+
record.equals === null ||
|
|
1365
|
+
typeof record.equals === 'string' ||
|
|
1366
|
+
typeof record.equals === 'number' ||
|
|
1367
|
+
typeof record.equals === 'boolean'
|
|
1368
|
+
? record.equals
|
|
1369
|
+
: true;
|
|
1370
|
+
const overrideValue = record.value;
|
|
1371
|
+
if (
|
|
1372
|
+
overrideValue !== null &&
|
|
1373
|
+
typeof overrideValue !== 'string' &&
|
|
1374
|
+
typeof overrideValue !== 'number' &&
|
|
1375
|
+
typeof overrideValue !== 'boolean'
|
|
1376
|
+
) {
|
|
1377
|
+
return [];
|
|
1378
|
+
}
|
|
1379
|
+
return [{ paths, equals, value: overrideValue }];
|
|
1380
|
+
});
|
|
1381
|
+
}
|
|
1382
|
+
|
|
1348
1383
|
function parseGetterMetadata(
|
|
1349
1384
|
value: unknown,
|
|
1350
1385
|
): Record<string, readonly string[]> | undefined {
|
|
@@ -1370,8 +1405,23 @@ function syntheticToolMetadata(toolId: string): ToolResultMetadataInput {
|
|
|
1370
1405
|
if (toolId === 'test_rate_limit') {
|
|
1371
1406
|
return {
|
|
1372
1407
|
toolId,
|
|
1408
|
+
extractors: {
|
|
1409
|
+
email_status: {
|
|
1410
|
+
paths: ['email_status'],
|
|
1411
|
+
transforms: ['emailStatus'],
|
|
1412
|
+
enum: ['valid', 'invalid', 'catch_all', 'unknown'],
|
|
1413
|
+
overrides: [
|
|
1414
|
+
{
|
|
1415
|
+
paths: ['mx_security_gateway'],
|
|
1416
|
+
equals: true,
|
|
1417
|
+
value: 'catch_all',
|
|
1418
|
+
},
|
|
1419
|
+
],
|
|
1420
|
+
},
|
|
1421
|
+
},
|
|
1373
1422
|
targetGetters: {
|
|
1374
1423
|
email: ['email', 'value'],
|
|
1424
|
+
email_status: ['email_status'],
|
|
1375
1425
|
},
|
|
1376
1426
|
};
|
|
1377
1427
|
}
|
|
@@ -1539,6 +1589,10 @@ function executeSyntheticTestRateLimit(
|
|
|
1539
1589
|
: 'match'));
|
|
1540
1590
|
const matched = syntheticMatchWindow(input, rowNumber);
|
|
1541
1591
|
const matchedEmail = matched ? `${matchedPrefix}@${matchedDomain}` : null;
|
|
1592
|
+
const securityGateway =
|
|
1593
|
+
input.emit_security_gateway === true
|
|
1594
|
+
? { email_status: 'valid', mx_security_gateway: true }
|
|
1595
|
+
: {};
|
|
1542
1596
|
return {
|
|
1543
1597
|
status: 'completed',
|
|
1544
1598
|
key: String(input.key || ''),
|
|
@@ -1549,6 +1603,7 @@ function executeSyntheticTestRateLimit(
|
|
|
1549
1603
|
email: matchedEmail,
|
|
1550
1604
|
value: matchedEmail,
|
|
1551
1605
|
batch: false,
|
|
1606
|
+
...securityGateway,
|
|
1552
1607
|
};
|
|
1553
1608
|
}
|
|
1554
1609
|
|