owenkaplinsky commited on
Commit
2624895
·
1 Parent(s): f429f61

Add lists_contains block; bool type

Browse files
project/blocks.txt CHANGED
@@ -50,6 +50,7 @@ VALUE: lists_indexOf(inputs(END: "FIRST/LAST", VALUE: value, FIND: value))
50
  VALUE: lists_reverse(inputs(LIST: value))
51
  VALUE: lists_create_with(inputs(ADDN: value)) // N starts at 0; you can make as many N as you want
52
  VALUE: lists_sort(inputs(TYPE: "NUMERIC/TEXT/IGNORE_CASE", DIRECTION: "1/-1")) // For direction, 1 is ascending, -1 is descending
 
53
 
54
  # Variables
55
  VALUE: variables_get(inputs(VAR: value)) // VAR is a variable ID
 
50
  VALUE: lists_reverse(inputs(LIST: value))
51
  VALUE: lists_create_with(inputs(ADDN: value)) // N starts at 0; you can make as many N as you want
52
  VALUE: lists_sort(inputs(TYPE: "NUMERIC/TEXT/IGNORE_CASE", DIRECTION: "1/-1")) // For direction, 1 is ascending, -1 is descending
53
+ VALUE: lists_contains(inputs(ITEM: value, LIST: value))
54
 
55
  # Variables
56
  VALUE: variables_get(inputs(VAR: value)) // VAR is a variable ID
project/src/blocks/text.js CHANGED
@@ -503,6 +503,7 @@ const container_input = {
503
  ["Integer", "integer"],
504
  ["Float", "float"],
505
  ["List", "list"],
 
506
  ]
507
  },
508
  { type: "field_input", name: "NAME" },
@@ -524,6 +525,7 @@ const container_output = {
524
  ["Integer", "integer"],
525
  ["Float", "float"],
526
  ["List", "list"],
 
527
  ]
528
  },
529
  { type: "field_input", name: "NAME" },
@@ -635,6 +637,20 @@ const make_json = {
635
  fieldCount_: 1,
636
  };
637
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
638
  // Dynamic function call block
639
  const func_call = {
640
  type: "func_call",
@@ -1143,4 +1159,5 @@ export const blocks = Blockly.common.createBlockDefinitionsFromJsonArray([
1143
  llm_call,
1144
  call_api,
1145
  in_json,
 
1146
  ]);
 
503
  ["Integer", "integer"],
504
  ["Float", "float"],
505
  ["List", "list"],
506
+ ["Boolean", "boolean"],
507
  ]
508
  },
509
  { type: "field_input", name: "NAME" },
 
525
  ["Integer", "integer"],
526
  ["Float", "float"],
527
  ["List", "list"],
528
+ ["Boolean", "boolean"],
529
  ]
530
  },
531
  { type: "field_input", name: "NAME" },
 
637
  fieldCount_: 1,
638
  };
639
 
640
+ const lists_contains = {
641
+ type: "lists_contains",
642
+ message0: "item %1 in list %2",
643
+ args0: [
644
+ { type: "input_value", name: "ITEM", check: null },
645
+ { type: "input_value", name: "LIST", check: "Array" },
646
+ ],
647
+ output: "Boolean",
648
+ colour: 260,
649
+ inputsInline: true,
650
+ tooltip: "Check if an item exists in a list",
651
+ helpUrl: "",
652
+ };
653
+
654
  // Dynamic function call block
655
  const func_call = {
656
  type: "func_call",
 
1159
  llm_call,
1160
  call_api,
1161
  in_json,
1162
+ lists_contains,
1163
  ]);
project/src/generators/python.js CHANGED
@@ -40,6 +40,9 @@ forBlock['create_mcp'] = function (block, generator) {
40
  case 'list':
41
  pyType = 'list';
42
  break;
 
 
 
43
  default:
44
  pyType = 'Any';
45
  }
@@ -67,12 +70,14 @@ forBlock['create_mcp'] = function (block, generator) {
67
  }
68
  }
69
 
70
- // Type-cast numeric returns to ensure proper Gradio compatibility
71
  const outputType = block.outputTypes_[r] || 'string';
72
  if (outputType === 'integer' && returnValue) {
73
  returnValue = `int(${returnValue})`;
74
  } else if (outputType === 'float' && returnValue) {
75
  returnValue = `float(${returnValue})`;
 
 
76
  }
