fastworkflow 2.15.4__py3-none-any.whl → 2.15.5__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.
fastworkflow/__init__.py CHANGED
@@ -1,6 +1,8 @@
1
1
  import contextlib
2
+ from dataclasses import dataclass
2
3
  from enum import Enum
3
4
  import os
5
+ import time
4
6
  from typing import Any, Optional, Union
5
7
 
6
8
  from pydantic import BaseModel
@@ -47,6 +49,20 @@ class MCPToolResult(BaseModel):
47
49
  content: list[MCPContent]
48
50
  isError: bool = False
49
51
 
52
+ class CommandTraceEventDirection(str, Enum):
53
+ AGENT_TO_WORKFLOW = "agent_to_workflow"
54
+ WORKFLOW_TO_AGENT = "workflow_to_agent"
55
+
56
+ @dataclass
57
+ class CommandTraceEvent:
58
+ direction: CommandTraceEventDirection
59
+ raw_command: str | None # for AGENT_TO_WORKFLOW
60
+ command_name: str | None # for WORKFLOW_TO_AGENT
61
+ parameters: dict | str | None
62
+ response_text: str | None
63
+ success: bool | None
64
+ timestamp_ms: int
65
+
50
66
  class CommandOutput(BaseModel):
51
67
  command_responses: list[CommandResponse]
52
68
  workflow_name: str = ""
@@ -119,6 +119,7 @@ class ChatSession:
119
119
  # Create queues for user messages and command outputs
120
120
  self._user_message_queue = Queue()
121
121
  self._command_output_queue = Queue()
122
+ self._command_trace_queue = Queue()
122
123
  self._status = SessionStatus.STOPPED
123
124
  self._chat_worker = None
124
125
 
@@ -290,6 +291,10 @@ class ChatSession:
290
291
  def command_output_queue(self) -> Queue:
291
292
  return self._command_output_queue
292
293
 
294
+ @property
295
+ def command_trace_queue(self) -> Queue:
296
+ return self._command_trace_queue
297
+
293
298
  @property
294
299
  def workflow_is_complete(self) -> bool:
295
300
  workflow = ChatSession.get_active_workflow()
@@ -45,18 +45,7 @@ class CommandExecutor(CommandExecutorInterface):
45
45
  command = command)
46
46
  )
47
47
 
48
- import json
49
-
50
48
  if command_output.command_handled or not command_output.success:
51
- # Append executed action to action.json for external consumers
52
- record = {
53
- "command" if command_output.success else "failing command": command,
54
- "command_name": command_output.command_name,
55
- "parameters": command_output.command_parameters.model_dump() if command_output.command_parameters else None,
56
- "response": command_output.command_responses[0].response if command_output.success else ''}
57
- with open("action.json", "a", encoding="utf-8") as f:
58
- f.write(json.dumps(record, ensure_ascii=False) + "\n")
59
-
60
49
  return command_output
61
50
 
62
51
  command_name = command_output.command_responses[0].artifacts["command_name"]
@@ -93,16 +82,7 @@ class CommandExecutor(CommandExecutorInterface):
93
82
  command_output.workflow_name = workflow_name
94
83
  command_output.context = context
95
84
  command_output.command_name = command_name
96
- command_output.command_parameters = str(input_obj) if input_obj else ''
97
-
98
- # Append executed action to action.json for external consumers
99
- record = {
100
- "command": command,
101
- "command_name": command_name,
102
- "parameters": input_obj.model_dump() if input_obj else None,
103
- "response": command_output.command_responses[0].response}
104
- with open("action.json", "a", encoding="utf-8") as f:
105
- f.write(json.dumps(record, ensure_ascii=False) + "\n")
85
+ command_output.command_parameters = input_obj or None
106
86
 
107
87
  return command_output
108
88
 
@@ -219,6 +219,29 @@ def run_main(args):
219
219
  with console.status("[bold cyan]Processing command...[/bold cyan]", spinner="dots") as status:
220
220
  counter = 0
221
221
  while wait_thread.is_alive():
222
+ # Check for agent traces if in agent mode
223
+ if args.run_as_agent:
224
+ while True:
225
+ try:
226
+ evt = fastworkflow.chat_session.command_trace_queue.get_nowait()
227
+ except queue.Empty:
228
+ break
229
+
230
+ # Choose styles based on success
231
+ info_style = "dim orange3" if (evt.success is False) else "dim yellow"
232
+ resp_style = "dim orange3" if (evt.success is False) else "dim green"
233
+
234
+ if evt.direction == fastworkflow.CommandTraceEventDirection.AGENT_TO_WORKFLOW:
235
+ console.print(Text("Agent -> Workflow: ", style=info_style), end="")
236
+ console.print(Text(str(evt.raw_command or ""), style=info_style))
237
+ else:
238
+ # command info (dim yellow or dim orange3)
239
+ info = f"{evt.command_name or ''}, {evt.parameters}: "
240
+ console.print(Text("Workflow -> Agent: ", style=info_style), end="")
241
+ console.print(Text(info, style=info_style), end="")
242
+ # response (dim green or dim orange3)
243
+ console.print(Text(str(evt.response_text or ""), style=resp_style))
244
+
222
245
  time.sleep(0.5)
223
246
  counter += 1
224
247
  if counter % 2 == 0: # Update message every second
@@ -3,6 +3,8 @@ Agent integration module for fastWorkflow.
3
3
  Provides workflow tool agent functionality for intelligent tool selection.
4
4
  """
5
5
 
6
+ import json
7
+ import time
6
8
  import dspy
7
9
 
8
10
  import fastworkflow
@@ -78,18 +80,67 @@ def _execute_workflow_query(command: str, chat_session_obj: fastworkflow.ChatSes
78
80
  Commands must be formatted using plain text for command name followed by XML tags enclosing parameter values (if any) as follows: command_name <param1_name>param1_value</param1_name> <param2_name>param2_value</param2_name> ...
79
81
  Don't use this tool to respond to a clarification requests in PARAMETER EXTRACTION ERROR state
80
82
  """
83
+ # Emit trace event before execution
84
+ chat_session_obj.command_trace_queue.put(fastworkflow.CommandTraceEvent(
85
+ direction=fastworkflow.CommandTraceEventDirection.AGENT_TO_WORKFLOW,
86
+ raw_command=command,
87
+ command_name=None,
88
+ parameters=None,
89
+ response_text=None,
90
+ success=None,
91
+ timestamp_ms=int(time.time() * 1000),
92
+ ))
93
+
81
94
  # Directly invoke the command without going through queues
82
95
  # This allows the agent to synchronously call workflow tools
83
96
  from fastworkflow.command_executor import CommandExecutor
84
97
  command_output = CommandExecutor.invoke_command(chat_session_obj, command)
85
98
 
99
+ # Emit trace event after execution
100
+ # Extract command name and parameters from command_output
101
+ name = command_output.command_name
102
+ params = command_output.command_parameters
103
+
104
+ # Handle parameter serialization
105
+ params_dict = params.model_dump() if params else None
106
+
107
+ # Extract response text
108
+ resp_text = ""
109
+ if command_output.command_responses:
110
+ response_parts = [
111
+ cmd_response.response
112
+ for cmd_response in command_output.command_responses
113
+ if cmd_response.response
114
+ ]
115
+ resp_text = "\n".join(response_parts)
116
+
117
+ chat_session_obj.command_trace_queue.put(fastworkflow.CommandTraceEvent(
118
+ direction=fastworkflow.CommandTraceEventDirection.WORKFLOW_TO_AGENT,
119
+ raw_command=None,
120
+ command_name=name,
121
+ parameters=params_dict,
122
+ response_text=resp_text or "",
123
+ success=bool(command_output.success),
124
+ timestamp_ms=int(time.time() * 1000),
125
+ ))
126
+
127
+ # Append executed action to action.json for external consumers (agent mode only)
128
+ record = {
129
+ "command" if command_output.success else "failing command": command,
130
+ "command_name": name,
131
+ "parameters": params_dict,
132
+ "response": resp_text if command_output.success else ""
133
+ }
134
+ with open("action.json", "a", encoding="utf-8") as f:
135
+ f.write(json.dumps(record, ensure_ascii=False) + "\n")
136
+
86
137
  # Format output - extract text from command response
