planar 0.10.0__py3-none-any.whl → 0.12.0__py3-none-any.whl

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 (73) hide show
  1. planar/app.py +26 -6
  2. planar/cli.py +26 -0
  3. planar/data/__init__.py +1 -0
  4. planar/data/config.py +12 -1
  5. planar/data/connection.py +89 -4
  6. planar/data/dataset.py +13 -7
  7. planar/data/utils.py +145 -25
  8. planar/db/alembic/env.py +68 -57
  9. planar/db/alembic.ini +1 -1
  10. planar/files/storage/config.py +7 -1
  11. planar/routers/dataset_router.py +5 -1
  12. planar/routers/info.py +79 -36
  13. planar/scaffold_templates/pyproject.toml.j2 +1 -1
  14. planar/testing/fixtures.py +7 -4
  15. planar/testing/planar_test_client.py +8 -0
  16. planar/version.py +27 -0
  17. planar-0.12.0.dist-info/METADATA +202 -0
  18. {planar-0.10.0.dist-info → planar-0.12.0.dist-info}/RECORD +20 -71
  19. planar/ai/test_agent_serialization.py +0 -229
  20. planar/ai/test_agent_tool_step_display.py +0 -78
  21. planar/data/test_dataset.py +0 -358
  22. planar/files/storage/test_azure_blob.py +0 -435
  23. planar/files/storage/test_local_directory.py +0 -162
  24. planar/files/storage/test_s3.py +0 -299
  25. planar/files/test_files.py +0 -282
  26. planar/human/test_human.py +0 -385
  27. planar/logging/test_formatter.py +0 -327
  28. planar/modeling/mixins/test_auditable.py +0 -97
  29. planar/modeling/mixins/test_timestamp.py +0 -134
  30. planar/modeling/mixins/test_uuid_primary_key.py +0 -52
  31. planar/routers/test_agents_router.py +0 -174
  32. planar/routers/test_dataset_router.py +0 -429
  33. planar/routers/test_files_router.py +0 -49
  34. planar/routers/test_object_config_router.py +0 -367
  35. planar/routers/test_routes_security.py +0 -168
  36. planar/routers/test_rule_router.py +0 -470
  37. planar/routers/test_workflow_router.py +0 -564
  38. planar/rules/test_data/account_dormancy_management.json +0 -223
  39. planar/rules/test_data/airline_loyalty_points_calculator.json +0 -262
  40. planar/rules/test_data/applicant_risk_assessment.json +0 -435
  41. planar/rules/test_data/booking_fraud_detection.json +0 -407
  42. planar/rules/test_data/cellular_data_rollover_system.json +0 -258
  43. planar/rules/test_data/clinical_trial_eligibility_screener.json +0 -437
  44. planar/rules/test_data/customer_lifetime_value.json +0 -143
  45. planar/rules/test_data/import_duties_calculator.json +0 -289
  46. planar/rules/test_data/insurance_prior_authorization.json +0 -443
  47. planar/rules/test_data/online_check_in_eligibility_system.json +0 -254
  48. planar/rules/test_data/order_consolidation_system.json +0 -375
  49. planar/rules/test_data/portfolio_risk_monitor.json +0 -471
  50. planar/rules/test_data/supply_chain_risk.json +0 -253
  51. planar/rules/test_data/warehouse_cross_docking.json +0 -237
  52. planar/rules/test_rules.py +0 -1494
  53. planar/security/tests/test_auth_middleware.py +0 -162
  54. planar/security/tests/test_authorization_context.py +0 -78
  55. planar/security/tests/test_cedar_basics.py +0 -41
  56. planar/security/tests/test_cedar_policies.py +0 -158
  57. planar/security/tests/test_jwt_principal_context.py +0 -179
  58. planar/test_app.py +0 -142
  59. planar/test_cli.py +0 -394
  60. planar/test_config.py +0 -515
  61. planar/test_object_config.py +0 -527
  62. planar/test_object_registry.py +0 -14
  63. planar/test_sqlalchemy.py +0 -193
  64. planar/test_utils.py +0 -105
  65. planar/testing/test_memory_storage.py +0 -143
  66. planar/workflows/test_concurrency_detection.py +0 -120
  67. planar/workflows/test_lock_timeout.py +0 -140
  68. planar/workflows/test_serialization.py +0 -1203
  69. planar/workflows/test_suspend_deserialization.py +0 -231
  70. planar/workflows/test_workflow.py +0 -2005
  71. planar-0.10.0.dist-info/METADATA +0 -323
  72. {planar-0.10.0.dist-info → planar-0.12.0.dist-info}/WHEEL +0 -0
  73. {planar-0.10.0.dist-info → planar-0.12.0.dist-info}/entry_points.txt +0 -0
