@platforma-sdk/workflow-tengo 6.3.3 → 6.5.0
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/tengo/lib/exec.constants.lib.tengo +18 -1
- package/dist/tengo/lib/exec.formula.lib.tengo +327 -0
- package/dist/tengo/lib/exec.lib.tengo +248 -9
- package/dist/tengo/lib/feats.lib.tengo +6 -1
- package/dist/tengo/lib/file.internal.lib.tengo +35 -3
- package/dist/tengo/lib/file.lib.tengo +4 -0
- package/dist/tengo/lib/pt.lib.tengo +25 -0
- package/dist/tengo/tpl/annotations.compute.plj.gz +0 -0
- package/dist/tengo/tpl/anonymize.deanonymize.plj.gz +0 -0
- package/dist/tengo/tpl/anonymize.impl.plj.gz +0 -0
- package/dist/tengo/tpl/check_network.create_workdir_from_storage.plj.gz +0 -0
- package/dist/tengo/tpl/check_network.download_blob.plj.gz +0 -0
- package/dist/tengo/tpl/check_network.run_hello_world.plj.gz +0 -0
- package/dist/tengo/tpl/check_network.run_hello_world_py.plj.gz +0 -0
- package/dist/tengo/tpl/check_network.upload_blob.plj.gz +0 -0
- package/dist/tengo/tpl/check_network.upload_template.plj.gz +0 -0
- package/dist/tengo/tpl/check_network.workdir_type_name_extractor.plj.gz +0 -0
- package/dist/tengo/tpl/exec.conda.create-env.plj.gz +0 -0
- package/dist/tengo/tpl/exec.delayed-compute-allocation.impl.plj.gz +0 -0
- package/dist/tengo/tpl/exec.exec-impl.plj.gz +0 -0
- package/dist/tengo/tpl/exec.exec.plj.gz +0 -0
- package/dist/tengo/tpl/exec.load-software.impl.plj.gz +0 -0
- package/dist/tengo/tpl/exec.monetization_info.plj.gz +0 -0
- package/dist/tengo/tpl/exec.monetization_to_json.plj.gz +0 -0
- package/dist/tengo/tpl/exec.python.create-venv.plj.gz +0 -0
- package/dist/tengo/tpl/exec.python.install-deps.plj.gz +0 -0
- package/dist/tengo/tpl/exec.python.venv-bin-path.plj.gz +0 -0
- package/dist/tengo/tpl/ll.get-field.plj.gz +0 -0
- package/dist/tengo/tpl/pframes.build-table.plj.gz +0 -0
- package/dist/tengo/tpl/pframes.export-multiple-pcolumns.plj.gz +0 -0
- package/dist/tengo/tpl/pframes.export-parquet-pcolumn-chunk.plj.gz +0 -0
- package/dist/tengo/tpl/pframes.export-pframe-for-ui.plj.gz +0 -0
- package/dist/tengo/tpl/pframes.export-pframe.plj.gz +0 -0
- package/dist/tengo/tpl/pframes.export-single-pcolumn.plj.gz +0 -0
- package/dist/tengo/tpl/pframes.import-dir.plj.gz +0 -0
- package/dist/tengo/tpl/pframes.merge-resource-maps.plj.gz +0 -0
- package/dist/tengo/tpl/pframes.parse-to-json.plj.gz +0 -0
- package/dist/tengo/tpl/pframes.process-pcolumn-batch-split.plj.gz +0 -0
- package/dist/tengo/tpl/pframes.process-pcolumn-batch.plj.gz +0 -0
- package/dist/tengo/tpl/pframes.process-pcolumn-data.plj.gz +0 -0
- package/dist/tengo/tpl/pframes.remove-nulls.plj.gz +0 -0
- package/dist/tengo/tpl/pframes.slice-data.plj.gz +0 -0
- package/dist/tengo/tpl/pframes.xsv-export-pframe.plj.gz +0 -0
- package/dist/tengo/tpl/pframes.xsv-import-if-not-null.plj.gz +0 -0
- package/dist/tengo/tpl/pframes.xsv-import-map.plj.gz +0 -0
- package/dist/tengo/tpl/pt.import-dir.plj.gz +0 -0
- package/dist/tengo/tpl/pt.workflow-run.plj.gz +0 -0
- package/dist/tengo/tpl/waiter.waiter.plj.gz +0 -0
- package/dist/tengo/tpl/workdir.save.plj.gz +0 -0
- package/dist/tengo/tpl/workflow.build-ctx.plj.gz +0 -0
- package/dist/tengo/tpl/workflow.query-anchored.plj.gz +0 -0
- package/dist/tengo/tpl/workflow.query-context-filter.plj.gz +0 -0
- package/package.json +2 -2
|
@@ -16,6 +16,19 @@ UI_TASKS_QUEUE := "ui-tasks"
|
|
|
16
16
|
RUNNER_BATCH := "batch" // batch system execution (k8s jobs, etc.)
|
|
17
17
|
RUNNER_EXECUTOR := "executor" // local binary execution
|
|
18
18
|
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
META_INPUT_MEM_FORMULA := "__memFormula__"
|
|
29
|
+
META_INPUT_CPU_FORMULA := "__cpuFormula__"
|
|
30
|
+
REGULAR_INPUT_LINE_COUNT := "__metric_lineCount__"
|
|
31
|
+
|
|
19
32
|
export ll.toStrict({
|
|
20
33
|
ARG_TYPE_STRING: ARG_TYPE_STRING,
|
|
21
34
|
ARG_TYPE_EXPRESSION: ARG_TYPE_EXPRESSION,
|
|
@@ -30,5 +43,9 @@ export ll.toStrict({
|
|
|
30
43
|
HEAVY_QUEUE: HEAVY_QUEUE,
|
|
31
44
|
|
|
32
45
|
RUNNER_BATCH: RUNNER_BATCH,
|
|
33
|
-
RUNNER_EXECUTOR: RUNNER_EXECUTOR
|
|
46
|
+
RUNNER_EXECUTOR: RUNNER_EXECUTOR,
|
|
47
|
+
|
|
48
|
+
META_INPUT_MEM_FORMULA: META_INPUT_MEM_FORMULA,
|
|
49
|
+
META_INPUT_CPU_FORMULA: META_INPUT_CPU_FORMULA,
|
|
50
|
+
REGULAR_INPUT_LINE_COUNT: REGULAR_INPUT_LINE_COUNT
|
|
34
51
|
})
|
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
ll := import("@platforma-sdk/workflow-tengo:ll")
|
|
33
|
+
text := import("text")
|
|
34
|
+
slices := import("@platforma-sdk/workflow-tengo:slices")
|
|
35
|
+
maps := import("@platforma-sdk/workflow-tengo:maps")
|
|
36
|
+
sets := import("@platforma-sdk/workflow-tengo:sets")
|
|
37
|
+
units := import("@platforma-sdk/workflow-tengo:units")
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
_KNOWN_OPS := sets.fromSlice([
|
|
55
|
+
"const", "metric", "metricSum",
|
|
56
|
+
"add", "sub", "mul", "div", "divCeil",
|
|
57
|
+
"max", "min", "clamp",
|
|
58
|
+
"gt", "gte", "lt", "lte", "and", "or", "not",
|
|
59
|
+
"if"
|
|
60
|
+
])
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
_BOOL_OPS := sets.fromSlice(["gt", "gte", "lt", "lte", "and", "or", "not"])
|
|
65
|
+
|
|
66
|
+
_wrap := func(x) {
|
|
67
|
+
if is_map(x) && !is_undefined(x.op) {
|
|
68
|
+
ll.assert(sets.hasElement(_KNOWN_OPS, x.op), "exec.formula: not a valid expression node (unknown op %v)", x.op)
|
|
69
|
+
return x
|
|
70
|
+
}
|
|
71
|
+
ll.assert(is_int(x), "exec.formula: expected an expression node or an integer, got %v", x)
|
|
72
|
+
return { op: "const", value: x }
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
_bin := func(op, a, b) { return { op: op, a: _wrap(a), b: _wrap(b) } }
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
_metric := func(metricName, args) {
|
|
79
|
+
node := { op: "metric", metric: metricName }
|
|
80
|
+
for arg in args {
|
|
81
|
+
if is_string(arg) {
|
|
82
|
+
ll.assert(is_undefined(node.tag), "exec.formula.%s: tag specified more than once", metricName)
|
|
83
|
+
node.tag = arg
|
|
84
|
+
} else if is_map(arg) && !is_undefined(arg.default) {
|
|
85
|
+
ll.assert(is_undefined(node.default), "exec.formula.%s: default specified more than once", metricName)
|
|
86
|
+
ll.assert(is_int(arg.default), "exec.formula.%s: default must be an integer", metricName)
|
|
87
|
+
node.default = arg.default
|
|
88
|
+
} else {
|
|
89
|
+
ll.panic("exec.formula.%s: unexpected argument %v", metricName, arg)
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return node
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
evaluate := undefined
|
|
96
|
+
evaluate = func(node, resolver) {
|
|
97
|
+
op := node.op
|
|
98
|
+
if op == "const" { return node.value }
|
|
99
|
+
if op == "metricSum" {
|
|
100
|
+
fn := resolver[node.metric]
|
|
101
|
+
ll.assert(!is_undefined(fn), "exec.formula.evaluate: no resolver for metric %q", node.metric)
|
|
102
|
+
return fn(node.files)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if op == "add" { return evaluate(node.a, resolver) + evaluate(node.b, resolver) }
|
|
106
|
+
if op == "sub" { return evaluate(node.a, resolver) - evaluate(node.b, resolver) }
|
|
107
|
+
if op == "mul" { return evaluate(node.a, resolver) * evaluate(node.b, resolver) }
|
|
108
|
+
if op == "div" {
|
|
109
|
+
b := evaluate(node.b, resolver)
|
|
110
|
+
ll.assert(b != 0, "exec.formula.evaluate: division by zero")
|
|
111
|
+
return evaluate(node.a, resolver) / b
|
|
112
|
+
}
|
|
113
|
+
if op == "divCeil" {
|
|
114
|
+
b := evaluate(node.b, resolver)
|
|
115
|
+
ll.assert(b != 0, "exec.formula.evaluate: division by zero")
|
|
116
|
+
a := evaluate(node.a, resolver)
|
|
117
|
+
|
|
118
|
+
return (a + b - 1) / b
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if op == "max" { a := evaluate(node.a, resolver); b := evaluate(node.b, resolver); return a > b ? a : b }
|
|
122
|
+
if op == "min" { a := evaluate(node.a, resolver); b := evaluate(node.b, resolver); return a < b ? a : b }
|
|
123
|
+
if op == "clamp" {
|
|
124
|
+
v := evaluate(node.value, resolver)
|
|
125
|
+
lo := evaluate(node.lo, resolver)
|
|
126
|
+
hi := evaluate(node.hi, resolver)
|
|
127
|
+
ll.assert(lo <= hi, "exec.formula.clamp: lo (%v) must be <= hi (%v) — inverted bounds collapse every input to hi", lo, hi)
|
|
128
|
+
if v < lo { v = lo }
|
|
129
|
+
if v > hi { v = hi }
|
|
130
|
+
return v
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if op == "gt" { return evaluate(node.a, resolver) > evaluate(node.b, resolver) }
|
|
134
|
+
if op == "gte" { return evaluate(node.a, resolver) >= evaluate(node.b, resolver) }
|
|
135
|
+
if op == "lt" { return evaluate(node.a, resolver) < evaluate(node.b, resolver) }
|
|
136
|
+
if op == "lte" { return evaluate(node.a, resolver) <= evaluate(node.b, resolver) }
|
|
137
|
+
if op == "and" { return evaluate(node.a, resolver) && evaluate(node.b, resolver) }
|
|
138
|
+
if op == "or" { return evaluate(node.a, resolver) || evaluate(node.b, resolver) }
|
|
139
|
+
if op == "not" { return !evaluate(node.a, resolver) }
|
|
140
|
+
|
|
141
|
+
if op == "if" { return evaluate(node.cond, resolver) ? evaluate(node.then, resolver) : evaluate(node["else"], resolver) }
|
|
142
|
+
|
|
143
|
+
ll.panic("exec.formula.evaluate: unknown op %q", op)
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
evaluateResource := func(node, resolver, label) {
|
|
156
|
+
ll.assert(!sets.hasElement(_BOOL_OPS, node.op),
|
|
157
|
+
"exec resource formula (%s) must compute a number, but its top-level op is %q (a comparison/logic op). Use comparisons and logic only inside f.if(...).",
|
|
158
|
+
label, node.op)
|
|
159
|
+
v := evaluate(node, resolver)
|
|
160
|
+
ll.assert(is_int(v) && v > 0,
|
|
161
|
+
"exec resource formula (%s) must evaluate to a positive integer, got %v. If a metric can be zero or a subtraction can underflow, floor it with f.max(...) or f.clamp(...).",
|
|
162
|
+
label, v)
|
|
163
|
+
return v
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
_LINECOUNT_OK := sets.fromSlice(["csv", "tsv", "txt", "fastq", "fq", "fasta", "fa", "tab"])
|
|
173
|
+
_COMPRESSION_EXT := sets.fromSlice(["gz", "bz2", "zst"])
|
|
174
|
+
|
|
175
|
+
_assertMetricCompatible := func(metric, fileName) {
|
|
176
|
+
if metric == "lineCount" {
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
parts := text.split(fileName, ".")
|
|
183
|
+
if len(parts) >= 2 && sets.hasElement(_COMPRESSION_EXT, text.to_lower(parts[len(parts)-1])) {
|
|
184
|
+
parts = parts[0:len(parts)-1]
|
|
185
|
+
}
|
|
186
|
+
ext := len(parts) >= 2 ? parts[len(parts)-1] : ""
|
|
187
|
+
ll.assert(sets.hasElement(_LINECOUNT_OK, text.to_lower(ext)),
|
|
188
|
+
"exec.formula: lineCount is not supported for file %q (extension %q is not a line-oriented text format)", fileName, ext)
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
resolveAst := undefined
|
|
194
|
+
resolveAst = func(node, tagMap, allFiles) {
|
|
195
|
+
op := node.op
|
|
196
|
+
if op == "metric" {
|
|
197
|
+
files := is_undefined(node.tag) ? allFiles : (is_undefined(tagMap[node.tag]) ? [] : tagMap[node.tag])
|
|
198
|
+
if len(files) == 0 {
|
|
199
|
+
if is_undefined(node.tag) {
|
|
200
|
+
ll.assert(!is_undefined(node.default),
|
|
201
|
+
"exec.formula: f.%s() references all input files but the exec has none, and no { default: ... } was given", node.metric)
|
|
202
|
+
} else {
|
|
203
|
+
ll.assert(!is_undefined(node.default),
|
|
204
|
+
"exec.formula: tag %q has no files and no { default: ... } was given", node.tag)
|
|
205
|
+
}
|
|
206
|
+
return { op: "const", value: node.default }
|
|
207
|
+
}
|
|
208
|
+
for fn in files { _assertMetricCompatible(node.metric, fn) }
|
|
209
|
+
files = slices.quickSort(files)
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
return { op: "metricSum", metric: node.metric, files: files }
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
return maps.mapValues(node, func(v) {
|
|
219
|
+
return is_map(v) && !is_undefined(v.op) ? resolveAst(v, tagMap, allFiles) : v
|
|
220
|
+
})
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
referencedMetricFiles := func(resolvedNode) {
|
|
224
|
+
acc := {}
|
|
225
|
+
walk := undefined
|
|
226
|
+
walk = func(n) {
|
|
227
|
+
if n.op == "metricSum" {
|
|
228
|
+
if n.metric != "size" {
|
|
229
|
+
existing := is_undefined(acc[n.metric]) ? [] : acc[n.metric]
|
|
230
|
+
for fn in n.files { existing = append(existing, fn) }
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
acc[n.metric] = slices.unique(existing)
|
|
235
|
+
}
|
|
236
|
+
return
|
|
237
|
+
}
|
|
238
|
+
for k, v in n {
|
|
239
|
+
if is_map(v) && !is_undefined(v.op) { walk(v) }
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
walk(resolvedNode)
|
|
243
|
+
return acc
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
applyFormulaFallback := func(dims) {
|
|
259
|
+
res := { ram: dims.ram.static, cpu: dims.cpu.static, err: undefined }
|
|
260
|
+
if !is_undefined(dims.ram.ast) && is_undefined(res.ram) {
|
|
261
|
+
if is_undefined(dims.ram.fallback) {
|
|
262
|
+
res.err = "exec.builder: memFormula needs a static fallback on backends that can't evaluate resource formulas at run time. Provide { fallback: ... } on memFormula, set a static .mem(), or upgrade the backend."
|
|
263
|
+
return res
|
|
264
|
+
}
|
|
265
|
+
res.ram = dims.ram.fallback
|
|
266
|
+
}
|
|
267
|
+
if !is_undefined(dims.cpu.ast) && is_undefined(res.cpu) {
|
|
268
|
+
if is_undefined(dims.cpu.fallback) {
|
|
269
|
+
res.err = "exec.builder: cpuFormula needs a static fallback on backends that can't evaluate resource formulas at run time. Provide { fallback: ... } on cpuFormula, set a static .cpu(), or upgrade the backend."
|
|
270
|
+
return res
|
|
271
|
+
}
|
|
272
|
+
res.cpu = dims.cpu.fallback
|
|
273
|
+
}
|
|
274
|
+
return res
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
export {
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
size: func(...args) { return _metric("size", args) },
|
|
284
|
+
lineCount: func(...args) { return _metric("lineCount", args) },
|
|
285
|
+
|
|
286
|
+
gib: func(n) { ll.assert(is_int(n), "exec.formula.gib: n must be an integer"); return { op: "const", value: n * units.GiB } },
|
|
287
|
+
mib: func(n) { ll.assert(is_int(n), "exec.formula.mib: n must be an integer"); return { op: "const", value: n * units.MiB } },
|
|
288
|
+
kib: func(n) { ll.assert(is_int(n), "exec.formula.kib: n must be an integer"); return { op: "const", value: n * units.KiB } },
|
|
289
|
+
gb: func(n) { ll.assert(is_int(n), "exec.formula.gb: n must be an integer"); return { op: "const", value: n * units.GB } },
|
|
290
|
+
mb: func(n) { ll.assert(is_int(n), "exec.formula.mb: n must be an integer"); return { op: "const", value: n * units.MB } },
|
|
291
|
+
kb: func(n) { ll.assert(is_int(n), "exec.formula.kb: n must be an integer"); return { op: "const", value: n * units.KB } },
|
|
292
|
+
|
|
293
|
+
add: func(a, b) { return _bin("add", a, b) },
|
|
294
|
+
sub: func(a, b) { return _bin("sub", a, b) },
|
|
295
|
+
mul: func(a, b) { return _bin("mul", a, b) },
|
|
296
|
+
div: func(a, b) { return _bin("div", a, b) },
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
divCeil: func(a, b) { return _bin("divCeil", a, b) },
|
|
301
|
+
|
|
302
|
+
max: func(a, b) { return _bin("max", a, b) },
|
|
303
|
+
min: func(a, b) { return _bin("min", a, b) },
|
|
304
|
+
clamp: func(value, lo, hi) { return { op: "clamp", value: _wrap(value), lo: _wrap(lo), hi: _wrap(hi) } },
|
|
305
|
+
|
|
306
|
+
gt: func(a, b) { return _bin("gt", a, b) },
|
|
307
|
+
gte: func(a, b) { return _bin("gte", a, b) },
|
|
308
|
+
lt: func(a, b) { return _bin("lt", a, b) },
|
|
309
|
+
lte: func(a, b) { return _bin("lte", a, b) },
|
|
310
|
+
and: func(a, b) { return _bin("and", a, b) },
|
|
311
|
+
or: func(a, b) { return _bin("or", a, b) },
|
|
312
|
+
not: func(a) { return { op: "not", a: _wrap(a) } },
|
|
313
|
+
|
|
314
|
+
"if": func(cond, then, els) { return { op: "if", cond: _wrap(cond), then: _wrap(then), "else": _wrap(els) } },
|
|
315
|
+
|
|
316
|
+
evaluateResource: evaluateResource,
|
|
317
|
+
resolveAst: resolveAst,
|
|
318
|
+
referencedMetricFiles: referencedMetricFiles,
|
|
319
|
+
applyFormulaFallback: applyFormulaFallback,
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
|
|
325
|
+
|
|
326
|
+
_internal: { evaluate: evaluate }
|
|
327
|
+
}
|
|
@@ -19,6 +19,7 @@ constants := import("@platforma-sdk/workflow-tengo:constants")
|
|
|
19
19
|
canonical := import("@platforma-sdk/workflow-tengo:canonical")
|
|
20
20
|
monetization := import("@platforma-sdk/workflow-tengo:exec.monetization_internal")
|
|
21
21
|
execConstants := import("@platforma-sdk/workflow-tengo:exec.constants")
|
|
22
|
+
execFormula := import("@platforma-sdk/workflow-tengo:exec.formula")
|
|
22
23
|
units := import("@platforma-sdk/workflow-tengo:units")
|
|
23
24
|
feats := import("@platforma-sdk/workflow-tengo:feats")
|
|
24
25
|
|
|
@@ -27,6 +28,34 @@ feats := import("@platforma-sdk/workflow-tengo:feats")
|
|
|
27
28
|
|
|
28
29
|
|
|
29
30
|
|
|
31
|
+
lineCounterSoft := assets.importSoftware("@platforma-open/milaboratories.software-small-binaries:line-counter")
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
_lineCountResource := undefined
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
_assertValidCpuRequest := func(amount, ctx) {
|
|
46
|
+
validation.assertType(amount, "number", ctx + ": amount of cores must be a number")
|
|
47
|
+
ll.assert(amount > 0, ctx + ": amount of cores should be greater than 0")
|
|
48
|
+
}
|
|
49
|
+
_assertValidMemRequest := func(amount, ctx) {
|
|
50
|
+
validation.assertType(amount, ["or", "number", "string"], ctx + ": RAM amount should be a number or string")
|
|
51
|
+
ll.assert(is_string(amount) || amount >= 16 * units.MiB, ctx + ": amount in bytes should be at least 16MiB")
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
|
|
30
59
|
builder := func() {
|
|
31
60
|
self := undefined
|
|
32
61
|
|
|
@@ -55,6 +84,13 @@ builder := func() {
|
|
|
55
84
|
ramRequest := undefined
|
|
56
85
|
gpuMemory := undefined
|
|
57
86
|
|
|
87
|
+
|
|
88
|
+
memFormulaAst := undefined
|
|
89
|
+
memFormulaFallback := undefined
|
|
90
|
+
cpuFormulaAst := undefined
|
|
91
|
+
cpuFormulaFallback := undefined
|
|
92
|
+
fileTags := {} // fileName -> tag (for f.size("tag") / f.lineCount("tag") aggregation)
|
|
93
|
+
|
|
58
94
|
commandName := ""
|
|
59
95
|
cache := 0
|
|
60
96
|
inputCache := 0
|
|
@@ -405,8 +441,7 @@ builder := func() {
|
|
|
405
441
|
|
|
406
442
|
|
|
407
443
|
cpu: func(amount) {
|
|
408
|
-
|
|
409
|
-
ll.assert(amount > 0, "exec.builder.cpu: amount of cores should be greater than 0")
|
|
444
|
+
_assertValidCpuRequest(amount, "exec.builder.cpu")
|
|
410
445
|
cpuRequest = amount
|
|
411
446
|
|
|
412
447
|
return self
|
|
@@ -424,8 +459,7 @@ builder := func() {
|
|
|
424
459
|
|
|
425
460
|
|
|
426
461
|
mem: func(amount) {
|
|
427
|
-
|
|
428
|
-
ll.assert(is_string(amount) || amount >= 16 * units.MiB, "exec.builder.mem: amount in bytes should be at least 16MiB")
|
|
462
|
+
_assertValidMemRequest(amount, "exec.builder.mem")
|
|
429
463
|
ramRequest = amount
|
|
430
464
|
|
|
431
465
|
return self
|
|
@@ -448,6 +482,89 @@ builder := func() {
|
|
|
448
482
|
|
|
449
483
|
|
|
450
484
|
|
|
485
|
+
|
|
486
|
+
|
|
487
|
+
|
|
488
|
+
|
|
489
|
+
|
|
490
|
+
|
|
491
|
+
|
|
492
|
+
|
|
493
|
+
|
|
494
|
+
|
|
495
|
+
|
|
496
|
+
|
|
497
|
+
|
|
498
|
+
|
|
499
|
+
|
|
500
|
+
|
|
501
|
+
|
|
502
|
+
|
|
503
|
+
|
|
504
|
+
|
|
505
|
+
|
|
506
|
+
memFormula: func(ast, ...opts) {
|
|
507
|
+
ll.assert(is_map(ast) && !is_undefined(ast.op), "exec.builder.memFormula: expected a formula node from exec.formula")
|
|
508
|
+
memFormulaAst = ast
|
|
509
|
+
if len(opts) > 0 && ll.isMap(opts[0]) {
|
|
510
|
+
for k, _ in opts[0] {
|
|
511
|
+
ll.assert(k == "fallback", "exec.builder.memFormula: unknown option %q (only { fallback } is supported)", k)
|
|
512
|
+
}
|
|
513
|
+
if !is_undefined(opts[0].fallback) {
|
|
514
|
+
_assertValidMemRequest(opts[0].fallback, "exec.builder.memFormula fallback")
|
|
515
|
+
memFormulaFallback = opts[0].fallback
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
return self
|
|
519
|
+
},
|
|
520
|
+
|
|
521
|
+
|
|
522
|
+
|
|
523
|
+
|
|
524
|
+
|
|
525
|
+
|
|
526
|
+
|
|
527
|
+
|
|
528
|
+
|
|
529
|
+
|
|
530
|
+
|
|
531
|
+
|
|
532
|
+
|
|
533
|
+
|
|
534
|
+
|
|
535
|
+
|
|
536
|
+
|
|
537
|
+
|
|
538
|
+
|
|
539
|
+
|
|
540
|
+
|
|
541
|
+
|
|
542
|
+
|
|
543
|
+
|
|
544
|
+
|
|
545
|
+
|
|
546
|
+
|
|
547
|
+
cpuFormula: func(ast, ...opts) {
|
|
548
|
+
ll.assert(is_map(ast) && !is_undefined(ast.op), "exec.builder.cpuFormula: expected a formula node from exec.formula")
|
|
549
|
+
cpuFormulaAst = ast
|
|
550
|
+
if len(opts) > 0 && ll.isMap(opts[0]) {
|
|
551
|
+
for k, _ in opts[0] {
|
|
552
|
+
ll.assert(k == "fallback", "exec.builder.cpuFormula: unknown option %q (only { fallback } is supported)", k)
|
|
553
|
+
}
|
|
554
|
+
if !is_undefined(opts[0].fallback) {
|
|
555
|
+
_assertValidCpuRequest(opts[0].fallback, "exec.builder.cpuFormula fallback")
|
|
556
|
+
cpuFormulaFallback = opts[0].fallback
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
return self
|
|
560
|
+
},
|
|
561
|
+
|
|
562
|
+
|
|
563
|
+
|
|
564
|
+
|
|
565
|
+
|
|
566
|
+
|
|
567
|
+
|
|
451
568
|
|
|
452
569
|
|
|
453
570
|
gpuMemory: func(...args) {
|
|
@@ -786,8 +903,14 @@ builder := func() {
|
|
|
786
903
|
|
|
787
904
|
fileName = path.canonize(fileName)
|
|
788
905
|
filesToAdd[fileName] = file
|
|
789
|
-
if len(opts) > 0 && ll.isMap(opts[0])
|
|
790
|
-
|
|
906
|
+
if len(opts) > 0 && ll.isMap(opts[0]) {
|
|
907
|
+
if opts[0].writable == true {
|
|
908
|
+
sets.add(writableFiles, fileName)
|
|
909
|
+
}
|
|
910
|
+
if !is_undefined(opts[0].tag) {
|
|
911
|
+
ll.assert(is_string(opts[0].tag), "exec.builder().addFile: tag must be a string")
|
|
912
|
+
fileTags[fileName] = opts[0].tag
|
|
913
|
+
}
|
|
791
914
|
}
|
|
792
915
|
monetization.addOptionalArg(mnz, fileName, opts...)
|
|
793
916
|
return self
|
|
@@ -1103,14 +1226,88 @@ builder := func() {
|
|
|
1103
1226
|
if (is_int(ramRequest)) {
|
|
1104
1227
|
ramRequest = string(ramRequest) + "b"
|
|
1105
1228
|
}
|
|
1229
|
+
|
|
1230
|
+
|
|
1231
|
+
|
|
1232
|
+
|
|
1233
|
+
|
|
1234
|
+
|
|
1235
|
+
|
|
1236
|
+
|
|
1237
|
+
|
|
1238
|
+
hasFormula := !is_undefined(memFormulaAst) || !is_undefined(cpuFormulaAst)
|
|
1239
|
+
resolvedMem := undefined
|
|
1240
|
+
resolvedCpu := undefined
|
|
1241
|
+
lineCountMapResource := undefined
|
|
1242
|
+
|
|
1243
|
+
if hasFormula {
|
|
1244
|
+
|
|
1245
|
+
|
|
1246
|
+
|
|
1247
|
+
|
|
1248
|
+
|
|
1249
|
+
|
|
1250
|
+
|
|
1251
|
+
|
|
1252
|
+
canEvaluateFormulas := feats.hasBlobSize
|
|
1253
|
+
if !canEvaluateFormulas {
|
|
1254
|
+
|
|
1255
|
+
|
|
1256
|
+
|
|
1257
|
+
|
|
1258
|
+
|
|
1259
|
+
fb := execFormula.applyFormulaFallback({
|
|
1260
|
+
ram: { ast: memFormulaAst, fallback: memFormulaFallback, static: ramRequest },
|
|
1261
|
+
cpu: { ast: cpuFormulaAst, fallback: cpuFormulaFallback, static: cpuRequest }
|
|
1262
|
+
})
|
|
1263
|
+
ll.assert(is_undefined(fb.err), fb.err)
|
|
1264
|
+
ramRequest = fb.ram
|
|
1265
|
+
cpuRequest = fb.cpu
|
|
1266
|
+
if is_int(ramRequest) { ramRequest = string(ramRequest) + "b" }
|
|
1267
|
+
} else {
|
|
1268
|
+
tagMap := {}
|
|
1269
|
+
for fileName, tag in fileTags {
|
|
1270
|
+
existing := is_undefined(tagMap[tag]) ? [] : tagMap[tag]
|
|
1271
|
+
tagMap[tag] = append(existing, fileName)
|
|
1272
|
+
}
|
|
1273
|
+
allFiles := maps.getKeys(filesToAdd)
|
|
1274
|
+
|
|
1275
|
+
neededLineCount := {}
|
|
1276
|
+
if !is_undefined(memFormulaAst) {
|
|
1277
|
+
resolvedMem = execFormula.resolveAst(memFormulaAst, tagMap, allFiles)
|
|
1278
|
+
refs := execFormula.referencedMetricFiles(resolvedMem)
|
|
1279
|
+
if !is_undefined(refs.lineCount) { sets.add(neededLineCount, refs.lineCount...) }
|
|
1280
|
+
}
|
|
1281
|
+
if !is_undefined(cpuFormulaAst) {
|
|
1282
|
+
resolvedCpu = execFormula.resolveAst(cpuFormulaAst, tagMap, allFiles)
|
|
1283
|
+
refs := execFormula.referencedMetricFiles(resolvedCpu)
|
|
1284
|
+
if !is_undefined(refs.lineCount) { sets.add(neededLineCount, refs.lineCount...) }
|
|
1285
|
+
}
|
|
1286
|
+
|
|
1287
|
+
if len(neededLineCount) > 0 {
|
|
1288
|
+
perFile := {}
|
|
1289
|
+
for fn, _ in neededLineCount {
|
|
1290
|
+
perFile[fn] = _lineCountResource(fn, filesToAdd[fn])
|
|
1291
|
+
}
|
|
1292
|
+
lineCountMapResource = smart.createMapResource(perFile)
|
|
1293
|
+
}
|
|
1294
|
+
}
|
|
1295
|
+
}
|
|
1296
|
+
|
|
1106
1297
|
quotaData := {
|
|
1107
1298
|
queue: queue,
|
|
1108
1299
|
cpu: cpuRequest,
|
|
1109
1300
|
ram: ramRequest
|
|
1110
1301
|
}
|
|
1111
1302
|
if !is_undefined(gpuMemory) {
|
|
1112
|
-
|
|
1113
|
-
|
|
1303
|
+
|
|
1304
|
+
|
|
1305
|
+
|
|
1306
|
+
|
|
1307
|
+
|
|
1308
|
+
|
|
1309
|
+
ll.assert(!is_undefined(cpuRequest) || !is_undefined(cpuFormulaAst), "exec.builder: cpu() or cpuFormula() is required when gpuMemory() is set. GPU nodes vary in CPU capacity and cost; please provide an explicit CPU request.")
|
|
1310
|
+
ll.assert(!is_undefined(ramRequest) || !is_undefined(memFormulaAst), "exec.builder: mem() or memFormula() is required when gpuMemory() is set. GPU nodes vary in RAM capacity and cost; please provide an explicit RAM request.")
|
|
1114
1311
|
quotaData.gpuMemory = gpuMemory
|
|
1115
1312
|
}
|
|
1116
1313
|
metaExecInputs := {
|
|
@@ -1120,6 +1317,26 @@ builder := func() {
|
|
|
1120
1317
|
|
|
1121
1318
|
|
|
1122
1319
|
|
|
1320
|
+
|
|
1321
|
+
|
|
1322
|
+
|
|
1323
|
+
|
|
1324
|
+
|
|
1325
|
+
|
|
1326
|
+
|
|
1327
|
+
|
|
1328
|
+
|
|
1329
|
+
|
|
1330
|
+
|
|
1331
|
+
|
|
1332
|
+
|
|
1333
|
+
if !is_undefined(resolvedMem) { metaExecInputs[execConstants.META_INPUT_MEM_FORMULA] = smart.createJsonResource(resolvedMem) }
|
|
1334
|
+
if !is_undefined(resolvedCpu) { metaExecInputs[execConstants.META_INPUT_CPU_FORMULA] = smart.createJsonResource(resolvedCpu) }
|
|
1335
|
+
if !is_undefined(lineCountMapResource) { pureExecInputs[execConstants.REGULAR_INPUT_LINE_COUNT] = lineCountMapResource }
|
|
1336
|
+
|
|
1337
|
+
|
|
1338
|
+
|
|
1339
|
+
|
|
1123
1340
|
if monetization.shouldRun(mnz) {
|
|
1124
1341
|
pureExecInputs.runOptions.monetization = monetization.toJson(mnz)
|
|
1125
1342
|
}
|
|
@@ -1283,6 +1500,27 @@ builder := func() {
|
|
|
1283
1500
|
return self
|
|
1284
1501
|
}
|
|
1285
1502
|
|
|
1503
|
+
|
|
1504
|
+
|
|
1505
|
+
|
|
1506
|
+
|
|
1507
|
+
|
|
1508
|
+
_lineCountResource = func(fileName, fileRef) {
|
|
1509
|
+
countOut := "linecount.txt"
|
|
1510
|
+
res := builder().
|
|
1511
|
+
software(lineCounterSoft).
|
|
1512
|
+
addFile(fileName, fileRef).
|
|
1513
|
+
arg("--input").arg(fileName).
|
|
1514
|
+
arg("--output").arg(countOut).
|
|
1515
|
+
saveFileContent(countOut).
|
|
1516
|
+
inLightQueue().
|
|
1517
|
+
cacheInputsDays(30).
|
|
1518
|
+
mem("256MiB").
|
|
1519
|
+
cpu(1).
|
|
1520
|
+
run()
|
|
1521
|
+
return res.getFileContent(countOut)
|
|
1522
|
+
}
|
|
1523
|
+
|
|
1286
1524
|
export ll.toStrict({
|
|
1287
1525
|
builder: builder,
|
|
1288
1526
|
|
|
@@ -1290,5 +1528,6 @@ export ll.toStrict({
|
|
|
1290
1528
|
|
|
1291
1529
|
|
|
1292
1530
|
|
|
1293
|
-
hasGpu: feats.hasGpu
|
|
1531
|
+
hasGpu: feats.hasGpu,
|
|
1532
|
+
formula: execFormula
|
|
1294
1533
|
})
|
|
@@ -77,5 +77,10 @@ export ll.toStrict({
|
|
|
77
77
|
secretEnvSupport: _isEnabled("secretEnvSupport"),
|
|
78
78
|
|
|
79
79
|
|
|
80
|
-
contextDomainQuery: _isEnabled("contextDomainQuery")
|
|
80
|
+
contextDomainQuery: _isEnabled("contextDomainQuery"),
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
multiStepProgress: _isEnabled("multiStepProgress")
|
|
81
86
|
})
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
ll := import("@platforma-sdk/workflow-tengo:ll")
|
|
13
13
|
smart := import("@platforma-sdk/workflow-tengo:smart")
|
|
14
14
|
validation := import("@platforma-sdk/workflow-tengo:validation")
|
|
15
|
+
feats := import("@platforma-sdk/workflow-tengo:feats")
|
|
15
16
|
|
|
16
17
|
json := import("json")
|
|
17
18
|
|
|
@@ -19,6 +20,22 @@ json := import("json")
|
|
|
19
20
|
|
|
20
21
|
|
|
21
22
|
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
_progressField := func(importer, handleField) {
|
|
29
|
+
if feats.multiStepProgress {
|
|
30
|
+
return importer.getField("progress")
|
|
31
|
+
}
|
|
32
|
+
return smart.mapBuilder().addRef("01", handleField).build()
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
|
|
22
39
|
RTYPE_BLOB_IMPORT_EXTERNAL := { Name: "BlobImportExternal", Version: "1" }
|
|
23
40
|
RTYPE_BLOB_IMPORT_INTERNAL := { Name: "BlobImportInternal", Version: "1" }
|
|
24
41
|
RTYPE_BLOB_UPLOAD := { Name: "BlobUpload", Version: "1" }
|
|
@@ -30,6 +47,9 @@ RTYPE_BLOB_DOWNLOAD := { Name: "BlobDownload", Version: "2" }
|
|
|
30
47
|
|
|
31
48
|
|
|
32
49
|
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
|
|
33
53
|
createBlobImportExternal := func(settings) {
|
|
34
54
|
validation.assertType(settings, {
|
|
35
55
|
"dataURL": "string",
|
|
@@ -38,10 +58,12 @@ createBlobImportExternal := func(settings) {
|
|
|
38
58
|
})
|
|
39
59
|
|
|
40
60
|
importer := smart.structBuilder(RTYPE_BLOB_IMPORT_EXTERNAL, json.encode(settings)).lockAndBuild()
|
|
61
|
+
handleField := importer.getField("handle")
|
|
41
62
|
|
|
42
63
|
return ll.toStrict({
|
|
43
64
|
file: importer.getField("blob"),
|
|
44
|
-
handle:
|
|
65
|
+
handle: handleField,
|
|
66
|
+
progress: _progressField(importer, handleField)
|
|
45
67
|
})
|
|
46
68
|
}
|
|
47
69
|
|
|
@@ -51,6 +73,9 @@ createBlobImportExternal := func(settings) {
|
|
|
51
73
|
|
|
52
74
|
|
|
53
75
|
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
|
|
54
79
|
createBlobImportInternal := func(settings) {
|
|
55
80
|
validation.assertType(settings, {
|
|
56
81
|
"path": "string",
|
|
@@ -60,10 +85,12 @@ createBlobImportInternal := func(settings) {
|
|
|
60
85
|
})
|
|
61
86
|
|
|
62
87
|
importer := smart.structBuilder(RTYPE_BLOB_IMPORT_INTERNAL, json.encode(settings)).lockAndBuild()
|
|
88
|
+
handleField := importer.getField("handle")
|
|
63
89
|
|
|
64
90
|
return ll.toStrict({
|
|
65
91
|
file: importer.getField("blob"),
|
|
66
|
-
handle:
|
|
92
|
+
handle: handleField,
|
|
93
|
+
progress: _progressField(importer, handleField)
|
|
67
94
|
})
|
|
68
95
|
}
|
|
69
96
|
|
|
@@ -73,6 +100,9 @@ createBlobImportInternal := func(settings) {
|
|
|
73
100
|
|
|
74
101
|
|
|
75
102
|
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
|
|
76
106
|
createBlobUpload := func(settings) {
|
|
77
107
|
validation.assertType(settings, {
|
|
78
108
|
"modificationTime": "string",
|
|
@@ -82,10 +112,12 @@ createBlobUpload := func(settings) {
|
|
|
82
112
|
})
|
|
83
113
|
|
|
84
114
|
uploader := smart.structBuilder(RTYPE_BLOB_UPLOAD, json.encode(settings)).lockAndBuild()
|
|
115
|
+
handleField := uploader.getField("handle")
|
|
85
116
|
|
|
86
117
|
return ll.toStrict({
|
|
87
118
|
file: uploader.getField("blob"),
|
|
88
|
-
handle:
|
|
119
|
+
handle: handleField,
|
|
120
|
+
progress: _progressField(uploader, handleField)
|
|
89
121
|
})
|
|
90
122
|
}
|
|
91
123
|
|
|
@@ -442,6 +442,14 @@ workflow := func() {
|
|
|
442
442
|
|
|
443
443
|
|
|
444
444
|
|
|
445
|
+
_testGetLastRawStep: func() {
|
|
446
|
+
ll.assert(len(steps) > 0, "_testGetLastRawStep: no steps registered")
|
|
447
|
+
return steps[len(steps)-1](undefined)
|
|
448
|
+
},
|
|
449
|
+
|
|
450
|
+
|
|
451
|
+
|
|
452
|
+
|
|
445
453
|
|
|
446
454
|
|
|
447
455
|
|
|
@@ -513,6 +521,7 @@ workflow := func() {
|
|
|
513
521
|
nRowsOpt := undefined
|
|
514
522
|
ignoreErrorsOpt := undefined
|
|
515
523
|
commentPrefixOpt := undefined
|
|
524
|
+
delimiterOpt := undefined
|
|
516
525
|
|
|
517
526
|
if is_map(frameInput) && !is_undefined(frameInput.file) {
|
|
518
527
|
fileRef = frameInput.file
|
|
@@ -610,6 +619,15 @@ workflow := func() {
|
|
|
610
619
|
commentPrefixOpt = opts.commentPrefix
|
|
611
620
|
}
|
|
612
621
|
|
|
622
|
+
if !is_undefined(opts.delimiter) {
|
|
623
|
+
if !is_string(opts.delimiter) {
|
|
624
|
+
ll.panic("'delimiter' option must be a string. Got: %T", opts.delimiter)
|
|
625
|
+
}
|
|
626
|
+
ll.assert(finalFormat == "csv" || finalFormat == "tsv",
|
|
627
|
+
"'delimiter' option applies only to csv/tsv reads, not %q", finalFormat)
|
|
628
|
+
delimiterOpt = opts.delimiter
|
|
629
|
+
}
|
|
630
|
+
|
|
613
631
|
if !is_undefined(fileRef) {
|
|
614
632
|
ll.assert(
|
|
615
633
|
smart.isReference(fileRef),
|
|
@@ -682,6 +700,13 @@ workflow := func() {
|
|
|
682
700
|
if !is_undefined(commentPrefixOpt) {
|
|
683
701
|
step.commentPrefix = commentPrefixOpt
|
|
684
702
|
}
|
|
703
|
+
|
|
704
|
+
|
|
705
|
+
|
|
706
|
+
|
|
707
|
+
if !is_undefined(delimiterOpt) {
|
|
708
|
+
step.delimiter = delimiterOpt
|
|
709
|
+
}
|
|
685
710
|
}
|
|
686
711
|
|
|
687
712
|
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@platforma-sdk/workflow-tengo",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.5.0",
|
|
4
4
|
"description": "Tengo SDK library",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"dependencies": {
|
|
19
19
|
"@milaboratories/pframes-rs-wasip2": "1.1.44",
|
|
20
20
|
"@milaboratories/software-pframes-conv": "2.2.9",
|
|
21
|
-
"@platforma-open/milaboratories.software-small-binaries": "^2.
|
|
21
|
+
"@platforma-open/milaboratories.software-small-binaries": "^2.1.1",
|
|
22
22
|
"@platforma-open/milaboratories.software-ptexter": "1.2.2",
|
|
23
23
|
"@platforma-open/milaboratories.software-ptabler": "2.1.1"
|
|
24
24
|
},
|