fastworkflow 2.17.8__py3-none-any.whl → 2.17.10__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.
@@ -407,7 +407,7 @@ Today's date is {today}.
407
407
  parsed = ast.literal_eval(text)
408
408
  if isinstance(parsed, list):
409
409
  return parsed
410
- # Fallback: comma-separated
410
+ # Comma-separated values
411
411
  if "," in text:
412
412
  parts = [p.strip() for p in text.split(",")]
413
413
  cleaned = [
@@ -415,6 +415,12 @@ Today's date is {today}.
415
415
  for p in parts
416
416
  ]
417
417
  return cleaned
418
+ # Single value - treat as a list with one element
419
+ if text:
420
+ # Remove quotes if present
421
+ if len(text) >= 2 and ((text[0] == text[-1] == '"') or (text[0] == text[-1] == "'")):
422
+ return [text[1:-1]]
423
+ return [text]
418
424
  return None
419
425
 
420
426
  def _coerce_scalar(expected_type: Type[Any], val: Any) -> Tuple[bool, Optional[Any]]:
@@ -511,7 +517,48 @@ Today's date is {today}.
511
517
 
512
518
  if valid_by_type:
513
519
  if corrected_value is not None:
514
- setattr(cmd_parameters, field_name, corrected_value)
520
+ pattern = next(
521
+ (meta.pattern
522
+ for meta in getattr(field_info, "metadata", [])
523
+ if hasattr(meta, "pattern")),
524
+ None,
525
+ )
526
+ if pattern and field_value is not None and field_value != NOT_FOUND:
527
+ invalid_value = None
528
+ if hasattr(field_info, "json_schema_extra") and field_info.json_schema_extra:
529
+ invalid_value = field_info.json_schema_extra.get("invalid_value")
530
+
531
+ # if invalid_value and field_value == invalid_value:
532
+ # invalid_fields.append(f"{field_name} '{field_value}'")
533
+ # pattern_str = str(pattern)
534
+ # examples = getattr(field_info, "examples", [])
535
+ # example = examples[0] if examples else ""
536
+ # all_suggestions[field_name] = [f"Please use the format matching pattern {pattern_str} (e.g., {example})"]
537
+ # is_valid = False
538
+
539
+ # else:
540
+ pattern_regex = re.compile(pattern)
541
+ if not pattern_regex.fullmatch(str(field_value)):
542
+ invalid_fields.append(f"{field_name} '{field_value}'")
543
+ pattern_str = str(pattern)
544
+ examples = getattr(field_info, "examples", [])
545
+ example = examples[0] if examples else ""
546
+
547
+ invalid_fields.append(f"{field_name} '{field_value}'")
548
+ all_suggestions[field_name] = [f"Please use the format matching pattern {pattern_str} (e.g., {example})"]
549
+ is_valid = False
550
+ else:
551
+ try:
552
+ setattr(cmd_parameters, field_name, corrected_value)
553
+ except Exception as e:
554
+ logger.critical(f"Failed to set attribute {field_name} with value {corrected_value}")
555
+ raise e
556
+ else:
557
+ try:
558
+ setattr(cmd_parameters, field_name, corrected_value)
559
+ except Exception as e:
560
+ logger.critical(f"Failed to set attribute {field_name} with value {corrected_value}")
561
+ raise e
515
562
  else:
516
563
  invalid_fields.append(f"{field_name} '{field_value}'")
517
564
  all_suggestions[field_name] = build_type_suggestion()
@@ -539,35 +586,6 @@ Today's date is {today}.
539
586
  missing_fields.append(field_name)
540
587
  is_valid = False
541
588
 