@@ -1,443 +0,0 @@
1
- {
2
- "nodes": [
3
- {
4
- "type": "inputNode",
5
- "content": {
6
- "schema": "{\n \"type\": \"object\",\n \"properties\": {\n \"patientInfo\": {\n \"type\": \"object\",\n \"properties\": {\n \"insuranceType\": {\n \"type\": \"string\",\n \"enum\": [\"Medicaid\", \"Medicare\", \"Commercial\"]\n }\n }\n },\n \"diagnosisCodes\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n },\n \"serviceType\": {\n \"type\": \"string\",\n \"enum\": [\"Medication\", \"Procedure\", \"Equipment\", \"Imaging\"]\n },\n \"serviceDetails\": {\n \"type\": \"object\",\n \"properties\": {\n \"code\": {\n \"type\": \"string\"\n },\n \"cost\": {\n \"type\": \"number\"\n },\n \"isEmergency\": {\n \"type\": \"boolean\"\n }\n }\n }\n }\n}"
7
- },
8
- "id": "inputNode",
9
- "name": "request",
10
- "position": {
11
- "x": 110,
12
- "y": 161.5
13
- }
14
- },
15
- {
16
- "type": "switchNode",
17
- "content": {
18
- "hitPolicy": "first",
19
- "statements": [
20
- {
21
- "id": "s1",
22
- "condition": "patientInfo.insuranceType == 'Medicaid'",
23
- "isDefault": false
24
- },
25
- {
26
- "id": "s2",
27
- "condition": "patientInfo.insuranceType == 'Medicare'",
28
- "isDefault": false
29
- },
30
- {
31
- "id": "s3",
32
- "condition": "patientInfo.insuranceType == 'Commercial'",
33
- "isDefault": false
34
- },
35
- {
36
- "id": "s4",
37
- "condition": "",
38
- "isDefault": true
39
- }
40
- ]
41
- },
42
- "id": "insuranceTypeCheck",
43
- "name": "Insurance Type Check",
44
- "position": {
45
- "x": 430,
46
- "y": 161.5
47
- }
48
- },
49
- {
50
- "type": "decisionTableNode",
51
- "content": {
52
- "hitPolicy": "first",
53
- "rules": [
54
- {
55
- "_id": "r1",
56
- "i1": "'Medication'",
57
- "i2": "> 200",
58
- "o1": "true",
59
- "o2": "'High-cost medication requires prior authorization'"
60
- },
61
- {
62
- "_id": "r2",
63
- "i1": "'Procedure'",
64
- "i2": "> 500",
65
- "o1": "true",
66
- "o2": "'High-cost procedure requires prior authorization'"
67
- },
68
- {
69
- "_id": "r3",
70
- "i1": "'Imaging'",
71
- "i2": "",
72
- "o1": "true",
73
- "o2": "'All imaging services require prior authorization'"
74
- },
75
- {
76
- "_id": "r4",
77
- "i1": "'Equipment'",
78
- "i2": "> 300",
79
- "o1": "true",
80
- "o2": "'DME over threshold requires prior authorization'"
81
- },
82
- {
83
- "_id": "r5",
84
- "i1": "",
85
- "i2": "",
86
- "o1": "false",
87
- "o2": "'Standard service does not require prior authorization'"
88
- }
89
- ],
90
- "inputs": [
91
- {
92
- "id": "i1",
93
- "name": "Service Type",
94
- "field": "serviceType"
95
- },
96
- {
97
- "id": "i2",
98
- "name": "Cost",
99
- "field": "serviceDetails.cost"
100
- }
101
- ],
102
- "outputs": [
103
- {
104
- "id": "o1",
105
- "name": "Requires Authorization",
106
- "field": "requiresAuthorization"
107
- },
108
- {
109
- "id": "o2",
110
- "name": "Reason",
111
- "field": "authorizationReason"
112
- }
113
- ],
114
- "passThrough": true,
115
- "inputField": null,
116
- "outputPath": null,
117
- "executionMode": "single"
118
- },
119
- "id": "medicaidRules",
120
- "name": "Medicaid Rules",
121
- "position": {
122
- "x": 750,
123
- "y": 63.5
124
- }
125
- },
126
- {
127
- "type": "decisionTableNode",
128
- "content": {
129
- "hitPolicy": "first",
130
- "rules": [
131
- {
132
- "_id": "r1",
133
- "i1": "'Medication'",
134
- "i2": "contains($, 'J')",
135
- "o1": "true",
136
- "o2": "'Part B medication requires prior authorization'"
137
- },
138
- {
139
- "_id": "r2",
140
- "i1": "'Procedure'",
141
- "i2": "number($) > 1000",
142
- "o1": "true",
143
- "o2": "'High-cost procedure requires prior authorization'"
144
- },
145
- {
146
- "_id": "r3",
147
- "i1": "'Imaging'",
148
- "i2": "startsWith($, 'CT') or startsWith($, 'MRI')",
149
- "o1": "true",
150
- "o2": "'Advanced imaging requires prior authorization'"
151
- },
152
- {
153
- "_id": "r4",
154
- "i1": "'Equipment'",
155
- "i2": "number($) > 500",
156
- "o1": "true",
157
- "o2": "'DME over threshold requires prior authorization'"
158
- },
159
- {
160
- "_id": "r5",
161
- "i1": "",
162
- "i2": "",
163
- "o1": "false",
164
- "o2": "'Standard Medicare service does not require prior authorization'"
165
- }
166
- ],
167
- "inputs": [
168
- {
169
- "id": "i1",
170
- "name": "Service Type",
171
- "field": "serviceType"
172
- },
173
- {
174
- "id": "i2",
175
- "name": "Code",
176
- "field": "serviceDetails.code"
177
- }
178
- ],
179
- "outputs": [
180
- {
181
- "id": "o1",
182
- "name": "Requires Authorization",
183
- "field": "requiresAuthorization"
184
- },
185
- {
186
- "id": "o2",
187
- "name": "Reason",
188
- "field": "authorizationReason"
189
- }
190
- ],
191
- "passThrough": true,
192
- "inputField": null,
193
- "outputPath": null,
194
- "executionMode": "single",
195
- "passThorough": false
196
- },
197
- "id": "medicareRules",
198
- "name": "Medicare Rules",
199
- "position": {
200
- "x": 750,
201
- "y": 161.5
202
- }
203
- },
204
- {
205
- "type": "decisionTableNode",
206
- "content": {
207
- "hitPolicy": "first",
208
- "rules": [
209
- {
210
- "_id": "r1",
211
- "i1": "'Medication'",
212
- "i2": "contains(serviceDetails.code, 'SPE')",
213
- "o1": "true",
214
- "o2": "'Specialty medication requires prior authorization'"
215
- },
216
- {
217
- "_id": "r2",
218
- "i1": "'Procedure'",
219
- "i2": "serviceDetails.code in ['33361', '33362', '33363', '33364']",
220
- "o1": "true",
221
- "o2": "'Specific procedures require prior authorization'"
222
- },
223
- {
224
- "_id": "r3",
225
- "i1": "'Imaging'",
226
- "i2": "serviceDetails.code in ['70450', '70460', '70470', '70551', '70552', '70553']",
227
- "o1": "true",
228
- "o2": "'Advanced imaging requires prior authorization'"
229
- },
230
- {
231
- "_id": "r4",
232
- "i1": "'Equipment'",
233
- "i2": "serviceDetails.cost > 1000",
234
- "o1": "true",
235
- "o2": "'High-cost equipment requires prior authorization'"
236
- },
237
- {
238
- "_id": "r5",
239
- "i1": "",
240
- "i2": "serviceDetails.isEmergency == true",
241
- "o1": "false",
242
- "o2": "'Emergency services do not require prior authorization'"
243
- },
244
- {
245
- "_id": "r6",
246
- "i1": "",
247
- "i2": "",
248
- "o1": "false",
249
- "o2": "'Standard commercial service does not require prior authorization'"
250
- }
251
- ],
252
- "inputs": [
253
- {
254
- "id": "i1",
255
- "name": "Service Type",
256
- "field": "serviceType"
257
- },
258
- {
259
- "id": "i2",
260
- "name": "Additional Check"
261
- }
262
- ],
263
- "outputs": [
264
- {
265
- "id": "o1",
266
- "name": "Requires Authorization",
267
- "field": "requiresAuthorization"
268
- },
269
- {
270
- "id": "o2",
271
- "name": "Reason",
272
- "field": "authorizationReason"
273
- }
274
- ],
275
- "passThrough": true,
276
- "inputField": null,
277
- "outputPath": null,
278
- "executionMode": "single"
279
- },
280
- "id": "commercialRules",
281
- "name": "Commercial Rules",
282
- "position": {
283
- "x": 750,
284
- "y": 259.5
285
- }
286
- },
287
- {
288
- "type": "decisionTableNode",
289
- "content": {
290
- "hitPolicy": "first",
291
- "rules": [
292
- {
293
- "_id": "r1",
294
- "i1": "some($, startsWith(#, 'Z51'))",
295
- "i2": "requiresAuthorization == true",
296
- "o1": "false",
297
- "o2": "'Encounter for chemotherapy exempt from prior authorization'"
298
- },
299
- {
300
- "_id": "r2",
301
- "i1": "some($, # in ['O09.511', 'O09.512', 'O09.513', 'O09.519'])",
302
- "i2": "requiresAuthorization == true",
303
- "o1": "false",
304
- "o2": "'Pregnancy-related services exempt from prior authorization'"
305
- },
306
- {
307
- "_id": "r3",
308
- "i1": "some($, # in ['U07.1'])",
309
- "i2": "requiresAuthorization == true and serviceType == 'Imaging'",
310
- "o1": "false",
311
- "o2": "'COVID-19 related imaging exempt from prior authorization'"
312
- },
313
- {
314
- "_id": "r4",
315
- "i1": "",
316
- "i2": "",
317
- "o1": "requiresAuthorization",
318
- "o2": "authorizationReason"
319
- }
320
- ],
321
- "inputs": [
322
- {
323
- "id": "i1",
324
- "name": "Diagnosis Codes",
325
- "field": "diagnosisCodes"
326
- },
327
- {
328
- "id": "i2",
329
- "name": "Current Authorization Status"
330
- }
331
- ],
332
- "outputs": [
333
- {
334
- "id": "o1",
335
- "name": "Final Authorization Required",
336
- "field": "requiresAuthorization"
337
- },
338
- {
339
- "id": "o2",
340
- "name": "Final Reason",
341
- "field": "authorizationReason"
342
- }
343
- ],
344
- "passThrough": true,
345
- "inputField": null,
346
- "outputPath": null,
347
- "executionMode": "single",
348
- "passThorough": false
349
- },
350
- "id": "diagnosisCheck",
351
- "name": "Diagnosis Code Exclusions",
352
- "position": {
353
- "x": 1070,
354
- "y": 161.5
355
- }
356
- },
357
- {
358
- "type": "expressionNode",
359
- "content": {
360
- "expressions": [
361
- {
362
- "id": "e1",
363
- "key": "requiresAuthorization",
364
- "value": "requiresAuthorization"
365
- },
366
- {
367
- "id": "e2",
368
- "key": "reason",
369
- "value": "authorizationReason"
370
- },
371
- {
372
- "id": "e3",
373
- "key": "timestamp",
374
- "value": "date('now')"
375
- }
376
- ],
377
- "passThrough": false,
378
- "inputField": null,
379
- "outputPath": null,
380
- "executionMode": "single"
381
- },
382
- "id": "finalDetermination",
383
- "name": "Final Determination",
384
- "position": {
385
- "x": 1390,
386
- "y": 161.5
387
- }
388
- }
389
- ],
390
- "edges": [
391
- {
392
- "id": "edge1",
393
- "sourceId": "inputNode",
394
- "targetId": "insuranceTypeCheck",
395
- "type": "edge"
396
- },
397
- {
398
- "id": "edge2",
399
- "sourceId": "insuranceTypeCheck",
400
- "targetId": "medicaidRules",
401
- "sourceHandle": "s1",
402
- "type": "edge"
403
- },
404
- {
405
- "id": "edge3",
406
- "sourceId": "insuranceTypeCheck",
407
- "targetId": "medicareRules",
408
- "sourceHandle": "s2",
409
- "type": "edge"
410
- },
411
- {
412
- "id": "edge4",
413
- "sourceId": "insuranceTypeCheck",
414
- "targetId": "commercialRules",
415
- "sourceHandle": "s3",
416
- "type": "edge"
417
- },
418
- {
419
- "id": "edge5",
420
- "sourceId": "medicaidRules",
421
- "targetId": "diagnosisCheck",
422
- "type": "edge"
423
- },
424
- {
425
- "id": "edge6",
426
- "sourceId": "medicareRules",
427
- "targetId": "diagnosisCheck",
428
- "type": "edge"
429
- },
430
- {
431
- "id": "edge7",
432
- "sourceId": "commercialRules",
433
- "targetId": "diagnosisCheck",
434
- "type": "edge"
435
- },
436
- {
437
- "id": "edge8",
438
- "sourceId": "diagnosisCheck",
439
- "targetId": "finalDetermination",
440
- "type": "edge"
441
- }
442
- ]
443
- }
@@ -1,254 +0,0 @@
1
- {
2
- "nodes": [
3
- {
4
- "id": "ip1",
5
- "name": "request",
6
- "type": "inputNode",
7
- "content": {
8
- "schema": ""
9
- },
10
- "position": {
11
- "x": 110,
12
- "y": 164.5
13
- }
14
- },
15
- {
16
- "id": "ex1",
17
- "name": "preprocessData",
18
- "type": "expressionNode",
19
- "content": {
20
- "inputField": null,
21
- "outputPath": null,
22
- "expressions": [
23
- {
24
- "id": "e1-1",
25
- "key": "flightDepartureTime",
26
- "value": "date(flight.departureTime)"
27
- },
28
- {
29
- "id": "e1-2",
30
- "key": "currentTime",
31
- "value": "date('2025-03-20T08:30:00Z')"
32
- },
33
- {
34
- "id": "e1-3",
35
- "key": "hoursUntilDeparture",
36
- "value": "($.flightDepartureTime - $.currentTime) / 3600"
37
- },
38
- {
39
- "id": "e1-4",
40
- "key": "hasRequiredDocuments",
41
- "value": "passenger.hasValidPassport == true and passenger.hasValidVisa == (flight.requiresVisa ?? false)"
42
- }
43
- ],
44
- "passThrough": true,
45
- "executionMode": "single"
46
- },
47
- "position": {
48
- "x": 430,
49
- "y": 164.5
50
- }
51
- },
52
- {
53
- "id": "dt1",
54
- "name": "checkEligibility",
55
- "type": "decisionTableNode",
56
- "content": {
57
- "rules": [
58
- {
59
- "_id": "r1-1",
60
- "i1-1": "hoursUntilDeparture < 1.5",
61
- "o1-1": "false",
62
- "o1-2": "'check_in_closed'",
63
- "o1-3": "'Online check-in is closed. Please proceed to the airport for assistance.'"
64
- },
65
- {
66
- "_id": "r1-2",
67
- "i1-1": "!hasRequiredDocuments",
68
- "o1-1": "false",
69
- "o1-2": "'missing_documents'",
70
- "o1-3": "'Missing required travel documents. Please check-in at the airport.'"
71
- },
72
- {
73
- "_id": "r1-3",
74
- "i1-1": "passenger.requiresSpecialAssistance",
75
- "o1-1": "false",
76
- "o1-2": "'special_assistance'",
77
- "o1-3": "'Special assistance required. Please check-in at the airport.'"
78
- },
79
- {
80
- "_id": "r1-4",
81
- "i1-1": "",
82
- "o1-1": "true",
83
- "o1-2": "'eligible'",
84
- "o1-3": "'You are eligible for online check-in.'"
85
- }
86
- ],
87
- "inputs": [
88
- {
89
- "id": "i1-1",
90
- "name": "Condition"
91
- }
92
- ],
93
- "outputs": [
94
- {
95
- "id": "o1-1",
96
- "name": "Is Eligible",
97
- "field": "isEligible"
98
- },
99
- {
100
- "id": "o1-2",
101
- "name": "Status Code",
102
- "field": "statusCode"
103
- },
104
- {
105
- "id": "o1-3",
106
- "name": "Message",
107
- "field": "message"
108
- }
109
- ],
110
- "hitPolicy": "first",
111
- "inputField": null,
112
- "outputPath": null,
113
- "passThrough": true,
114
- "executionMode": "single"
115
- },
116
- "position": {
117
- "x": 750,
118
- "y": 164.5
119
- }
120
- },
121
- {
122
- "id": "sw1",
123
- "name": "eligibilityCheck",
124
- "type": "switchNode",
125
- "content": {
126
- "hitPolicy": "first",
127
- "statements": [
128
- {
129
- "id": "s1-1",
130
- "condition": "isEligible == true",
131
- "isDefault": false
132
- },
133
- {
134
- "id": "s1-2",
135
- "condition": "",
136
- "isDefault": true
137
- }
138
- ]
139
- },
140
- "position": {
141
- "x": 1070,
142
- "y": 164.5
143
- }
144
- },
145
- {
146
- "id": "ex2",
147
- "name": "additionalServices",
148
- "type": "expressionNode",
149
- "content": {
150
- "inputField": null,
151
- "outputPath": null,
152
- "expressions": [
153
- {
154
- "id": "01248d19-c35f-4f47-a424-526359696be5",
155
- "key": "isEligible",
156
- "value": "false"
157
- },
158
- {
159
- "id": "e2-1",
160
- "key": "canSelectSeat",
161
- "value": "flight.hasSeatSelection == true"
162
- },
163
- {
164
- "id": "e2-2",
165
- "key": "canAddBaggage",
166
- "value": "flight.allowsExtraBaggage == true"
167
- },
168
- {
169
- "id": "d053c9cd-f974-417a-92fe-ab880d498c5c",
170
- "key": "statusCode",
171
- "value": "statusCode"
172
- },
173
- {
174
- "id": "44b35986-520b-4615-87ab-fd990e3b501c",
175
- "key": "message",
176
- "value": "message"
177
- }
178
- ],
179
- "passThrough": false,
180
- "executionMode": "single"
181
- },
182
- "position": {
183
- "x": 1390,
184
- "y": 190
185
- }
186
- },
187
- {
188
- "id": "e87f2886-5c3d-42c2-ba78-9c576cc442b7",
189
- "name": "nonEligible",
190
- "type": "expressionNode",
191
- "content": {
192
- "inputField": null,
193
- "outputPath": null,
194
- "expressions": [
195
- {
196
- "id": "76a5124e-9d0f-4d85-9e21-6e5cb5cc3bdd",
197
- "key": "isEligible",
198
- "value": "false"
199
- },
200
- {
201
- "id": "377c0312-f2e1-49ea-a9ad-d3abb82e48b5",
202
- "key": "statusCode",
203
- "value": "statusCode"
204
- },
205
- {
206
- "id": "cbe1da24-a10a-4ac8-ba3c-06740d7be79b",
207
- "key": "message",
208
- "value": "message"
209
- }
210
- ],
211
- "passThrough": false,
212
- "executionMode": "single"
213
- },
214
- "position": {
215
- "x": 1390,
216
- "y": 330
217
- }
218
- }
219
- ],
220
- "edges": [
221
- {
222
- "id": "ed1",
223
- "type": "edge",
224
- "sourceId": "ip1",
225
- "targetId": "ex1"
226
- },
227
- {
228
- "id": "ed2",
229
- "type": "edge",
230
- "sourceId": "ex1",
231
- "targetId": "dt1"
232
- },
233
- {
234
- "id": "ed3",
235
- "type": "edge",
236
- "sourceId": "dt1",
237
- "targetId": "sw1"
238
- },
239
- {
240
- "id": "ed4",
241
- "type": "edge",
242
- "sourceId": "sw1",
243
- "targetId": "ex2",
244
- "sourceHandle": "s1-1"
245
- },
246
- {
247
- "id": "44445fe0-c343-4f6d-a5dc-bdbec35c4d5f",
248
- "type": "edge",
249
- "sourceId": "sw1",
250
- "targetId": "e87f2886-5c3d-42c2-ba78-9c576cc442b7",
251
- "sourceHandle": "s1-2"
252
- }
253
- ]
254
- }