87
- if hasattr(command_output, 'command_responses') and command_output.command_responses:
138
+ if command_output.command_responses:
88
139
  response_parts = []
89
140
  response_parts.extend(
90
141
  cmd_response.response
91
142
  for cmd_response in command_output.command_responses
92
- if hasattr(cmd_response, 'response') and cmd_response.response
143
+ if cmd_response.response
93
144
  )
94
145
  return "\n".join(response_parts) if response_parts else "Command executed successfully."
95
146
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fastworkflow
3
- Version: 2.15.4
3
+ Version: 2.15.5
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
@@ -1,5 +1,5 @@
1
1
  fastworkflow/.DS_Store,sha256=CTvh7SVnPHlYsgd1jwLq9digT-k8QV6JS7JgXEw0OVo,8196
2
- fastworkflow/__init__.py,sha256=FbOtFQsjbYXcMjL800X46LcDayzqmB6RDZL782_hj9w,7102
2
+ fastworkflow/__init__.py,sha256=wrifGmkwLnHs6BupEliX20cDuV7WkQEKjNspunkzBlc,7604
3
3
  fastworkflow/_commands/.gitkeep,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  fastworkflow/_workflows/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
5
  fastworkflow/_workflows/command_metadata_extraction/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -33,11 +33,11 @@ fastworkflow/build/navigator_stub_generator.py,sha256=_DSvHC6r1xWQiFHtUgPhI51nQf
33
33
  fastworkflow/build/pydantic_model_generator.py,sha256=oNyoANyUWBpHG-fE3tGL911RNvDzQXjxAm0ssvuXUH4,1854
34
34
  fastworkflow/build/utterance_generator.py,sha256=UrtkF0wyAZ1hiFitHX0g8w7Wh-D0leLCrP1aUACSfHo,299
35
35
  fastworkflow/cache_matching.py,sha256=OoB--1tO6-O4BKCuCrUbB0CkUr76J62K4VAf6MShi-w,7984
36
- fastworkflow/chat_session.py,sha256=KfbRrw4fhTANNifgA6oSmZP7nlz9xSo1dOx3x-B7foI,27848
36
+ fastworkflow/chat_session.py,sha256=rdW26lnBjBSmeb3q-JDeihdw-kJEv8HLIXyxhTavGmU,27992
37
37
  fastworkflow/cli.py,sha256=RB78V78NAZsZtNqF4_kk-TnEKCOy-cFLF6wSwz8aP14,26345
38
38
  fastworkflow/command_context_model.py,sha256=nWxLP3TR7WJr3yWCedqcdFOxo_kwae_mS3VRN2cOmK8,13437
39
39
  fastworkflow/command_directory.py,sha256=aJ6UQCwevfF11KbcQB2Qz6mQ7Kj91pZtvHmQY6JFnao,29030
40
- fastworkflow/command_executor.py,sha256=nlg-vzZI78f-9tcacrOB4_SK4vVhvszsZd6cwfDP9hc,9030
40
+ fastworkflow/command_executor.py,sha256=IEcuHEqrqc6I-Hpv451VIHw6z64zkO4o51MpXUFnPGo,7936
41
41
  fastworkflow/command_interfaces.py,sha256=PWIKlcp0G8nmYl0vkrg1o6QzJL0pxXkfrn1joqTa0eU,460
42
42
  fastworkflow/command_metadata_api.py,sha256=KtidE3PM9HYfY-nmEXZ8Y4nnaw2qn23p_gvwFVT3F8Y,39770
