@platforma-sdk/workflow-tengo 5.7.2 → 5.8.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.
Files changed (55) hide show
  1. package/dist/tengo/lib/annotations.lib.tengo +1 -1
  2. package/dist/tengo/lib/exec.constants.lib.tengo +8 -1
  3. package/dist/tengo/lib/exec.limits.lib.tengo +18 -12
  4. package/dist/tengo/lib/exec.runcmd.lib.tengo +6 -13
  5. package/dist/tengo/lib/feats.lib.tengo +15 -0
  6. package/dist/tengo/lib/pframes.lib.tengo +1 -0
  7. package/dist/tengo/lib/pframes.util.lib.tengo +7 -1
  8. package/dist/tengo/lib/pframes.xsv-builder.lib.tengo +2 -1
  9. package/dist/tengo/lib/pframes.xsv-import-file.lib.tengo +5 -1
  10. package/dist/tengo/lib/pframes.xsv-import-pt.lib.tengo +6 -1
  11. package/dist/tengo/lib/pframes.xsv.lib.tengo +2 -1
  12. package/dist/tengo/lib/pt.lib.tengo +25 -30
  13. package/dist/tengo/lib/slices.lib.tengo +20 -1
  14. package/dist/tengo/lib/workdir.lib.tengo +1 -1
  15. package/dist/tengo/tpl/annotations.compute.plj.gz +0 -0
  16. package/dist/tengo/tpl/anonymize.deanonymize.plj.gz +0 -0
  17. package/dist/tengo/tpl/anonymize.impl.plj.gz +0 -0
  18. package/dist/tengo/tpl/check_network.create_workdir_from_storage.plj.gz +0 -0
  19. package/dist/tengo/tpl/check_network.download_blob.plj.gz +0 -0
  20. package/dist/tengo/tpl/check_network.run_hello_world.plj.gz +0 -0
  21. package/dist/tengo/tpl/check_network.run_hello_world_py.plj.gz +0 -0
  22. package/dist/tengo/tpl/check_network.upload_blob.plj.gz +0 -0
  23. package/dist/tengo/tpl/check_network.upload_template.plj.gz +0 -0
  24. package/dist/tengo/tpl/check_network.workdir_type_name_extractor.plj.gz +0 -0
  25. package/dist/tengo/tpl/exec.conda.create-env.plj.gz +0 -0
  26. package/dist/tengo/tpl/exec.delayed-compute-allocation.impl.plj.gz +0 -0
  27. package/dist/tengo/tpl/exec.exec-impl.plj.gz +0 -0
  28. package/dist/tengo/tpl/exec.exec.plj.gz +0 -0
  29. package/dist/tengo/tpl/exec.load-software.impl.plj.gz +0 -0
  30. package/dist/tengo/tpl/exec.monetization_info.plj.gz +0 -0
  31. package/dist/tengo/tpl/exec.monetization_to_json.plj.gz +0 -0
  32. package/dist/tengo/tpl/exec.python.create-venv.plj.gz +0 -0
  33. package/dist/tengo/tpl/exec.python.install-deps.plj.gz +0 -0
  34. package/dist/tengo/tpl/exec.python.venv-bin-path.plj.gz +0 -0
  35. package/dist/tengo/tpl/ll.get-field.plj.gz +0 -0
  36. package/dist/tengo/tpl/pframes.export-multiple-pcolumns.plj.gz +0 -0
  37. package/dist/tengo/tpl/pframes.export-parquet-pcolumn-chunk.plj.gz +0 -0
  38. package/dist/tengo/tpl/pframes.export-pframe-for-ui.plj.gz +0 -0
  39. package/dist/tengo/tpl/pframes.export-pframe.plj.gz +0 -0
  40. package/dist/tengo/tpl/pframes.export-single-pcolumn.plj.gz +0 -0
  41. package/dist/tengo/tpl/pframes.import-dir.plj.gz +0 -0
  42. package/dist/tengo/tpl/pframes.parse-to-json.plj.gz +0 -0
  43. package/dist/tengo/tpl/pframes.process-pcolumn-data.plj.gz +0 -0
  44. package/dist/tengo/tpl/pframes.remove-nulls.plj.gz +0 -0
  45. package/dist/tengo/tpl/pframes.slice-data.plj.gz +0 -0
  46. package/dist/tengo/tpl/pframes.xsv-export-pframe.plj.gz +0 -0
  47. package/dist/tengo/tpl/pframes.xsv-import-if-not-null.plj.gz +0 -0
  48. package/dist/tengo/tpl/pframes.xsv-import-map.plj.gz +0 -0
  49. package/dist/tengo/tpl/pt.import-dir.plj.gz +0 -0
  50. package/dist/tengo/tpl/pt.workflow-run.plj.gz +0 -0
  51. package/dist/tengo/tpl/waiter.waiter.plj.gz +0 -0
  52. package/dist/tengo/tpl/workdir.save.plj.gz +0 -0
  53. package/dist/tengo/tpl/workflow.build-ctx.plj.gz +0 -0
  54. package/dist/tengo/tpl/workflow.query-anchored.plj.gz +0 -0
  55. package/package.json +5 -5