542
- pattern = next(
543
- (meta.pattern
544
- for meta in getattr(field_info, "metadata", [])
545
- if hasattr(meta, "pattern")),
546
- None,
547
- )
548
- if pattern and field_value is not None and field_value != NOT_FOUND:
549
- invalid_value = None
550
- if hasattr(field_info, "json_schema_extra") and field_info.json_schema_extra:
551
- invalid_value = field_info.json_schema_extra.get("invalid_value")
552
-
553
- if invalid_value and field_value == invalid_value:
554
- invalid_fields.append(f"{field_name} '{field_value}'")
555
- pattern_str = str(pattern)
556
- examples = getattr(field_info, "examples", [])
557
- example = examples[0] if examples else ""
558
- all_suggestions[field_name] = [f"Please use the format matching pattern {pattern_str} (e.g., {example})"]
559
- is_valid = False
560
-
561
- else:
562
- pattern_regex = re.compile(pattern)
563
- if not pattern_regex.fullmatch(str(field_value)):
564
- invalid_fields.append(f"{field_name} '{field_value}'")
565
- pattern_str = str(pattern)
566
- examples = getattr(field_info, "examples", [])
567
- example = examples[0] if examples else ""
568
- all_suggestions[field_name] = [f"Please use the format matching pattern {pattern_str} (e.g., {example})"]
569
- is_valid = False
570
-
571
589
  for field_name, field_info in type(cmd_parameters).model_fields.items():
572
590
  field_value = getattr(cmd_parameters, field_name, None)
573
591
 