43
43
  fastworkflow/command_routing.py,sha256=R7194pcY0d2VHzmCu9ALacm1UvNuIRIvTn8mLp-EZIM,17219
@@ -142,7 +142,7 @@ fastworkflow/mcp_server.py,sha256=f6vqHiG-cuMpeoeRY-mvsFxApmQ28cAJFfMtqoJYy5k,88
142
142
  fastworkflow/model_pipeline_training.py,sha256=P_9wrYSfJVSYCTu8VEPkgXJ16eH58LLCK4rCRbRFAVg,46740
143
143
  fastworkflow/refine/__main__.py,sha256=bDLpPNMcdp8U4EFnMdjxx1sPDQCZuEJoBURr2KebTng,3398
144
144
  fastworkflow/run/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
145
- fastworkflow/run/__main__.py,sha256=f03MJeL9gELvxsn276AUl1Hx35sY2diliepCpV8_k38,10801
145
+ fastworkflow/run/__main__.py,sha256=BYK1i0o2zLBlpLbwXwy0FCj7W72KN7h5Tjkc0H9ZyWI,12219
146
146
  fastworkflow/run_agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
147
147
  fastworkflow/run_agent/__main__.py,sha256=japXWziVDHdLl7Hk-jzwcYkImVY4j4k9SodMhiRK3ow,11986
148
148
  fastworkflow/run_agent/agent_module.py,sha256=XbOfX2K2CwmIRT45YtoROCN4en9Ud8gMQh2kGEhqw_A,8012
@@ -166,10 +166,10 @@ fastworkflow/utils/python_utils.py,sha256=OzSf-bGve1401SHM3QXXFauBOBrlGQzPNgvvGJ
166
166
  fastworkflow/utils/signatures.py,sha256=3B3EafS5b76L4hOwDyABKMuY_bfEwmCYdK6T5DxWM1w,20968
167
167
  fastworkflow/utils/startup_progress.py,sha256=9icSdnpFAxzIq0sUliGpNaH0Efvrt5lDtGfURV5BD98,3539
168
168
  fastworkflow/workflow.py,sha256=F7kGoNQbAMwy71zT1V_KF8PbRTCY4Dz-16Zv4ApK8m8,18939
169
- fastworkflow/workflow_agent.py,sha256=ryVP3OVr-o6kEd32c9lCTYjmnJ24M7NgspfOJ9r3Q5k,13653
169
+ fastworkflow/workflow_agent.py,sha256=usSLXUJouVHQOBR2GWMGlb_uTYf9SL_WKav6nEoAxP8,15385
170
170
  fastworkflow/workflow_inheritance_model.py,sha256=Pp-qSrQISgPfPjJVUfW84pc7HLmL2evuq0UVIYR51K0,7974
171
- fastworkflow-2.15.4.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
172
- fastworkflow-2.15.4.dist-info/METADATA,sha256=8ApRYYVYgmvedFe6L2K7YB19xF9kAL8x_lU2Z67pbOE,29867
173
- fastworkflow-2.15.4.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
174
- fastworkflow-2.15.4.dist-info/entry_points.txt,sha256=m8HqoPzCyaZLAx-V5X8MJgw3Lx3GiPDlxNEZ7K-Gb-U,54
175
- fastworkflow-2.15.4.dist-info/RECORD,,
171
+ fastworkflow-2.15.5.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
172
+ fastworkflow-2.15.5.dist-info/METADATA,sha256=geBiwc_MYU7xiXrD1JI48e7zZiW2Rxpxw1J5zpFDDHs,29867
173
+ fastworkflow-2.15.5.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
174
+ fastworkflow-2.15.5.dist-info/entry_points.txt,sha256=m8HqoPzCyaZLAx-V5X8MJgw3Lx3GiPDlxNEZ7K-Gb-U,54
175
+ fastworkflow-2.15.5.dist-info/RECORD,,