@@ -50,7 +50,7 @@ computeAnnotations := func(inputs) {
50
50
 
51
51
  columnsFromExpressions := util.extractColumnsFromExpressions(slices.map(steps, func(step) { return step.value }))
52
52
  additionalColumns := is_array(inputs.additionalColumns) ? inputs.additionalColumns : []
53
- columns := columnsFromExpressions + additionalColumns
53
+ columns := slices.unique(columnsFromExpressions + additionalColumns)
54
54
 
55
55
  bundleBuilder := wf.createPBundleBuilder()
56
56
  bundleBuilder.addAnchor("main", anchorRef)
@@ -11,6 +11,10 @@ MEDIUM_QUEUE := "medium"
11
11
  LIGHT_QUEUE := "light"
12
12
  UI_TASKS_QUEUE := "ui-tasks"
13
13
 
14
+
15
+ RUNNER_BATCH := "batch" // batch system execution (k8s jobs, etc.)
16
+ RUNNER_EXECUTOR := "executor" // local binary execution
17
+
14
18
  export ll.toStrict({
15
19
  ARG_TYPE_STRING: ARG_TYPE_STRING,
16
20
  ARG_TYPE_EXPRESSION: ARG_TYPE_EXPRESSION,
@@ -21,5 +25,8 @@ export ll.toStrict({
21
25
  UI_TASKS_QUEUE: UI_TASKS_QUEUE,
22
26
  LIGHT_QUEUE: LIGHT_QUEUE,
23
27
  MEDIUM_QUEUE: MEDIUM_QUEUE,
24
- HEAVY_QUEUE: HEAVY_QUEUE
28
+ HEAVY_QUEUE: HEAVY_QUEUE,
29
+
30
+ RUNNER_BATCH: RUNNER_BATCH,
31
+ RUNNER_EXECUTOR: RUNNER_EXECUTOR
25
32
  })
@@ -23,8 +23,18 @@ _RTYPE_QUOTA := { Name: "Quota", Version: "1" }
23
23
 
24
24
 
25
25
 
26
- useBatch := func(queueName) {
27
- return feats.hasBatch && !slices.hasElement([ constants.UI_TASKS_QUEUE ], queueName)
26
+ getRunnerType := func(queueName) {
27
+
28
+ runner := feats.getRunnerFor(queueName)
29
+ if !is_undefined(runner) {
30
+ return runner
31
+ }
32
+
33
+
34
+ if feats.hasBatch && !slices.hasElement([ constants.UI_TASKS_QUEUE ], queueName) {
35
+ return constants.RUNNER_BATCH
36
+ }
37
+ return constants.RUNNER_EXECUTOR
28
38
  }
29
39
 
30
40
 
@@ -158,8 +168,9 @@ storageSpaceRequestBuilder := func() {
158
168
  return self
159
169
  }
160
170
 
161
- _RTYPE_COMPUTE_REQUEST_EXECUTOR_V1 := { Name: "ComputeRequest/executor", Version: "1" }
162
- _RTYPE_COMPUTE_REQUEST_BATCH_V1 := { Name: "ComputeRequest/batch", Version: "1" }
171
+ _computeRequestResourceType := func(runnerType) {
172
+ return { Name: "ComputeRequest/" + runnerType, Version: "1" }
173
+ }
163
174
 
164
175
  _CR_FIELD_REQUEST := "request" // input
165
176
  _CR_FIELD_ALLOCATION := "allocation" // output
@@ -205,13 +216,8 @@ computeRequestBuilder := func() {
205
216
  ll.assert(smart.isReference(quota), "exec.limits.build: quota of ComputeRequest must be a valid reference")
206
217
  ll.assert(queue_name != "", "exec.limits.build: queue name is required for computeRequestBuilder")
207
218
 
208
- requestBuilder := undefined
209
-
210
- if useBatch(queue_name) {
211
- requestBuilder = smart.ephemeralBuilder(_RTYPE_COMPUTE_REQUEST_BATCH_V1)
212
- } else {
213
- requestBuilder = smart.ephemeralBuilder(_RTYPE_COMPUTE_REQUEST_EXECUTOR_V1)
214
- }
219
+ runnerType := getRunnerType(queue_name)
220
+ requestBuilder := smart.ephemeralBuilder(_computeRequestResourceType(runnerType))
215
221
 
216
222
  requestBuilder.getField(_CR_FIELD_REQUEST).set(quota)
217
223
 
@@ -229,7 +235,7 @@ computeRequestBuilder := func() {
229
235
  }
230
236
 
231
237
  export ll.toStrict({
232
- useBatch: useBatch,
238
+ getRunnerType: getRunnerType,
233
239
  quotaBuilder: quotaBuilder,
234
240
  storageSpaceRequestBuilder: storageSpaceRequestBuilder,
235
241
  computeRequestBuilder: computeRequestBuilder
@@ -19,8 +19,10 @@ limits := import("@platforma-sdk/workflow-tengo:exec.limits")
19
19
  delayedCompAlloc := import("@platforma-sdk/workflow-tengo:exec.delayed-compute-allocation")
20
20
 
21
21
  _RTYPE_RUN_COMMAND_V1 := { Name: "RunCommand/executor", Version: "1" }
22
- _RTYPE_RUN_COMMAND_EXEC_V2 := { Name: "RunCommand/executor", Version: "2" }
23
- _RTYPE_RUN_COMMAND_BATCH_V2 := { Name: "RunCommand/batch", Version: "2" }
22
+
23
+ _runCommandResourceType := func(runnerType) {
24
+ return { Name: "RunCommand/" + runnerType, Version: "2" }
25
+ }
24
26
  _RTYPE_RUN_COMMAND_CMD := { Name: "RunCommandCmd", Version: "1" }
25
27
  _RTYPE_RUN_COMMAND_ARGS := { Name: "RunCommandArgs", Version: "1" }
26
28
  _RTYPE_RUN_COMMAND_OPTIONS := { Name: "run-command/options", Version: "1" }
@@ -669,17 +671,8 @@ builder := func(workdir, ...initialState) {
669
671
 
670
672
  ll.assert(!is_undefined(queue), "runcmd.builder.build: queue is required for any command run")
671
673
 
672
- useBatch := limits.useBatch(queue)
673
-
674
- if useBatch {
675
-
676
-
677
-
678
- runRes = smart.ephemeralBuilder(_RTYPE_RUN_COMMAND_BATCH_V2)
679
-
680
- } else {
681
- runRes = smart.ephemeralBuilder(_RTYPE_RUN_COMMAND_EXEC_V2)
682
- }
674
+ runnerType := limits.getRunnerType(queue)
675
+ runRes = smart.ephemeralBuilder(_runCommandResourceType(runnerType))
683
676
 
684
677
  runRes.getField(_FIELD_WORKDIR_IN).set(workdir)
685
678
 
@@ -30,10 +30,25 @@ _hasRunner := func(e_id) {
30
30
  return !is_undefined(_executors[e_id])
31
31
  }
32
32
 
33
+
34
+ _hasGetRunnerFor := ll.methodExists(plapi, "getRunnerFor")
35
+
36
+
37
+
38
+ _getRunnerFor := func(queueName) {
39
+ if !_hasGetRunnerFor {
40
+ return undefined
41
+ }
42
+ return plapi.getRunnerFor(queueName)
43
+ }
44
+
33
45
  export ll.toStrict({
34
46
  hasExec: _hasRunner("executor"), // local binary execution is available
35
47
  hasBatch: _hasRunner("batch"), // batch system execution is available
36
48
 
49
+
50
+ getRunnerFor: _getRunnerFor,
51
+
37
52
  pureFutureFields: _isEnabled("pureFutureFields") || _api >= 1, // 'pure' future fields magic that provides deduplication
38
53
  commandExpressions: _isEnabled("commandExpressions") || _api >= 2, // rich expressions in command arguments ( {{ system.ram_bytes / 20 }} )
39
54
 
@@ -1106,5 +1106,6 @@ export ll.toStrict({
1106
1106
  pColumnResourceMapDataBuilder: pColumnResourceMapDataBuilder,
1107
1107
  tsvFileBuilder: func() { return xsvBuilder.xsvFileBuilder("tsv") },
1108
1108
  csvFileBuilder: func() { return xsvBuilder.xsvFileBuilder("csv") },
1109
+ parquetFileBuilder: func() { return xsvBuilder.xsvFileBuilder("parquet") },
1109
1110
  parseToJson: parseToJson
1110
1111
  })
@@ -798,6 +798,11 @@ isStructuredPfMap := func(pf) {
798
798
  return true
799
799
  }
800
800
 
801
+ validateXsvType := func(xsvType) {
802
+ validation.assertType(xsvType, "string,regex=csv|tsv|parquet",
803
+ "xsvType must be one of [csv, tsv, parquet], found: %v", xsvType)
804
+ }
805
+
801
806
  export ll.toStrict({
802
807
  PFCONV_IMPORT_CFG_SCHEMA: PFCONV_IMPORT_CFG_SCHEMA,
803
808
  PFCONV_EXPORT_CFG_SCHEMA: PFCONV_EXPORT_CFG_SCHEMA,
@@ -810,5 +815,6 @@ export ll.toStrict({
810
815
  pFrameToColumnsMap: pFrameToColumnsMap,
811
816
  addColumnToWd: addColumnToWd,
812
817
  isFlatPfMap: isFlatPfMap,
813
- isStructuredPfMap: isStructuredPfMap
818
+ isStructuredPfMap: isStructuredPfMap,
819
+ validateXsvType: validateXsvType
814
820
  })
@@ -8,9 +8,10 @@ pBuilder := import("@platforma-sdk/workflow-tengo:pframes.builder")
8
8
  xsv := import("@platforma-sdk/workflow-tengo:pframes.xsv")
9
9
  canonical := import("@platforma-sdk/workflow-tengo:canonical")
10
10
  execConstants := import("@platforma-sdk/workflow-tengo:exec.constants")
11
+ util := import("@platforma-sdk/workflow-tengo:pframes.util")
11
12
 
12
13
  xsvFileBuilder := func(xsvType) {
13
- ll.assert(xsvType == "csv" || xsvType == "tsv", "xsvType must be 'csv' or 'tsv'")
14
+ util.validateXsvType(xsvType)
14
15
 
15
16
  PTablerNA := "%%NA%%" // Constant for PTabler NA representation
16
17
  naValueInternal := "" // Default NA value, can be changed by setNA
@@ -84,7 +84,7 @@ getColumnSpec := func(axesSpec, col) {
84
84
 
85
85
 
86
86
  importFile := func(xsvFile, xsvType, spec, ...ops) {
87
- ll.assert(xsvType == "csv" || xsvType == "tsv", "expected one of [tsv, csv] types, found: " + xsvType)
87
+ util.validateXsvType(xsvType)
88
88
 
89
89
  validation.assertType(spec, util.PFCONV_IMPORT_CFG_SCHEMA)
90
90
 
@@ -106,6 +106,8 @@ importFile := func(xsvFile, xsvType, spec, ...ops) {
106
106
  ops := renderOps({ dataOnly: false, splitDataAndSpec: false, queue: execConstants.LIGHT_QUEUE, inputCache: undefined }, ops...)
107
107
 
108
108
  if ops.transpose != undefined {
109
+ ll.assert(xsvType != "parquet",
110
+ "transpose is not supported with xsvType 'parquet', please use 'csv' or 'tsv' instead")
109
111
 
110
112
  tops := ops.transpose
111
113
 
@@ -170,6 +172,8 @@ importFile := func(xsvFile, xsvType, spec, ...ops) {
170
172
  if storageFormat == "Parquet" {
171
173
  return xsvImportPt.importFileParquet(xsvFile, xsvType, spec, ops)
172
174
  }
175
+ ll.assert(xsvType != "parquet",
176
+ "storageFormat '%v' is not supported with xsvType 'parquet', please use storageFormat 'Parquet'", storageFormat)
173
177
 
174
178
 
175
179
  pureSpec := util.purifySpec(spec)
@@ -59,9 +59,14 @@ applyNaRegex := func(colExpr, naRegex, colType) {
59
59
 
60
60
 
61
61
  importFileParquet := func(xsvFile, xsvType, spec, ops) {
62
- ll.assert(xsvType == "csv" || xsvType == "tsv", "unknown xsv type: %v", xsvType)
62
+ util.validateXsvType(xsvType)
63
63
 
64
64
  validation.assertType(spec, util.PFCONV_IMPORT_CFG_SCHEMA)
65
+ if xsvType == "parquet" {
66
+ ll.assert(is_undefined(spec.separator), "separator is not supported with xsvType 'parquet'")
67
+ ll.assert(is_undefined(spec.commentLinePrefix), "commentLinePrefix is not supported with xsvType 'parquet'")
68
+ ll.assert(is_undefined(spec.skipEmptyLines), "skipEmptyLines is not supported with xsvType 'parquet'")
69
+ }
65
70
 
66
71
 
67
72
  ll.assert(is_undefined(spec.index), "index axis is not supported with Parquet storage format")
@@ -89,7 +89,8 @@ getColumnSpec := func(axesSpec, col) {
89
89
 
90
90
 
91
91
  importFile := func(xsvFile, xsvType, spec, ...ops) {
92
- ll.assert(xsvType == "csv" || xsvType == "tsv", "expected one of [tsv, csv] types, found: " + xsvType)
92
+ ll.assert(xsvType == "csv" || xsvType == "tsv" || xsvType == "parquet",
93
+ "expected one of [csv, tsv, parquet] types, found: %v", xsvType)
93
94
 
94
95
  validation.assertType(spec, util.PFCONV_IMPORT_CFG_SCHEMA)
95
96
 
@@ -15,6 +15,7 @@ pframesSpec := import("@platforma-sdk/workflow-tengo:pframes.spec")
15
15
  render := import("@platforma-sdk/workflow-tengo:render")
16
16
  maps := import("@platforma-sdk/workflow-tengo:maps")
17
17
  canonical := import("@platforma-sdk/workflow-tengo:canonical")
18
+ validation := import("@platforma-sdk/workflow-tengo:validation")
18
19
 
19
20
 
20
21
 
@@ -468,17 +469,14 @@ workflow := func() {
468
469
 
469
470
 
470
471
  if !is_undefined(opts.format) {
471
- if opts.format != "csv" && opts.format != "tsv" && opts.format != "ndjson" {
472
- ll.panic("format must be 'csv', 'tsv', or 'ndjson'. Got: %v", opts.format)
473
- }
472
+ validation.assertType(opts.format, "string,regex=csv|tsv|parquet|ndjson",
473
+ "format must be one of [csv, tsv, parquet, ndjson], found: %v", opts.format)
474
474
  if !is_undefined(finalFormat) && finalFormat != opts.format {
475
475
  ll.panic("format and xsvType from structural input cannot be used together. Got: %v and %v", opts.format, finalFormat)
476
476
  }
477
477
  finalFormat = opts.format
478
478
  } else if !is_undefined(opts.xsvType) {
479
- if opts.xsvType != "csv" && opts.xsvType != "tsv" {
480
- ll.panic("xsvType must be 'csv' or 'tsv'. Got: %v", opts.xsvType)
481
- }
479
+ pframesUtil.validateXsvType(opts.xsvType)
482
480
  if !is_undefined(finalFormat) && finalFormat != opts.xsvType {
483
481
  ll.panic("opts.xsvType and xsvType from structural input cannot be used together. Got: %v and %v", opts.xsvType, finalFormat)
484
482
  }
@@ -594,23 +592,23 @@ workflow := func() {
594
592
  translation: translation
595
593
  }
596
594
  } else if finalFormat == "parquet" {
597
- step = {
598
- type: "read_parquet",
599
- file: finalFileName,
600
- name: finalDataFrameId
601
- }
602
- } else if finalFormat == "ndjson" {
603
- step = {
604
- type: "read_ndjson",
605
- file: finalFileName,
606
- name: finalDataFrameId
607
- }
608
- } else { // csv or tsv
609
- step = {
610
- type: "read_csv",
611
- file: finalFileName,
612
- name: finalDataFrameId
613
- }
595
+ step = {
596
+ type: "read_parquet",
597
+ file: finalFileName,
598
+ name: finalDataFrameId
599
+ }
600
+ } else if finalFormat == "ndjson" {
601
+ step = {
602
+ type: "read_ndjson",
603
+ file: finalFileName,
604
+ name: finalDataFrameId
605
+ }
606
+ } else { // csv or tsv
607
+ step = {
608
+ type: "read_csv",
609
+ file: finalFileName,
610
+ name: finalDataFrameId
611
+ }
614
612
 
615
613
  if finalFormat == "csv" {
616
614
  step.delimiter = ","
@@ -632,7 +630,7 @@ workflow := func() {
632
630
  }
633
631
 
634
632
 
635
- if !is_undefined(finalSchemaToUse) {
633
+ if !is_undefined(finalSchemaToUse) && finalFormat != "parquet" {
636
634
  step.schema = finalSchemaToUse
637
635
  }
638
636
 
@@ -1044,14 +1042,11 @@ _newDataFrame = func(parentWorkflow, dfName) {
1044
1042
 
1045
1043
 
1046
1044
  if !is_undefined(opts.format) {
1047
- if opts.format != "csv" && opts.format != "tsv" && opts.format != "ndjson" {
1048
- ll.panic("format must be 'csv', 'tsv', or 'ndjson'. Got: %v", opts.format)
1049
- }
1045
+ validation.assertType(opts.format, "string,regex=csv|tsv|parquet|ndjson",
1046
+ "format must be one of [csv, tsv, parquet, ndjson], found: %v", opts.format)
1050
1047
  finalFormat = opts.format
1051
1048
  } else if !is_undefined(opts.xsvType) {
1052
- if opts.xsvType != "csv" && opts.xsvType != "tsv" {
1053
- ll.panic("xsvType must be 'csv' or 'tsv'. Got: %v", opts.xsvType)
1054
- }
1049
+ pframesUtil.validateXsvType(opts.xsvType)
1055
1050
  finalFormat = opts.xsvType
1056
1051
  } else {
1057
1052
 
@@ -376,6 +376,24 @@ sortUnique := func(list) {
376
376
  return quickSortInPlace(uniqueList)
377
377
  }
378
378
 
379
+
380
+
381
+
382
+
383
+
384
+
385
+ unique := func(list) {
386
+ arr := []
387
+ map := {}
388
+ for _, item in list {
389
+ if is_undefined(map[item]) {
390
+ arr = append(arr, item)
391
+ map[item] = true
392
+ }
393
+ }
394
+ return arr
395
+ }
396
+
379
397
  export ll.toStrict({
380
398
  length: length,
381
399
  safeAppend: safeAppend,
@@ -396,5 +414,6 @@ export ll.toStrict({
396
414
  fromSet: fromSet,
397
415
  slice: slice,
398
416
  normalize: normalize,
399
- sortUnique: sortUnique
417
+ sortUnique: sortUnique,
418
+ unique: unique
400
419
  })
@@ -323,7 +323,7 @@ _fill := func() {
323
323
  quotaBuilder.ram(ram)
324
324
  }
325
325
 
326
- if limits.useBatch(queue) {
326
+ if limits.getRunnerType(queue) == execConstants.RUNNER_BATCH {
327
327
  quotaBuilder.queue(execConstants.BATCH_QUEUE)
328
328
  } else {
329
329
  quotaBuilder.queue(queue)
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": "5.7.2",
3
+ "version": "5.8.0",
4
4
  "description": "Tengo SDK library",
5
5
  "type": "module",
6
6
  "types": "./dist/index.d.ts",
@@ -17,12 +17,12 @@
17
17
  ],
18
18
  "dependencies": {
19
19
  "@milaboratories/software-pframes-conv": "2.2.9",
20
- "@platforma-open/milaboratories.software-small-binaries": "^1.15.25",
21
- "@platforma-open/milaboratories.software-ptabler": "1.14.0",
22
- "@platforma-open/milaboratories.software-ptexter": "1.2.0"
20
+ "@platforma-open/milaboratories.software-small-binaries": "^1.15.26",
21
+ "@platforma-open/milaboratories.software-ptexter": "1.2.0",
22
+ "@platforma-open/milaboratories.software-ptabler": "1.14.0"
23
23
  },
24
24
  "devDependencies": {
25
- "@platforma-sdk/tengo-builder": "2.4.2"
25
+ "@platforma-sdk/tengo-builder": "2.4.8"
26
26
  },
27
27
  "scripts": {
28
28
  "type-check": "pl-tengo check",