77
 
78
  returnValues.push(returnValue || 'None');
@@ -115,6 +120,9 @@ forBlock['create_mcp'] = function (block, generator) {
115
  case 'list':
116
  gradioInputs.push('gr.Dataframe()');
117
  break;
 
 
 
118
  default:
119
  gradioInputs.push('gr.Textbox()');
120
  }
@@ -141,6 +149,9 @@ forBlock['create_mcp'] = function (block, generator) {
141
  case 'list':
142
  gradioOutputs.push('gr.Dataframe()');
143
  break;
 
 
 
144
  default:
145
  gradioOutputs.push('gr.Textbox()');
146
  }
@@ -199,6 +210,9 @@ forBlock['func_def'] = function (block, generator) {
199
  case 'list':
200
  pyType = 'list';
201
  break;
 
 
 
202
  default:
203
  pyType = 'Any';
204
  }
@@ -224,12 +238,14 @@ forBlock['func_def'] = function (block, generator) {
224
  }
225
  }
226
 
227
- // Type-cast numeric returns to ensure proper Gradio compatibility
228
  const outputType = block.outputTypes_[r] || 'string';
229
  if (outputType === 'integer' && returnValue) {
230
  returnValue = `int(${returnValue})`;
231
  } else if (outputType === 'float' && returnValue) {
232
  returnValue = `float(${returnValue})`;
 
 
233
  }
234
 
235
  returnValues.push(returnValue || 'None');
@@ -362,4 +378,13 @@ forBlock['make_json'] = function (block, generator) {
362
  // Generate valid Python dict syntax
363
  const code = pairs.length > 0 ? `{${pairs.join(', ')}}` : '{}';
364
  return [code, Order.ATOMIC];
 
 
 
 
 
 
 
 
 
365
  };
 
40
  case 'list':
41
  pyType = 'list';
42
  break;
43
+ case 'boolean':
44
+ pyType = 'bool';
45
+ break;
46
  default:
47
  pyType = 'Any';
48
  }
 
70
  }
71
  }
72
 
73
+ // Type-cast returns to ensure proper Gradio compatibility
74
  const outputType = block.outputTypes_[r] || 'string';
75
  if (outputType === 'integer' && returnValue) {
76
  returnValue = `int(${returnValue})`;
77
  } else if (outputType === 'float' && returnValue) {
78
  returnValue = `float(${returnValue})`;
79
+ } else if (outputType === 'boolean' && returnValue) {
80
+ returnValue = `bool(${returnValue})`;
81
  }
82
 
83
  returnValues.push(returnValue || 'None');
 
120
  case 'list':
121
  gradioInputs.push('gr.Dataframe()');
122
  break;
123
+ case 'boolean':
124
+ gradioInputs.push('gr.Checkbox()');
125
+ break;
126
  default:
127
  gradioInputs.push('gr.Textbox()');
128
  }
 
149
  case 'list':
150
  gradioOutputs.push('gr.Dataframe()');
151
  break;
152
+ case 'boolean':
153
+ gradioOutputs.push('gr.Checkbox()');
154
+ break;
155
  default:
156
  gradioOutputs.push('gr.Textbox()');
157
  }
 
210
  case 'list':
211
  pyType = 'list';
212
  break;
213
+ case 'boolean':
214
+ pyType = 'bool';
215
+ break;
216
  default:
217
  pyType = 'Any';
218
  }
 
238
  }
239
  }
240
 
241
+ // Type-cast returns to ensure proper Gradio compatibility
242
  const outputType = block.outputTypes_[r] || 'string';
243
  if (outputType === 'integer' && returnValue) {
244
  returnValue = `int(${returnValue})`;
245
  } else if (outputType === 'float' && returnValue) {
246
  returnValue = `float(${returnValue})`;
247
+ } else if (outputType === 'boolean' && returnValue) {
248
+ returnValue = `bool(${returnValue})`;
249
  }
250
 
251
  returnValues.push(returnValue || 'None');
 
378
  // Generate valid Python dict syntax
379
  const code = pairs.length > 0 ? `{${pairs.join(', ')}}` : '{}';
380
  return [code, Order.ATOMIC];