@@ -99,10 +99,10 @@ def _execute_workflow_query(command: str, chat_session_obj: fastworkflow.ChatSes
99
99
  # Extract command name and parameters from command_output
100
100
  name = command_output.command_name
101
101
  params = command_output.command_parameters
102
-
102
+
103
103
  # Handle parameter serialization
104
104
  params_dict = params.model_dump() if params else None
105
-
105
+
106
106
  # Extract response text
107
107
  response_text = ""
108
108
  if command_output.command_responses:
@@ -135,8 +135,81 @@ def _execute_workflow_query(command: str, chat_session_obj: fastworkflow.ChatSes
135
135
  with open("action.jsonl", "a", encoding="utf-8") as f:
136
136
  f.write(json.dumps(record, ensure_ascii=False) + "\n")
137
137
 
138
- if 'PARAMETER EXTRACTION ERROR' in response_text or 'The command is ambiguous' in response_text:
139
- abort_confirmation = _execute_workflow_query('abort', chat_session_obj = chat_session_obj)
138
+ # Check workflow context to determine if we're in an error state that needs specialized handling
139
+ cme_workflow = chat_session_obj.cme_workflow
140
+ nlu_stage = cme_workflow.context.get("NLU_Pipeline_Stage")
141
+
142
+ # Handle intent ambiguity clarification state with specialized agent
143
+ if nlu_stage == fastworkflow.NLUPipelineStage.INTENT_AMBIGUITY_CLARIFICATION:
144
+ if intent_agent := chat_session_obj.intent_clarification_agent:
145
+ # Get suggested commands from intent detection system
146
+ from fastworkflow._workflows.command_metadata_extraction.intent_detection import CommandNamePrediction
147
+ predictor = CommandNamePrediction(cme_workflow)
148
+ suggested_commands = predictor._get_suggested_commands(predictor.path)
149
+
150
+ suggested_commands = list(suggested_commands) if suggested_commands is not None else []
151
+
152
+ # Get metadata for only the suggested commands
153
+ current_workflow = chat_session_obj.get_active_workflow()
154
+ suggested_commands_metadata = CommandMetadataAPI.get_suggested_commands_metadata(
155
+ subject_workflow_path=current_workflow.folderpath,
156
+ cme_workflow_path=fastworkflow.get_internal_workflow_path("command_metadata_extraction"),
157
+ active_context_name=current_workflow.current_command_context_name,
158
+ suggested_command_names=suggested_commands
159
+ )
160
+
161
+ # Get the workflow agent's trajectory and inputs for context
162
+ workflow_tool_agent = chat_session_obj.workflow_tool_agent
163
+ agent_inputs = workflow_tool_agent.inputs if workflow_tool_agent else {}
164
+ agent_trajectory = workflow_tool_agent.current_trajectory if workflow_tool_agent else {}
165
+
166
+ lm = dspy_utils.get_lm("LLM_AGENT", "LITELLM_API_KEY_AGENT")
167
+ with dspy.context(lm=lm):
168
+ result = intent_agent(
169
+ original_command=command,
170
+ error_message=response_text,
171
+ agent_inputs=agent_inputs,
172
+ agent_trajectory=agent_trajectory,
173
+ suggested_commands_metadata=suggested_commands_metadata
174
+ )
175
+ # The clarified command should have the correct name with all original parameters
176
+ clarified_cmd = result.clarified_command if hasattr(result, 'clarified_command') else str(result)
177
+ # Execute the clarified command
178
+ return _execute_workflow_query(clarified_cmd, chat_session_obj=chat_session_obj)
179
+ else:
180
+ # No intent clarification agent available, fall back to abort
181
+ abort_confirmation = _execute_workflow_query('abort', chat_session_obj=chat_session_obj)
182
+ return f'{response_text}\n{abort_confirmation}'
183
+
184
+ # Handle intent misunderstanding clarification state with specialized agent
185
+ if nlu_stage == fastworkflow.NLUPipelineStage.INTENT_MISUNDERSTANDING_CLARIFICATION:
186
+ if intent_agent := chat_session_obj.intent_clarification_agent:
187
+ # Get the workflow agent's trajectory and inputs for context
188
+ workflow_tool_agent = chat_session_obj.workflow_tool_agent
189
+ agent_inputs = workflow_tool_agent.inputs if workflow_tool_agent else {}
190
+ agent_trajectory = workflow_tool_agent.current_trajectory if workflow_tool_agent else {}
191
+
192
+ lm = dspy_utils.get_lm("LLM_AGENT", "LITELLM_API_KEY_AGENT")
193
+ with dspy.context(lm=lm):
194
+ result = intent_agent(
195
+ original_command=command,
196
+ error_message=response_text,
197
+ agent_inputs=agent_inputs,
198
+ agent_trajectory=agent_trajectory,
199
+ suggested_commands_metadata=""
200
+ )
201
+
202
+ clarified_cmd = result.clarified_command if hasattr(result, 'clarified_command') else str(result)
203
+
204
+ return _execute_workflow_query(clarified_cmd, chat_session_obj=chat_session_obj)
205
+ else:
206
+ # No intent clarification agent available, fall back to abort
207
+ abort_confirmation = _execute_workflow_query('abort', chat_session_obj=chat_session_obj)
208
+ return f'{response_text}\n{abort_confirmation}'
209
+
210
+ # Handle parameter extraction errors with abort
211
+ if nlu_stage == fastworkflow.NLUPipelineStage.PARAMETER_EXTRACTION:
212
+ abort_confirmation = _execute_workflow_query('abort', chat_session_obj=chat_session_obj)
140
213
  return f'{response_text}\n{abort_confirmation}'
141
214
 
142
215
  return response_text
@@ -253,6 +326,7 @@ def initialize_workflow_tool_agent(chat_session: fastworkflow.ChatSession, max_i
253
326
  The clarification_request must be plain text without any formatting.
254
327
  Note that using the wrong command name can produce missing information errors. Double-check with the what_can_i_do tool to verify that the correct command name is being used
255
328
  """
329
+ chat_session_obj.workflow_tool_agent.iteration_counter = 0 # reset iteration counter, everytime we ask the user
256
330
  return _ask_user_tool(clarification_request, chat_session_obj=chat_session_obj)
257
331
 
258
332
  tools = [
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fastworkflow
3
- Version: 2.17.8
3
+ Version: 2.17.10
4
4
  Summary: A framework for rapidly building large-scale, deterministic, interactive workflows with a fault-tolerant, conversational UX
5
5
  License: Apache-2.0
6
6
  Keywords: fastworkflow,ai,workflow,llm,openai
@@ -13,7 +13,7 @@ fastworkflow/_workflows/command_metadata_extraction/_commands/__init__.py,sha256
13
13
  fastworkflow/_workflows/command_metadata_extraction/_commands/wildcard.py,sha256=Sqpc2hwM-DgmsqiHu3OoOuqo3XnHLkFlmyYCJA8nj_8,7843
14
14
  fastworkflow/_workflows/command_metadata_extraction/command_context_model.json,sha256=zGWBweQSmFf7WsfR_F2DE7AJ8S8-q7F9ZbvyccysJJI,117
15
15
  fastworkflow/_workflows/command_metadata_extraction/intent_detection.py,sha256=Ci0Cut_rH8wpUlLEsTMK-OhT3AO2nKgJmXQYIsoTzJw,14543
16
- fastworkflow/_workflows/command_metadata_extraction/parameter_extraction.py,sha256=MgNkPgA05E1-LSw9pNKDlXdsAphulYNhuDeTTqk5dBY,13686
16
+ fastworkflow/_workflows/command_metadata_extraction/parameter_extraction.py,sha256=Vo3ff1fivB6fXRwALRpAsTO5r3FHdOABvUq_QxpxEKY,17089
17
17
  fastworkflow/build/__main__.py,sha256=NtedkZfM56qoEJ5vQECSURbE8AMTfwHN3tAZyZoWabk,15905
18
18
  fastworkflow/build/ast_class_extractor.py,sha256=F9OG4stkp7w3kadKqxMm8h3ZDSp_zg6mwcrKMl_XqdI,13527
19
19
  fastworkflow/build/class_analysis_structures.py,sha256=UWOKcs9pCiNuXc64hNywkTJq5X5KfG1pqdSZwWiZh-c,4053
@@ -35,13 +35,13 @@ fastworkflow/build/navigator_stub_generator.py,sha256=_DSvHC6r1xWQiFHtUgPhI51nQf
35
35
  fastworkflow/build/pydantic_model_generator.py,sha256=oNyoANyUWBpHG-fE3tGL911RNvDzQXjxAm0ssvuXUH4,1854
36
36
  fastworkflow/build/utterance_generator.py,sha256=UrtkF0wyAZ1hiFitHX0g8w7Wh-D0leLCrP1aUACSfHo,299
37
37
  fastworkflow/cache_matching.py,sha256=OoB--1tO6-O4BKCuCrUbB0CkUr76J62K4VAf6MShi-w,7984
38
- fastworkflow/chat_session.py,sha256=u3aQauea5vYmt98_ADTkWzkF_WsJaaiA8AX6OlGeyf8,32332
38
+ fastworkflow/chat_session.py,sha256=O1HFst4GcglS0xR8lu2iaHiXzmNv0QVhdQ-8Nn2BFRw,35175
39
39
  fastworkflow/cli.py,sha256=n-PFDC0EOkq1zIK1Ip44at-VcaP9cW9aSxZ2IVj3VoE,23796
40
40
  fastworkflow/command_context_model.py,sha256=bQadDB_IH2lc0br46IT07Iej_j2KrAMderiVKqU7gno,15914
41
41
  fastworkflow/command_directory.py,sha256=aJ6UQCwevfF11KbcQB2Qz6mQ7Kj91pZtvHmQY6JFnao,29030
42
42
  fastworkflow/command_executor.py,sha256=WTSrukv6UDQfWUDSNleIQ1TxwDnAQIKIimh4sQVwnig,8457
43
43
  fastworkflow/command_interfaces.py,sha256=PWIKlcp0G8nmYl0vkrg1o6QzJL0pxXkfrn1joqTa0eU,460
44
- fastworkflow/command_metadata_api.py,sha256=J5ltiwOhFRf1fggm8yWziKPrZA3trKt_rkyBtSS0H3I,42233
44
+ fastworkflow/command_metadata_api.py,sha256=PBu9c8iwYLcRy7YipAv6wKDimK7YZOweTe_q3rFuDMg,44191
45
45
  fastworkflow/command_routing.py,sha256=R7194pcY0d2VHzmCu9ALacm1UvNuIRIvTn8mLp-EZIM,17219
46
46
  fastworkflow/docs/context_modules_prd.txt,sha256=9wvs3LgNoIVXAczo1sXBIV4YmFqVhzC2ja1T3K7FG04,2199
47
47
  fastworkflow/examples/extended_workflow_example/README.md,sha256=2O0O4Bg--fwF98YDScnkNCUL3PcH8KpX2p6I1cwNWeg,2864
@@ -140,21 +140,22 @@ fastworkflow/examples/simple_workflow_template/application/__init__.py,sha256=47
140
140
  fastworkflow/examples/simple_workflow_template/application/workitem.py,sha256=Sm-QoX-EZvynkNf7uO3dViZF2VZqUlr6PAZZ7yjQEfk,40197
141
141
  fastworkflow/examples/simple_workflow_template/simple_workflow_template.json,sha256=A-dAl5iD9ehdMGGn05O2Kjwq6ZetqQjAGzlM1st0K9U,1237
142
142
  fastworkflow/examples/simple_workflow_template/startup_action.json,sha256=gj0-B4CqTYCs8OwHKhTu95H4uZbLsDf1th06IFfNXVs,75
143
+ fastworkflow/intent_clarification_agent.py,sha256=UW5gj4Tg0wXduLRbDTkidVgBl-Cx-Esx_z9xRigMUJc,5215
143
144
  fastworkflow/mcp_server.py,sha256=NxbLSKf2MA4lAHVcm6ZfiVuOjVO6IeV5Iw17wImFbxQ,8867
144
145
  fastworkflow/model_pipeline_training.py,sha256=P_9wrYSfJVSYCTu8VEPkgXJ16eH58LLCK4rCRbRFAVg,46740
145
146
  fastworkflow/refine/__main__.py,sha256=bDLpPNMcdp8U4EFnMdjxx1sPDQCZuEJoBURr2KebTng,3398
146
147
  fastworkflow/run/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
147
148
  fastworkflow/run/__main__.py,sha256=XmybAsr1MnCx8tzvhWxtBT7xu2Om3PVZFtABXavPccU,12075
148
- fastworkflow/run_fastapi_mcp/README.md,sha256=THJVLHXrPQ3ePZKbSHV9o-aQcgT20lv4nbgeLZDhJDY,10806
149
+ fastworkflow/run_fastapi_mcp/README.md,sha256=dAmG2KF-9mqSjyIPSA9vhUit-DjsDH6WJUDCkQ3C1is,11943
149
150
  fastworkflow/run_fastapi_mcp/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
150
- fastworkflow/run_fastapi_mcp/__main__.py,sha256=ggsT9o2sKR1zNyovIhBo09Ha1JZx7SzSdX8tAY6jLds,48782
151
- fastworkflow/run_fastapi_mcp/conversation_store.py,sha256=OuS6Yq5noXrNn5jPwld_KueVi53Jlpa0qvF_vLUIbgg,13516
152
- fastworkflow/run_fastapi_mcp/jwt_manager.py,sha256=6djyNebME5U5hF_d42T9PjFOb2yDvXg2B03YjiAVXC4,11878
151
+ fastworkflow/run_fastapi_mcp/__main__.py,sha256=R3A5PUoBXtEufaTTKF92kWhBuDg3xsVG0IQEyg4XJOI,53536
152
+ fastworkflow/run_fastapi_mcp/conversation_store.py,sha256=2qnNLO_RVHznbIzTjpdff7szsrGyr1FVt1spcKvkrKk,13534
153
+ fastworkflow/run_fastapi_mcp/jwt_manager.py,sha256=o3JLV71WiKNhr61KFIrYDnYQvvNYrqhSqEnsWNBUya4,12480
153
154
  fastworkflow/run_fastapi_mcp/mcp_specific.py,sha256=RdOPcPn68KlxNSM9Vb2yeYEDNGoNTcKZq-AC0cd86cw,4506
154
155
  fastworkflow/run_fastapi_mcp/redoc_2_standalone_html.py,sha256=oYWn30O-xKX6pVjunCeLupyOM2DbeZ3QgFj-F2LalOE,1191
155
- fastworkflow/run_fastapi_mcp/utils.py,sha256=A09htp-8Q2ksKM-nyor5V5bwek1O7prBSwHyGsxjBoo,17142
156
+ fastworkflow/run_fastapi_mcp/utils.py,sha256=SX6meWba0T-iYn7YmEajbwJrijfVVUuYGv4usDXzA2c,19589
156
157
  fastworkflow/train/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
157
- fastworkflow/train/__main__.py,sha256=AeGja42d0QhslQkxvDVigIluxxL7DYLdQPXYFOKQ7QA,8536
158
+ fastworkflow/train/__main__.py,sha256=03OeHVwa7MmBNHGtBrQ-0cT2rtrVtAiQtvQBzkcbp3w,8533
158
159
  fastworkflow/train/generate_synthetic.py,sha256=sTDk-E5ewkS4o-0LJeofiEv4uXGpqdGcFRYKY_Yf36Y,5322
159
160
  fastworkflow/user_message_queues.py,sha256=svbuFxQ16q6Tz6urPWfD4IEsOTMxtS1Kc1PP8EE8AWg,1422
160
161
  fastworkflow/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -171,14 +172,14 @@ fastworkflow/utils/logging.py,sha256=2SA-04fg7Lx_vGf980tfCOGDQxBvU9X6Vbhv47rbdaw
171
172
  fastworkflow/utils/parameterize_func_decorator.py,sha256=V6YJnishWRCdwiBQW6P17hmGGrga0Empk-AN5Gm7iMk,633
172
173
  fastworkflow/utils/pydantic_model_2_dspy_signature_class.py,sha256=w1pvl8rJq48ulFwaAtBgfXYn_SBIDBgq1aLMUg1zJn8,12875
173
174
  fastworkflow/utils/python_utils.py,sha256=D0JBdzkwKoyK7XvZcnIxOgsS8CRGdvuW-zcO45_pfOA,8252
174
- fastworkflow/utils/react.py,sha256=2nsmtwFZJ9QkZqNxDt94a1cpuFSZplTTYeH-Z2dEX5s,11668
175
- fastworkflow/utils/signatures.py,sha256=QOLX3j-AJkRWIkDhogbhxQo8MIt668xIKwd4SWiS2LY,31734
175
+ fastworkflow/utils/react.py,sha256=eROhiG0TQACLqa-4aVQB36kr4KsnqqQTQjqQdMpImCs,12384
176
+ fastworkflow/utils/signatures.py,sha256=uv1HxkVK8yzu6xt0ci8RUSgQW0Njaz22YuJVO_aNUEM,33393
176
177
  fastworkflow/utils/startup_progress.py,sha256=9icSdnpFAxzIq0sUliGpNaH0Efvrt5lDtGfURV5BD98,3539
177
178
  fastworkflow/workflow.py,sha256=37gn7e3ct-gdGw43zS6Ab_ADoJJBO4eJW2PywfUpjEg,18825
178
- fastworkflow/workflow_agent.py,sha256=-RXoHXH-vrEh6AWC6iYAwwR9CvaRynYuu-KrzOPCJbg,16348
179
+ fastworkflow/workflow_agent.py,sha256=-JxcF_T7bfT1sgizyUbgQmiPc7SnYxfnJkmRWZXNcIk,20708
179
180
  fastworkflow/workflow_inheritance_model.py,sha256=Pp-qSrQISgPfPjJVUfW84pc7HLmL2evuq0UVIYR51K0,7974
180
- fastworkflow-2.17.8.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
181
- fastworkflow-2.17.8.dist-info/METADATA,sha256=gO8KAHW-610IsPFNAaowDYDLiGZyLx9EafazpL_-moo,30634
182
- fastworkflow-2.17.8.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
183
- fastworkflow-2.17.8.dist-info/entry_points.txt,sha256=m8HqoPzCyaZLAx-V5X8MJgw3Lx3GiPDlxNEZ7K-Gb-U,54
184
- fastworkflow-2.17.8.dist-info/RECORD,,
181
+ fastworkflow-2.17.10.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
182
+ fastworkflow-2.17.10.dist-info/METADATA,sha256=JvxWPbCGYSxT7j_TbSTp68Zv8u4uhoU2Gy--jViCCIo,30635
183
+ fastworkflow-2.17.10.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
184
+ fastworkflow-2.17.10.dist-info/entry_points.txt,sha256=m8HqoPzCyaZLAx-V5X8MJgw3Lx3GiPDlxNEZ7K-Gb-U,54
185
+ fastworkflow-2.17.10.dist-info/RECORD,,