deepline 0.1.145 → 0.1.147
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bundling-sources/apps/play-runner-workers/src/entry.ts +205 -75
- package/dist/bundling-sources/apps/play-runner-workers/src/runtime/dataset-handles.ts +8 -0
- package/dist/bundling-sources/apps/play-runner-workers/src/runtime/output-datasets.ts +363 -0
- package/dist/bundling-sources/apps/play-runner-workers/src/runtime/result-dataset-persistence.ts +50 -0
- package/dist/bundling-sources/sdk/src/release.ts +54 -21
- package/dist/bundling-sources/sdk/src/tool-output.ts +18 -7
- package/dist/bundling-sources/shared_libs/play-runtime/tool-result-types.ts +2 -1
- package/dist/bundling-sources/shared_libs/play-runtime/tool-result.ts +81 -5
- package/dist/cli/index.js +371 -41
- package/dist/cli/index.mjs +383 -53
- package/dist/index.d.mts +91 -89
- package/dist/index.d.ts +91 -89
- package/dist/index.js +545 -31
- package/dist/index.mjs +546 -32
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -348,10 +348,11 @@ var SDK_RELEASE = {
|
|
|
348
348
|
// 0.1.108 ships explicit dataset column/tool recompute policy and removes
|
|
349
349
|
// the SDK enrich generator's one-second stale policy.
|
|
350
350
|
// 0.1.110 ships authored V2 prebuilts and required top-level play descriptions.
|
|
351
|
-
|
|
352
|
-
|
|
351
|
+
// 0.1.111 ships dataset-native tool list getters and result row datasets.
|
|
352
|
+
version: "0.1.147",
|
|
353
|
+
apiContract: "2026-06-dataset-handle-results-hard-cutover",
|
|
353
354
|
supportPolicy: {
|
|
354
|
-
latest: "0.1.
|
|
355
|
+
latest: "0.1.147",
|
|
355
356
|
minimumSupported: "0.1.53",
|
|
356
357
|
deprecatedBelow: "0.1.53",
|
|
357
358
|
commandMinimumSupported: [
|
|
@@ -362,52 +363,79 @@ var SDK_RELEASE = {
|
|
|
362
363
|
},
|
|
363
364
|
{
|
|
364
365
|
command: "plays",
|
|
365
|
-
minimumSupported: "0.1.
|
|
366
|
-
reason: "Play file commands now
|
|
366
|
+
minimumSupported: "0.1.111",
|
|
367
|
+
reason: "Play file commands now use dataset-native list getters and result row datasets."
|
|
367
368
|
},
|
|
368
369
|
{
|
|
369
370
|
command: "plays run",
|
|
370
|
-
minimumSupported: "0.1.
|
|
371
|
-
reason: "Play
|
|
371
|
+
minimumSupported: "0.1.111",
|
|
372
|
+
reason: "Play run results now promote row-shaped outputs into dataset handles for safe export."
|
|
372
373
|
},
|
|
373
374
|
{
|
|
374
375
|
command: "run",
|
|
375
376
|
displayCommand: "plays run",
|
|
376
|
-
minimumSupported: "0.1.
|
|
377
|
-
reason: "Play
|
|
377
|
+
minimumSupported: "0.1.111",
|
|
378
|
+
reason: "Play run results now promote row-shaped outputs into dataset handles for safe export."
|
|
378
379
|
},
|
|
379
380
|
{
|
|
380
381
|
command: "plays check",
|
|
381
|
-
minimumSupported: "0.1.
|
|
382
|
-
reason: "Play file
|
|
382
|
+
minimumSupported: "0.1.111",
|
|
383
|
+
reason: "Play file checks now validate dataset-native list getter authoring."
|
|
383
384
|
},
|
|
384
385
|
{
|
|
385
386
|
command: "check",
|
|
386
387
|
displayCommand: "plays check",
|
|
387
|
-
minimumSupported: "0.1.
|
|
388
|
-
reason: "Play file
|
|
388
|
+
minimumSupported: "0.1.111",
|
|
389
|
+
reason: "Play file checks now validate dataset-native list getter authoring."
|
|
389
390
|
},
|
|
390
391
|
{
|
|
391
392
|
command: "plays publish",
|
|
392
|
-
minimumSupported: "0.1.
|
|
393
|
-
reason: "
|
|
393
|
+
minimumSupported: "0.1.111",
|
|
394
|
+
reason: "Published play artifacts now target dataset-native list getters and result row datasets."
|
|
394
395
|
},
|
|
395
396
|
{
|
|
396
397
|
command: "publish",
|
|
397
398
|
displayCommand: "plays publish",
|
|
398
|
-
minimumSupported: "0.1.
|
|
399
|
-
reason: "
|
|
399
|
+
minimumSupported: "0.1.111",
|
|
400
|
+
reason: "Published play artifacts now target dataset-native list getters and result row datasets."
|
|
400
401
|
},
|
|
401
402
|
{
|
|
402
403
|
command: "plays set-live",
|
|
403
|
-
minimumSupported: "0.1.
|
|
404
|
-
reason: "
|
|
404
|
+
minimumSupported: "0.1.111",
|
|
405
|
+
reason: "Published play artifacts now target dataset-native list getters and result row datasets."
|
|
405
406
|
},
|
|
406
407
|
{
|
|
407
408
|
command: "set-live",
|
|
408
409
|
displayCommand: "plays set-live",
|
|
409
|
-
minimumSupported: "0.1.
|
|
410
|
-
reason: "
|
|
410
|
+
minimumSupported: "0.1.111",
|
|
411
|
+
reason: "Published play artifacts now target dataset-native list getters and result row datasets."
|
|
412
|
+
},
|
|
413
|
+
{
|
|
414
|
+
command: "runs",
|
|
415
|
+
minimumSupported: "0.1.111",
|
|
416
|
+
reason: "Run result rows now render as dataset handles with explicit export commands."
|
|
417
|
+
},
|
|
418
|
+
{
|
|
419
|
+
command: "runs get",
|
|
420
|
+
minimumSupported: "0.1.111",
|
|
421
|
+
reason: "Run result rows now render as dataset handles with explicit export commands."
|
|
422
|
+
},
|
|
423
|
+
{
|
|
424
|
+
command: "get",
|
|
425
|
+
displayCommand: "runs get",
|
|
426
|
+
minimumSupported: "0.1.111",
|
|
427
|
+
reason: "Run result rows now render as dataset handles with explicit export commands."
|
|
428
|
+
},
|
|
429
|
+
{
|
|
430
|
+
command: "runs export",
|
|
431
|
+
minimumSupported: "0.1.111",
|
|
432
|
+
reason: "Run result row datasets now use the dataset-handle export contract."
|
|
433
|
+
},
|
|
434
|
+
{
|
|
435
|
+
command: "export",
|
|
436
|
+
displayCommand: "runs export",
|
|
437
|
+
minimumSupported: "0.1.111",
|
|
438
|
+
reason: "Run result row datasets now use the dataset-handle export contract."
|
|
411
439
|
}
|
|
412
440
|
],
|
|
413
441
|
autoUpdatePatchLag: 2
|
|
@@ -3903,6 +3931,420 @@ function isDeeplineExtractorTarget(value) {
|
|
|
3903
3931
|
return value in DEEPLINE_EXTRACTOR_TARGET_DEFINITIONS;
|
|
3904
3932
|
}
|
|
3905
3933
|
|
|
3934
|
+
// ../shared_libs/plays/dataset.ts
|
|
3935
|
+
var PLAY_DATASET_BRAND = /* @__PURE__ */ Symbol.for("deepline.play.dataset");
|
|
3936
|
+
var NODE_INSPECT_CUSTOM = /* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom");
|
|
3937
|
+
var DEFAULT_MATERIALIZE_LIMIT = 1e4;
|
|
3938
|
+
function resolveMaterializeLimitCap() {
|
|
3939
|
+
const raw = process.env.DEEPLINE_PLAY_DATASET_MATERIALIZE_LIMIT;
|
|
3940
|
+
const parsed = raw ? Number(raw) : NaN;
|
|
3941
|
+
if (Number.isFinite(parsed) && parsed > 0) {
|
|
3942
|
+
return Math.floor(parsed);
|
|
3943
|
+
}
|
|
3944
|
+
return DEFAULT_MATERIALIZE_LIMIT;
|
|
3945
|
+
}
|
|
3946
|
+
function inferPreviewColumns(rows) {
|
|
3947
|
+
const columns = /* @__PURE__ */ new Set();
|
|
3948
|
+
for (const row of rows) {
|
|
3949
|
+
if (!row || typeof row !== "object" || Array.isArray(row)) {
|
|
3950
|
+
continue;
|
|
3951
|
+
}
|
|
3952
|
+
for (const key of Object.keys(row)) {
|
|
3953
|
+
columns.add(key);
|
|
3954
|
+
}
|
|
3955
|
+
}
|
|
3956
|
+
return columns.size > 0 ? [...columns] : void 0;
|
|
3957
|
+
}
|
|
3958
|
+
var DeferredPlayDataset = class {
|
|
3959
|
+
[PLAY_DATASET_BRAND] = true;
|
|
3960
|
+
datasetKind;
|
|
3961
|
+
datasetId;
|
|
3962
|
+
backing;
|
|
3963
|
+
sourceLabel;
|
|
3964
|
+
tableNamespace;
|
|
3965
|
+
previewRows;
|
|
3966
|
+
previewColumns;
|
|
3967
|
+
workProgress;
|
|
3968
|
+
cachedCount;
|
|
3969
|
+
resolvers;
|
|
3970
|
+
constructor(input) {
|
|
3971
|
+
this.datasetKind = input.datasetKind;
|
|
3972
|
+
this.datasetId = input.datasetId;
|
|
3973
|
+
this.cachedCount = input.count;
|
|
3974
|
+
this.backing = input.backing;
|
|
3975
|
+
this.previewRows = input.previewRows;
|
|
3976
|
+
this.previewColumns = inferPreviewColumns(this.previewRows);
|
|
3977
|
+
this.sourceLabel = input.sourceLabel ?? null;
|
|
3978
|
+
this.tableNamespace = input.tableNamespace ?? null;
|
|
3979
|
+
this.workProgress = input.workProgress;
|
|
3980
|
+
this.resolvers = input.resolvers;
|
|
3981
|
+
}
|
|
3982
|
+
async count() {
|
|
3983
|
+
this.cachedCount = await this.resolvers.count();
|
|
3984
|
+
return this.cachedCount;
|
|
3985
|
+
}
|
|
3986
|
+
async peek(limit = 10) {
|
|
3987
|
+
if (limit <= this.previewRows.length) {
|
|
3988
|
+
return this.previewRows.slice(0, Math.max(0, limit));
|
|
3989
|
+
}
|
|
3990
|
+
return await this.resolvers.peek(limit);
|
|
3991
|
+
}
|
|
3992
|
+
map(mapper, options) {
|
|
3993
|
+
return createTransformedPlayDataset(this, { kind: "map", mapper }, options);
|
|
3994
|
+
}
|
|
3995
|
+
filter(predicate, options) {
|
|
3996
|
+
return createTransformedPlayDataset(
|
|
3997
|
+
this,
|
|
3998
|
+
{ kind: "filter", predicate },
|
|
3999
|
+
options
|
|
4000
|
+
);
|
|
4001
|
+
}
|
|
4002
|
+
slice(start, end, options) {
|
|
4003
|
+
return createTransformedPlayDataset(
|
|
4004
|
+
this,
|
|
4005
|
+
{ kind: "slice", start, end },
|
|
4006
|
+
options
|
|
4007
|
+
);
|
|
4008
|
+
}
|
|
4009
|
+
take(limit, options) {
|
|
4010
|
+
return this.slice(0, limit, options);
|
|
4011
|
+
}
|
|
4012
|
+
async materialize(limit) {
|
|
4013
|
+
const requestedLimit = limit !== void 0 ? Math.max(0, Math.floor(limit)) : void 0;
|
|
4014
|
+
const cap = resolveMaterializeLimitCap();
|
|
4015
|
+
if (requestedLimit !== void 0) {
|
|
4016
|
+
if (requestedLimit > cap) {
|
|
4017
|
+
throw new Error(
|
|
4018
|
+
`PlayDataset.materialize(${requestedLimit}) exceeds the hard limit of ${cap} rows. Return the dataset handle instead, or request a smaller bounded slice.`
|
|
4019
|
+
);
|
|
4020
|
+
}
|
|
4021
|
+
return await this.resolvers.materialize(requestedLimit);
|
|
4022
|
+
}
|
|
4023
|
+
const count = await this.count();
|
|
4024
|
+
if (count > cap) {
|
|
4025
|
+
throw new Error(
|
|
4026
|
+
`PlayDataset.materialize() refuses to load ${count} rows into memory. The hard limit is ${cap}. Return the dataset handle instead or call materialize(limit).`
|
|
4027
|
+
);
|
|
4028
|
+
}
|
|
4029
|
+
return await this.resolvers.materialize();
|
|
4030
|
+
}
|
|
4031
|
+
async *[Symbol.asyncIterator]() {
|
|
4032
|
+
for await (const row of this.resolvers.iterate()) {
|
|
4033
|
+
yield row;
|
|
4034
|
+
}
|
|
4035
|
+
}
|
|
4036
|
+
toJSON() {
|
|
4037
|
+
return {
|
|
4038
|
+
kind: "dataset",
|
|
4039
|
+
datasetKind: this.datasetKind,
|
|
4040
|
+
datasetId: this.datasetId,
|
|
4041
|
+
count: this.cachedCount,
|
|
4042
|
+
...this.backing ? { backing: this.backing } : {},
|
|
4043
|
+
...this.sourceLabel ? { sourceLabel: this.sourceLabel } : {},
|
|
4044
|
+
...this.tableNamespace ? { tableNamespace: this.tableNamespace } : {},
|
|
4045
|
+
...this.previewColumns ? { columns: this.previewColumns } : {},
|
|
4046
|
+
...this.workProgress ? { _metadata: { workProgress: this.workProgress } } : {},
|
|
4047
|
+
preview: [...this.previewRows]
|
|
4048
|
+
};
|
|
4049
|
+
}
|
|
4050
|
+
[NODE_INSPECT_CUSTOM]() {
|
|
4051
|
+
return this.toJSON();
|
|
4052
|
+
}
|
|
4053
|
+
};
|
|
4054
|
+
function normalizeSliceBounds(input) {
|
|
4055
|
+
const count = Math.max(0, Math.floor(input.count));
|
|
4056
|
+
const rawStart = input.start ?? 0;
|
|
4057
|
+
const rawEnd = input.end ?? count;
|
|
4058
|
+
const startInteger = Number.isFinite(rawStart) ? Math.trunc(rawStart) : 0;
|
|
4059
|
+
const endInteger = Number.isFinite(rawEnd) ? Math.trunc(rawEnd) : count;
|
|
4060
|
+
const start = startInteger < 0 ? Math.max(count + startInteger, 0) : Math.min(startInteger, count);
|
|
4061
|
+
const end = endInteger < 0 ? Math.max(count + endInteger, 0) : Math.min(endInteger, count);
|
|
4062
|
+
return { start, end: Math.max(start, end) };
|
|
4063
|
+
}
|
|
4064
|
+
function transformDatasetId(input) {
|
|
4065
|
+
const key = input.key?.trim();
|
|
4066
|
+
return key ? `${input.source.datasetId}:${input.kind}:${key}` : `${input.source.datasetId}:${input.kind}`;
|
|
4067
|
+
}
|
|
4068
|
+
function createTransformedPlayDataset(source, transform, options) {
|
|
4069
|
+
const sourceLabel = options?.sourceLabel ?? `${source.sourceLabel ?? source.tableNamespace ?? source.datasetId}.${transform.kind}`;
|
|
4070
|
+
const iterate = async function* () {
|
|
4071
|
+
if (transform.kind === "slice") {
|
|
4072
|
+
const bounds = normalizeSliceBounds({
|
|
4073
|
+
start: transform.start,
|
|
4074
|
+
end: transform.end,
|
|
4075
|
+
count: await source.count()
|
|
4076
|
+
});
|
|
4077
|
+
let index = 0;
|
|
4078
|
+
for await (const row of source) {
|
|
4079
|
+
if (index >= bounds.end) break;
|
|
4080
|
+
if (index >= bounds.start) {
|
|
4081
|
+
yield row;
|
|
4082
|
+
}
|
|
4083
|
+
index += 1;
|
|
4084
|
+
}
|
|
4085
|
+
return;
|
|
4086
|
+
}
|
|
4087
|
+
let inputIndex = 0;
|
|
4088
|
+
let outputIndex = 0;
|
|
4089
|
+
for await (const row of source) {
|
|
4090
|
+
if (transform.kind === "filter") {
|
|
4091
|
+
if (await transform.predicate(row, inputIndex)) {
|
|
4092
|
+
yield row;
|
|
4093
|
+
outputIndex += 1;
|
|
4094
|
+
}
|
|
4095
|
+
} else {
|
|
4096
|
+
yield await transform.mapper(row, outputIndex);
|
|
4097
|
+
outputIndex += 1;
|
|
4098
|
+
}
|
|
4099
|
+
inputIndex += 1;
|
|
4100
|
+
}
|
|
4101
|
+
};
|
|
4102
|
+
const collect = async (limit) => {
|
|
4103
|
+
const rows = [];
|
|
4104
|
+
const boundedLimit = limit === void 0 ? void 0 : Math.max(0, Math.floor(limit));
|
|
4105
|
+
if (boundedLimit === 0) return rows;
|
|
4106
|
+
for await (const row of iterate()) {
|
|
4107
|
+
rows.push(row);
|
|
4108
|
+
if (boundedLimit !== void 0 && rows.length >= boundedLimit) break;
|
|
4109
|
+
}
|
|
4110
|
+
return rows;
|
|
4111
|
+
};
|
|
4112
|
+
const count = async () => {
|
|
4113
|
+
if (transform.kind === "map") return await source.count();
|
|
4114
|
+
if (transform.kind === "slice") {
|
|
4115
|
+
const bounds = normalizeSliceBounds({
|
|
4116
|
+
start: transform.start,
|
|
4117
|
+
end: transform.end,
|
|
4118
|
+
count: await source.count()
|
|
4119
|
+
});
|
|
4120
|
+
return Math.max(0, bounds.end - bounds.start);
|
|
4121
|
+
}
|
|
4122
|
+
let total = 0;
|
|
4123
|
+
for await (const _row of iterate()) {
|
|
4124
|
+
void _row;
|
|
4125
|
+
total += 1;
|
|
4126
|
+
}
|
|
4127
|
+
return total;
|
|
4128
|
+
};
|
|
4129
|
+
return createDeferredPlayDataset({
|
|
4130
|
+
datasetKind: source.datasetKind,
|
|
4131
|
+
datasetId: transformDatasetId({
|
|
4132
|
+
source,
|
|
4133
|
+
kind: transform.kind,
|
|
4134
|
+
key: options?.key
|
|
4135
|
+
}),
|
|
4136
|
+
count: 0,
|
|
4137
|
+
backing: source.backing,
|
|
4138
|
+
sourceLabel,
|
|
4139
|
+
tableNamespace: options?.key ?? null,
|
|
4140
|
+
resolvers: {
|
|
4141
|
+
count,
|
|
4142
|
+
peek: async (limit) => collect(limit),
|
|
4143
|
+
materialize: async (limit) => collect(limit),
|
|
4144
|
+
iterate: () => ({
|
|
4145
|
+
async *[Symbol.asyncIterator]() {
|
|
4146
|
+
yield* iterate();
|
|
4147
|
+
}
|
|
4148
|
+
})
|
|
4149
|
+
}
|
|
4150
|
+
});
|
|
4151
|
+
}
|
|
4152
|
+
function createDeferredPlayDataset(input) {
|
|
4153
|
+
return new DeferredPlayDataset({
|
|
4154
|
+
...input,
|
|
4155
|
+
previewRows: input.previewRows ?? []
|
|
4156
|
+
});
|
|
4157
|
+
}
|
|
4158
|
+
function createPlayDataset(rows, metadata) {
|
|
4159
|
+
const materializedRows = [...rows];
|
|
4160
|
+
return createDeferredPlayDataset({
|
|
4161
|
+
datasetKind: metadata?.kind ?? "map",
|
|
4162
|
+
datasetId: metadata?.datasetId ?? `${metadata?.kind ?? "map"}:${metadata?.tableNamespace ?? metadata?.sourceLabel ?? "inline"}`,
|
|
4163
|
+
count: materializedRows.length,
|
|
4164
|
+
previewRows: materializedRows.slice(0, 5),
|
|
4165
|
+
sourceLabel: metadata?.sourceLabel ?? null,
|
|
4166
|
+
tableNamespace: metadata?.tableNamespace ?? null,
|
|
4167
|
+
resolvers: {
|
|
4168
|
+
count: async () => materializedRows.length,
|
|
4169
|
+
peek: async (limit) => materializedRows.slice(0, Math.max(0, limit)),
|
|
4170
|
+
materialize: async (limit) => limit === void 0 ? [...materializedRows] : materializedRows.slice(0, Math.max(0, limit)),
|
|
4171
|
+
iterate: () => ({
|
|
4172
|
+
async *[Symbol.asyncIterator]() {
|
|
4173
|
+
for (const row of materializedRows) {
|
|
4174
|
+
yield row;
|
|
4175
|
+
}
|
|
4176
|
+
}
|
|
4177
|
+
})
|
|
4178
|
+
}
|
|
4179
|
+
});
|
|
4180
|
+
}
|
|
4181
|
+
|
|
4182
|
+
// ../shared_libs/plays/row-identity.ts
|
|
4183
|
+
var POSTGRES_IDENTIFIER_MAX_LENGTH = 63;
|
|
4184
|
+
var MAP_KEY_NAMESPACE_MAX_LENGTH = POSTGRES_IDENTIFIER_MAX_LENGTH;
|
|
4185
|
+
var SHA256_INITIAL_HASH = [
|
|
4186
|
+
1779033703,
|
|
4187
|
+
3144134277,
|
|
4188
|
+
1013904242,
|
|
4189
|
+
2773480762,
|
|
4190
|
+
1359893119,
|
|
4191
|
+
2600822924,
|
|
4192
|
+
528734635,
|
|
4193
|
+
1541459225
|
|
4194
|
+
];
|
|
4195
|
+
var SHA256_ROUND_CONSTANTS = [
|
|
4196
|
+
1116352408,
|
|
4197
|
+
1899447441,
|
|
4198
|
+
3049323471,
|
|
4199
|
+
3921009573,
|
|
4200
|
+
961987163,
|
|
4201
|
+
1508970993,
|
|
4202
|
+
2453635748,
|
|
4203
|
+
2870763221,
|
|
4204
|
+
3624381080,
|
|
4205
|
+
310598401,
|
|
4206
|
+
607225278,
|
|
4207
|
+
1426881987,
|
|
4208
|
+
1925078388,
|
|
4209
|
+
2162078206,
|
|
4210
|
+
2614888103,
|
|
4211
|
+
3248222580,
|
|
4212
|
+
3835390401,
|
|
4213
|
+
4022224774,
|
|
4214
|
+
264347078,
|
|
4215
|
+
604807628,
|
|
4216
|
+
770255983,
|
|
4217
|
+
1249150122,
|
|
4218
|
+
1555081692,
|
|
4219
|
+
1996064986,
|
|
4220
|
+
2554220882,
|
|
4221
|
+
2821834349,
|
|
4222
|
+
2952996808,
|
|
4223
|
+
3210313671,
|
|
4224
|
+
3336571891,
|
|
4225
|
+
3584528711,
|
|
4226
|
+
113926993,
|
|
4227
|
+
338241895,
|
|
4228
|
+
666307205,
|
|
4229
|
+
773529912,
|
|
4230
|
+
1294757372,
|
|
4231
|
+
1396182291,
|
|
4232
|
+
1695183700,
|
|
4233
|
+
1986661051,
|
|
4234
|
+
2177026350,
|
|
4235
|
+
2456956037,
|
|
4236
|
+
2730485921,
|
|
4237
|
+
2820302411,
|
|
4238
|
+
3259730800,
|
|
4239
|
+
3345764771,
|
|
4240
|
+
3516065817,
|
|
4241
|
+
3600352804,
|
|
4242
|
+
4094571909,
|
|
4243
|
+
275423344,
|
|
4244
|
+
430227734,
|
|
4245
|
+
506948616,
|
|
4246
|
+
659060556,
|
|
4247
|
+
883997877,
|
|
4248
|
+
958139571,
|
|
4249
|
+
1322822218,
|
|
4250
|
+
1537002063,
|
|
4251
|
+
1747873779,
|
|
4252
|
+
1955562222,
|
|
4253
|
+
2024104815,
|
|
4254
|
+
2227730452,
|
|
4255
|
+
2361852424,
|
|
4256
|
+
2428436474,
|
|
4257
|
+
2756734187,
|
|
4258
|
+
3204031479,
|
|
4259
|
+
3329325298
|
|
4260
|
+
];
|
|
4261
|
+
function rightRotate32(value, bits) {
|
|
4262
|
+
return value >>> bits | value << 32 - bits;
|
|
4263
|
+
}
|
|
4264
|
+
function sha256Hex(input) {
|
|
4265
|
+
const bytes = Array.from(new TextEncoder().encode(input));
|
|
4266
|
+
const bitLength = bytes.length * 8;
|
|
4267
|
+
bytes.push(128);
|
|
4268
|
+
while (bytes.length % 64 !== 56) {
|
|
4269
|
+
bytes.push(0);
|
|
4270
|
+
}
|
|
4271
|
+
const highBits = Math.floor(bitLength / 4294967296);
|
|
4272
|
+
const lowBits = bitLength >>> 0;
|
|
4273
|
+
bytes.push(
|
|
4274
|
+
highBits >>> 24 & 255,
|
|
4275
|
+
highBits >>> 16 & 255,
|
|
4276
|
+
highBits >>> 8 & 255,
|
|
4277
|
+
highBits & 255,
|
|
4278
|
+
lowBits >>> 24 & 255,
|
|
4279
|
+
lowBits >>> 16 & 255,
|
|
4280
|
+
lowBits >>> 8 & 255,
|
|
4281
|
+
lowBits & 255
|
|
4282
|
+
);
|
|
4283
|
+
const hash = [...SHA256_INITIAL_HASH];
|
|
4284
|
+
const words = new Array(64).fill(0);
|
|
4285
|
+
for (let offset = 0; offset < bytes.length; offset += 64) {
|
|
4286
|
+
for (let index = 0; index < 16; index += 1) {
|
|
4287
|
+
const wordOffset = offset + index * 4;
|
|
4288
|
+
words[index] = (bytes[wordOffset] ?? 0) << 24 | (bytes[wordOffset + 1] ?? 0) << 16 | (bytes[wordOffset + 2] ?? 0) << 8 | (bytes[wordOffset + 3] ?? 0);
|
|
4289
|
+
}
|
|
4290
|
+
for (let index = 16; index < 64; index += 1) {
|
|
4291
|
+
const s0 = rightRotate32(words[index - 15], 7) ^ rightRotate32(words[index - 15], 18) ^ words[index - 15] >>> 3;
|
|
4292
|
+
const s1 = rightRotate32(words[index - 2], 17) ^ rightRotate32(words[index - 2], 19) ^ words[index - 2] >>> 10;
|
|
4293
|
+
words[index] = words[index - 16] + s0 + words[index - 7] + s1 >>> 0;
|
|
4294
|
+
}
|
|
4295
|
+
let [a, b, c, d, e, f, g, h] = hash;
|
|
4296
|
+
for (let index = 0; index < 64; index += 1) {
|
|
4297
|
+
const s1 = rightRotate32(e, 6) ^ rightRotate32(e, 11) ^ rightRotate32(e, 25);
|
|
4298
|
+
const ch = e & f ^ ~e & g;
|
|
4299
|
+
const temp1 = h + s1 + ch + SHA256_ROUND_CONSTANTS[index] + words[index] >>> 0;
|
|
4300
|
+
const s0 = rightRotate32(a, 2) ^ rightRotate32(a, 13) ^ rightRotate32(a, 22);
|
|
4301
|
+
const maj = a & b ^ a & c ^ b & c;
|
|
4302
|
+
const temp2 = s0 + maj >>> 0;
|
|
4303
|
+
h = g;
|
|
4304
|
+
g = f;
|
|
4305
|
+
f = e;
|
|
4306
|
+
e = d + temp1 >>> 0;
|
|
4307
|
+
d = c;
|
|
4308
|
+
c = b;
|
|
4309
|
+
b = a;
|
|
4310
|
+
a = temp1 + temp2 >>> 0;
|
|
4311
|
+
}
|
|
4312
|
+
hash[0] = hash[0] + a >>> 0;
|
|
4313
|
+
hash[1] = hash[1] + b >>> 0;
|
|
4314
|
+
hash[2] = hash[2] + c >>> 0;
|
|
4315
|
+
hash[3] = hash[3] + d >>> 0;
|
|
4316
|
+
hash[4] = hash[4] + e >>> 0;
|
|
4317
|
+
hash[5] = hash[5] + f >>> 0;
|
|
4318
|
+
hash[6] = hash[6] + g >>> 0;
|
|
4319
|
+
hash[7] = hash[7] + h >>> 0;
|
|
4320
|
+
}
|
|
4321
|
+
return hash.map((word) => word.toString(16).padStart(8, "0")).join("");
|
|
4322
|
+
}
|
|
4323
|
+
function sanitizeIdentifierPart(value) {
|
|
4324
|
+
return value.trim().replace(/[^a-z0-9]+/gi, "_").replace(/_+/g, "_").replace(/^_+|_+$/g, "").toLowerCase();
|
|
4325
|
+
}
|
|
4326
|
+
function validateIdentifierPart(rawValue, label, maxLength) {
|
|
4327
|
+
const sanitized = sanitizeIdentifierPart(rawValue);
|
|
4328
|
+
if (!sanitized) {
|
|
4329
|
+
throw new Error(
|
|
4330
|
+
`${label} must contain at least one letter or number after normalization. Use only letters, numbers, underscores, or hyphens.`
|
|
4331
|
+
);
|
|
4332
|
+
}
|
|
4333
|
+
if (sanitized.length > maxLength) {
|
|
4334
|
+
throw new Error(
|
|
4335
|
+
`${label} is too long after normalization (${sanitized.length}/${maxLength}). Shorten it to ${maxLength} characters or fewer. Normalized value: "${sanitized}".`
|
|
4336
|
+
);
|
|
4337
|
+
}
|
|
4338
|
+
return sanitized;
|
|
4339
|
+
}
|
|
4340
|
+
function normalizeTableNamespace(value) {
|
|
4341
|
+
return validateIdentifierPart(
|
|
4342
|
+
value,
|
|
4343
|
+
"ctx.dataset() key",
|
|
4344
|
+
MAP_KEY_NAMESPACE_MAX_LENGTH
|
|
4345
|
+
);
|
|
4346
|
+
}
|
|
4347
|
+
|
|
3906
4348
|
// ../shared_libs/play-runtime/tool-result.ts
|
|
3907
4349
|
var TARGET_FALLBACK_KEYS = {
|
|
3908
4350
|
email: [/^email$/i, /^address$/i, /email/i],
|
|
@@ -4250,17 +4692,31 @@ function resolveListRows(result, listExtractorPaths) {
|
|
|
4250
4692
|
);
|
|
4251
4693
|
let resolvedPath = null;
|
|
4252
4694
|
let rows = null;
|
|
4695
|
+
let emptyMatch = null;
|
|
4253
4696
|
for (const candidate of candidates) {
|
|
4254
4697
|
rows = normalizeRows(getAtPath(result, candidate));
|
|
4255
|
-
if (rows) {
|
|
4698
|
+
if (!rows) {
|
|
4699
|
+
continue;
|
|
4700
|
+
}
|
|
4701
|
+
if (rows.length > 0) {
|
|
4256
4702
|
resolvedPath = candidate;
|
|
4257
4703
|
break;
|
|
4258
4704
|
}
|
|
4705
|
+
emptyMatch ??= { path: candidate, rows };
|
|
4706
|
+
}
|
|
4707
|
+
if (!rows && emptyMatch) {
|
|
4708
|
+
resolvedPath = emptyMatch.path;
|
|
4709
|
+
rows = emptyMatch.rows;
|
|
4259
4710
|
}
|
|
4260
4711
|
if (!rows) continue;
|
|
4261
4712
|
const storedPath = resolvedPath ?? path;
|
|
4262
4713
|
const name = storedPath.split(".").filter(Boolean).at(-1)?.replace(/\[\d+\]$/, "");
|
|
4263
|
-
|
|
4714
|
+
const listName = name || storedPath;
|
|
4715
|
+
const existing = lists[listName];
|
|
4716
|
+
if (existing?.rows.length && rows.length === 0) {
|
|
4717
|
+
continue;
|
|
4718
|
+
}
|
|
4719
|
+
lists[listName] = { path: storedPath, rows };
|
|
4264
4720
|
}
|
|
4265
4721
|
return lists;
|
|
4266
4722
|
}
|
|
@@ -4408,10 +4864,24 @@ function buildExtractedAccessors(targets) {
|
|
|
4408
4864
|
})
|
|
4409
4865
|
);
|
|
4410
4866
|
}
|
|
4411
|
-
function buildListAccessors(resolved, lists) {
|
|
4867
|
+
function buildListAccessors(resolved, lists, toolId, executionDiscriminator) {
|
|
4412
4868
|
return Object.fromEntries(
|
|
4413
4869
|
Object.entries(lists).map(([name, metadata]) => {
|
|
4414
4870
|
const rows = resolved[name]?.rows ?? [];
|
|
4871
|
+
const datasetDiscriminator = `${executionDiscriminator}:${listRowsFingerprint(rows)}`;
|
|
4872
|
+
const dataset = createPlayDataset(rows, {
|
|
4873
|
+
kind: "csv",
|
|
4874
|
+
sourceLabel: metadata.path,
|
|
4875
|
+
tableNamespace: listTableNamespace(
|
|
4876
|
+
toolId,
|
|
4877
|
+
name,
|
|
4878
|
+
metadata.path,
|
|
4879
|
+
datasetDiscriminator
|
|
4880
|
+
),
|
|
4881
|
+
datasetId: `tool-list:${sha256Hex(
|
|
4882
|
+
`${toolId}:${metadata.path}:${datasetDiscriminator}`
|
|
4883
|
+
)}`
|
|
4884
|
+
});
|
|
4415
4885
|
const accessor = {
|
|
4416
4886
|
path: metadata.path,
|
|
4417
4887
|
count: metadata.count,
|
|
@@ -4419,7 +4889,7 @@ function buildListAccessors(resolved, lists) {
|
|
|
4419
4889
|
};
|
|
4420
4890
|
Object.defineProperty(accessor, "get", {
|
|
4421
4891
|
value() {
|
|
4422
|
-
return
|
|
4892
|
+
return dataset;
|
|
4423
4893
|
},
|
|
4424
4894
|
enumerable: false
|
|
4425
4895
|
});
|
|
@@ -4427,6 +4897,37 @@ function buildListAccessors(resolved, lists) {
|
|
|
4427
4897
|
})
|
|
4428
4898
|
);
|
|
4429
4899
|
}
|
|
4900
|
+
function listRowsFingerprint(rows) {
|
|
4901
|
+
try {
|
|
4902
|
+
return sha256Hex(
|
|
4903
|
+
JSON.stringify(
|
|
4904
|
+
{
|
|
4905
|
+
count: rows.length,
|
|
4906
|
+
rows
|
|
4907
|
+
},
|
|
4908
|
+
(_key, value) => typeof value === "bigint" ? value.toString() : value
|
|
4909
|
+
)
|
|
4910
|
+
).slice(0, 12);
|
|
4911
|
+
} catch {
|
|
4912
|
+
return sha256Hex(String(rows.length)).slice(0, 12);
|
|
4913
|
+
}
|
|
4914
|
+
}
|
|
4915
|
+
function listTableNamespace(toolId, name, path, discriminator) {
|
|
4916
|
+
const raw = `${toolId}_${name || path || "rows"}_${sha256Hex(discriminator).slice(0, 10)}`;
|
|
4917
|
+
try {
|
|
4918
|
+
return normalizeTableNamespace(raw);
|
|
4919
|
+
} catch {
|
|
4920
|
+
const hash = sha256Hex(raw).slice(0, 10);
|
|
4921
|
+
const leaf = name || path.split(".").filter(Boolean).at(-1) || "rows";
|
|
4922
|
+
let prefix = "rows";
|
|
4923
|
+
try {
|
|
4924
|
+
prefix = normalizeTableNamespace(leaf).slice(0, 52) || "rows";
|
|
4925
|
+
} catch {
|
|
4926
|
+
prefix = "rows";
|
|
4927
|
+
}
|
|
4928
|
+
return normalizeTableNamespace(`${prefix}_${hash}`);
|
|
4929
|
+
}
|
|
4930
|
+
}
|
|
4430
4931
|
function createToolExecuteResult(input) {
|
|
4431
4932
|
const result = toResultEnvelope(input.result);
|
|
4432
4933
|
const resultRoot = {
|
|
@@ -4457,7 +4958,12 @@ function createToolExecuteResult(input) {
|
|
|
4457
4958
|
...result.meta ? { meta: result.meta } : {}
|
|
4458
4959
|
};
|
|
4459
4960
|
const extractedValues = buildExtractedAccessors(targets);
|
|
4460
|
-
const extractedLists = buildListAccessors(
|
|
4961
|
+
const extractedLists = buildListAccessors(
|
|
4962
|
+
resolvedLists,
|
|
4963
|
+
lists,
|
|
4964
|
+
input.metadata.toolId,
|
|
4965
|
+
input.jobId ?? input.execution.cacheKey ?? "inline"
|
|
4966
|
+
);
|
|
4461
4967
|
const wrapper = {
|
|
4462
4968
|
status: input.status,
|
|
4463
4969
|
...input.jobId ? { job_id: input.jobId } : {},
|
|
@@ -4995,7 +5501,7 @@ function getDefinedPlayMetadata(value) {
|
|
|
4995
5501
|
// src/tool-output.ts
|
|
4996
5502
|
import { mkdirSync as mkdirSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
4997
5503
|
import { homedir as homedir4 } from "os";
|
|
4998
|
-
import { join as join3 } from "path";
|
|
5504
|
+
import { dirname as dirname2, join as join3 } from "path";
|
|
4999
5505
|
function isPlainObject(value) {
|
|
5000
5506
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
5001
5507
|
}
|
|
@@ -5068,16 +5574,24 @@ function tryConvertToList(payload, options) {
|
|
|
5068
5574
|
(entry) => typeof entry === "string" && entry.trim().length > 0
|
|
5069
5575
|
) : [];
|
|
5070
5576
|
if (listExtractorPaths.length > 0) {
|
|
5577
|
+
let emptyMatch = null;
|
|
5071
5578
|
for (const root of candidateRoots(payload)) {
|
|
5072
5579
|
for (const extractorPath of listExtractorPaths) {
|
|
5073
5580
|
const resolved = getByDottedPath(root.value, extractorPath);
|
|
5074
5581
|
const rows = normalizeRows2(resolved);
|
|
5075
|
-
if (rows
|
|
5076
|
-
|
|
5582
|
+
if (!rows) {
|
|
5583
|
+
continue;
|
|
5584
|
+
}
|
|
5585
|
+
const sourcePath = root.path ? `${root.path}.${extractorPath}` : extractorPath;
|
|
5586
|
+
if (rows.length > 0) {
|
|
5077
5587
|
return { rows, strategy: "configured_paths", sourcePath };
|
|
5078
5588
|
}
|
|
5589
|
+
emptyMatch ??= { rows, strategy: "configured_paths", sourcePath };
|
|
5079
5590
|
}
|
|
5080
5591
|
}
|
|
5592
|
+
if (emptyMatch) {
|
|
5593
|
+
return emptyMatch;
|
|
5594
|
+
}
|
|
5081
5595
|
}
|
|
5082
5596
|
for (const root of candidateRoots(payload)) {
|
|
5083
5597
|
const candidate = findBestArrayCandidate(root.value, root.path ?? "");
|
|
@@ -5101,9 +5615,9 @@ function writeJsonOutputFile(payload, stem) {
|
|
|
5101
5615
|
writeFileSync2(outputPath, JSON.stringify(payload, null, 2), "utf-8");
|
|
5102
5616
|
return outputPath;
|
|
5103
5617
|
}
|
|
5104
|
-
function writeCsvOutputFile(rows, stem) {
|
|
5105
|
-
const
|
|
5106
|
-
|
|
5618
|
+
function writeCsvOutputFile(rows, stem, options) {
|
|
5619
|
+
const outputPath = options?.outPath ? options.outPath : join3(ensureOutputDir(), `${stem}_${Date.now()}.csv`);
|
|
5620
|
+
mkdirSync2(dirname2(outputPath), { recursive: true });
|
|
5107
5621
|
const seen = /* @__PURE__ */ new Set();
|
|
5108
5622
|
const columns = [];
|
|
5109
5623
|
for (const row of rows) {
|