381
+ };
382
+
383
+ forBlock['lists_contains'] = function (block, generator) {
384
+ const item = generator.valueToCode(block, 'ITEM', Order.NONE) || "''";
385
+ const list = generator.valueToCode(block, 'LIST', Order.NONE) || "[]";
386
+
387
+ // Generate code to check if item is in list
388
+ const code = `${item} in ${list}`;
389
+ return [code, Order.ATOMIC];
390
  };
project/src/index.js CHANGED
@@ -1274,12 +1274,10 @@ const updateCode = () => {
1274
  const blocks = ws.getAllBlocks(false);
1275
  const hasCall = blocks.some(block => block.type === 'llm_call');
1276
  const hasAPI = blocks.some(block => block.type === 'call_api');
1277
- const hasListSort = code.includes('lists_sort(');
1278
  const hasPrime = code.includes('math_isPrime(');
1279
 
1280
  if (hasCall) code = call + code;
1281
  if (hasAPI) code = API + code;
1282
- if (hasListSort) code = listSort + code;
1283
 
1284
  if (hasPrime) {
1285
  code = code.replace(/math_isPrime\(([^)]*)\)/g, 'isprime($1)');
 
1274
  const blocks = ws.getAllBlocks(false);
1275
  const hasCall = blocks.some(block => block.type === 'llm_call');
1276
  const hasAPI = blocks.some(block => block.type === 'call_api');
 
1277
  const hasPrime = code.includes('math_isPrime(');
1278
 
1279
  if (hasCall) code = call + code;
1280
  if (hasAPI) code = API + code;
 
1281
 
1282
  if (hasPrime) {
1283
  code = code.replace(/math_isPrime\(([^)]*)\)/g, 'isprime($1)');
project/src/toolbox.js CHANGED
@@ -518,6 +518,10 @@ export const toolbox = {
518
  kind: 'block',
519
  type: 'lists_reverse',
520
  },
 
 
 
 
521
  ],
522
  },
523
  {
 
518
  kind: 'block',
519
  type: 'lists_reverse',
520
  },
521
+ {
522
+ kind: 'block',
523
+ type: 'lists_contains',
524
+ },
525
  ],
526
  },
527
  {
project/test.py CHANGED
@@ -155,7 +155,11 @@ def execute_blockly_logic(user_inputs):
155
  elif anno == float:
156
  typed_args.append(float(arg))
157
  elif anno == bool:
158
- typed_args.append(str(arg).lower() in ("true", "1"))
 
 
 
 
159
  elif anno == list:
160
  try:
161
  # Convert string like '["a", "b", "c"]' into an actual list
@@ -193,7 +197,7 @@ def execute_blockly_logic(user_inputs):
193
  print("[EXECUTION ERROR]", e)
194
  result = f"Error: {str(e)}"
195
 
196
- return result if result else "No output generated"
197
 
198
 
199
  def build_interface():
@@ -279,12 +283,13 @@ def build_interface():
279
  out_types = []
280
  else:
281
  out_types = []
282
- # Convert output types: handle string, integer, float, list
283
  out_types = [
284
  "string" if t == "str" else
285
  "integer" if t == "int" else
286
  "float" if t == "float" else
287
- "list" if t == "list" else t
 
288
  for t in out_types
289
  ]
290
 
 
155
  elif anno == float:
156
  typed_args.append(float(arg))
157
  elif anno == bool:
158
+ # Handle boolean conversion from string (checkbox in Gradio sends True/False)
159
+ if isinstance(arg, bool):
160
+ typed_args.append(arg)
161
+ else:
162
+ typed_args.append(str(arg).lower() in ("true", "1"))
163
  elif anno == list:
164
  try:
165
  # Convert string like '["a", "b", "c"]' into an actual list
 
197
  print("[EXECUTION ERROR]", e)
198
  result = f"Error: {str(e)}"
199
 
200
+ return result if result is not None and result != "" else "No output generated"
201
 
202
 
203
  def build_interface():
 
283
  out_types = []
284
  else:
285
  out_types = []
286
+ # Convert output types: handle string, integer, float, list, boolean
287
  out_types = [
288
  "string" if t == "str" else
289
  "integer" if t == "int" else
290
  "float" if t == "float" else
291
+ "list" if t == "list" else
292
+ "boolean" if t == "bool" else t
293
  for t in out_types
294
  ]
295