falyx 0.1.22__py3-none-any.whl → 0.1.24__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.
- falyx/__main__.py +3 -8
- falyx/action.py +40 -22
- falyx/action_factory.py +16 -3
- falyx/bottom_bar.py +2 -2
- falyx/command.py +10 -7
- falyx/config.py +134 -56
- falyx/config_schema.py +76 -0
- falyx/context.py +16 -8
- falyx/debug.py +2 -1
- falyx/exceptions.py +3 -0
- falyx/execution_registry.py +61 -14
- falyx/falyx.py +108 -100
- falyx/hook_manager.py +20 -3
- falyx/hooks.py +12 -5
- falyx/http_action.py +8 -7
- falyx/init.py +83 -22
- falyx/io_action.py +34 -16
- falyx/logger.py +5 -0
- falyx/menu_action.py +8 -2
- falyx/options_manager.py +7 -3
- falyx/parsers.py +2 -2
- falyx/prompt_utils.py +31 -1
- falyx/protocols.py +2 -0
- falyx/retry.py +23 -12
- falyx/retry_utils.py +1 -0
- falyx/select_file_action.py +40 -5
- falyx/selection.py +9 -5
- falyx/selection_action.py +22 -8
- falyx/signal_action.py +2 -0
- falyx/signals.py +3 -0
- falyx/tagged_table.py +2 -1
- falyx/utils.py +11 -39
- falyx/validators.py +8 -7
- falyx/version.py +1 -1
- {falyx-0.1.22.dist-info → falyx-0.1.24.dist-info}/METADATA +1 -1
- falyx-0.1.24.dist-info/RECORD +42 -0
- falyx-0.1.22.dist-info/RECORD +0 -40
- {falyx-0.1.22.dist-info → falyx-0.1.24.dist-info}/LICENSE +0 -0
- {falyx-0.1.22.dist-info → falyx-0.1.24.dist-info}/WHEEL +0 -0
- {falyx-0.1.22.dist-info → falyx-0.1.24.dist-info}/entry_points.txt +0 -0
falyx/config_schema.py
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
FALYX_CONFIG_SCHEMA = {
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
3
|
+
"title": "Falyx CLI Config",
|
4
|
+
"type": "object",
|
5
|
+
"properties": {
|
6
|
+
"title": {"type": "string", "description": "Title shown at top of menu"},
|
7
|
+
"prompt": {
|
8
|
+
"oneOf": [
|
9
|
+
{"type": "string"},
|
10
|
+
{
|
11
|
+
"type": "array",
|
12
|
+
"items": {
|
13
|
+
"type": "array",
|
14
|
+
"prefixItems": [
|
15
|
+
{
|
16
|
+
"type": "string",
|
17
|
+
"description": "Style string (e.g., 'bold #ff0000 italic')",
|
18
|
+
},
|
19
|
+
{"type": "string", "description": "Text content"},
|
20
|
+
],
|
21
|
+
"minItems": 2,
|
22
|
+
"maxItems": 2,
|
23
|
+
},
|
24
|
+
},
|
25
|
+
]
|
26
|
+
},
|
27
|
+
"columns": {
|
28
|
+
"type": "integer",
|
29
|
+
"minimum": 1,
|
30
|
+
"description": "Number of menu columns",
|
31
|
+
},
|
32
|
+
"welcome_message": {"type": "string"},
|
33
|
+
"exit_message": {"type": "string"},
|
34
|
+
"commands": {
|
35
|
+
"type": "array",
|
36
|
+
"items": {
|
37
|
+
"type": "object",
|
38
|
+
"required": ["key", "description", "action"],
|
39
|
+
"properties": {
|
40
|
+
"key": {"type": "string", "minLength": 1},
|
41
|
+
"description": {"type": "string"},
|
42
|
+
"action": {
|
43
|
+
"type": "string",
|
44
|
+
"pattern": "^[a-zA-Z_][a-zA-Z0-9_]*(\\.[a-zA-Z_][a-zA-Z0-9_]*)+$",
|
45
|
+
"description": "Dotted import path (e.g., mymodule.task)",
|
46
|
+
},
|
47
|
+
"args": {"type": "array"},
|
48
|
+
"kwargs": {"type": "object"},
|
49
|
+
"aliases": {"type": "array", "items": {"type": "string"}},
|
50
|
+
"tags": {"type": "array", "items": {"type": "string"}},
|
51
|
+
"style": {"type": "string"},
|
52
|
+
"confirm": {"type": "boolean"},
|
53
|
+
"confirm_message": {"type": "string"},
|
54
|
+
"preview_before_confirm": {"type": "boolean"},
|
55
|
+
"spinner": {"type": "boolean"},
|
56
|
+
"spinner_message": {"type": "string"},
|
57
|
+
"spinner_type": {"type": "string"},
|
58
|
+
"spinner_style": {"type": "string"},
|
59
|
+
"logging_hooks": {"type": "boolean"},
|
60
|
+
"retry": {"type": "boolean"},
|
61
|
+
"retry_all": {"type": "boolean"},
|
62
|
+
"retry_policy": {
|
63
|
+
"type": "object",
|
64
|
+
"properties": {
|
65
|
+
"enabled": {"type": "boolean"},
|
66
|
+
"max_retries": {"type": "integer"},
|
67
|
+
"delay": {"type": "number"},
|
68
|
+
"backoff": {"type": "number"},
|
69
|
+
},
|
70
|
+
},
|
71
|
+
},
|
72
|
+
},
|
73
|
+
},
|
74
|
+
},
|
75
|
+
"required": ["commands"],
|
76
|
+
}
|
falyx/context.py
CHANGED
@@ -29,10 +29,10 @@ class ExecutionContext(BaseModel):
|
|
29
29
|
"""
|
30
30
|
Represents the runtime metadata and state for a single action execution.
|
31
31
|
|
32
|
-
The `ExecutionContext` tracks arguments, results, exceptions, timing, and
|
33
|
-
metadata for each invocation of a Falyx `BaseAction`. It provides
|
34
|
-
Falyx hook system and execution registry, enabling lifecycle
|
35
|
-
and structured logging.
|
32
|
+
The `ExecutionContext` tracks arguments, results, exceptions, timing, and
|
33
|
+
additional metadata for each invocation of a Falyx `BaseAction`. It provides
|
34
|
+
integration with the Falyx hook system and execution registry, enabling lifecycle
|
35
|
+
management, diagnostics, and structured logging.
|
36
36
|
|
37
37
|
Attributes:
|
38
38
|
name (str): The name of the action being executed.
|
@@ -47,7 +47,8 @@ class ExecutionContext(BaseModel):
|
|
47
47
|
end_wall (datetime | None): Wall-clock timestamp when execution ended.
|
48
48
|
extra (dict): Metadata for custom introspection or special use by Actions.
|
49
49
|
console (Console): Rich console instance for logging or UI output.
|
50
|
-
shared_context (SharedContext | None): Optional shared context when running in
|
50
|
+
shared_context (SharedContext | None): Optional shared context when running in
|
51
|
+
a chain or group.
|
51
52
|
|
52
53
|
Properties:
|
53
54
|
duration (float | None): The execution duration in seconds.
|
@@ -95,7 +96,11 @@ class ExecutionContext(BaseModel):
|
|
95
96
|
self.end_wall = datetime.now()
|
96
97
|
|
97
98
|
def get_shared_context(self) -> SharedContext:
|
98
|
-
|
99
|
+
if not self.shared_context:
|
100
|
+
raise ValueError(
|
101
|
+
"SharedContext is not set. This context is not part of a chain or group."
|
102
|
+
)
|
103
|
+
return self.shared_context
|
99
104
|
|
100
105
|
@property
|
101
106
|
def duration(self) -> float | None:
|
@@ -190,8 +195,10 @@ class SharedContext(BaseModel):
|
|
190
195
|
errors (list[tuple[int, Exception]]): Indexed list of errors from failed actions.
|
191
196
|
current_index (int): Index of the currently executing action (used in chains).
|
192
197
|
is_parallel (bool): Whether the context is used in parallel mode (ActionGroup).
|
193
|
-
shared_result (Any | None): Optional shared value available to all actions in
|
194
|
-
|
198
|
+
shared_result (Any | None): Optional shared value available to all actions in
|
199
|
+
parallel mode.
|
200
|
+
share (dict[str, Any]): Custom shared key-value store for user-defined
|
201
|
+
communication
|
195
202
|
between actions (e.g., flags, intermediate data, settings).
|
196
203
|
|
197
204
|
Note:
|
@@ -208,6 +215,7 @@ class SharedContext(BaseModel):
|
|
208
215
|
"""
|
209
216
|
|
210
217
|
name: str
|
218
|
+
action: Any
|
211
219
|
results: list[Any] = Field(default_factory=list)
|
212
220
|
errors: list[tuple[int, Exception]] = Field(default_factory=list)
|
213
221
|
current_index: int = -1
|
falyx/debug.py
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
# Falyx CLI Framework — (c) 2025 rtj.dev LLC — MIT Licensed
|
2
|
+
"""debug.py"""
|
2
3
|
from falyx.context import ExecutionContext
|
3
4
|
from falyx.hook_manager import HookManager, HookType
|
4
|
-
from falyx.
|
5
|
+
from falyx.logger import logger
|
5
6
|
|
6
7
|
|
7
8
|
def log_before(context: ExecutionContext):
|
falyx/exceptions.py
CHANGED
falyx/execution_registry.py
CHANGED
@@ -1,5 +1,32 @@
|
|
1
1
|
# Falyx CLI Framework — (c) 2025 rtj.dev LLC — MIT Licensed
|
2
|
-
"""
|
2
|
+
"""
|
3
|
+
execution_registry.py
|
4
|
+
|
5
|
+
This module provides the `ExecutionRegistry`, a global class for tracking and
|
6
|
+
introspecting the execution history of Falyx actions.
|
7
|
+
|
8
|
+
The registry captures `ExecutionContext` instances from all executed actions, making it
|
9
|
+
easy to debug, audit, and visualize workflow behavior over time. It supports retrieval,
|
10
|
+
filtering, clearing, and formatted summary display.
|
11
|
+
|
12
|
+
Core Features:
|
13
|
+
- Stores all action execution contexts globally (with access by name).
|
14
|
+
- Provides live execution summaries in a rich table format.
|
15
|
+
- Enables creation of a built-in Falyx Action to print history on demand.
|
16
|
+
- Integrates with Falyx's introspectable and hook-driven execution model.
|
17
|
+
|
18
|
+
Intended for:
|
19
|
+
- Debugging and diagnostics
|
20
|
+
- Post-run inspection of CLI workflows
|
21
|
+
- Interactive tools built with Falyx
|
22
|
+
|
23
|
+
Example:
|
24
|
+
from falyx.execution_registry import ExecutionRegistry as er
|
25
|
+
er.record(context)
|
26
|
+
er.summary()
|
27
|
+
"""
|
28
|
+
from __future__ import annotations
|
29
|
+
|
3
30
|
from collections import defaultdict
|
4
31
|
from datetime import datetime
|
5
32
|
from typing import Dict, List
|
@@ -9,10 +36,40 @@ from rich.console import Console
|
|
9
36
|
from rich.table import Table
|
10
37
|
|
11
38
|
from falyx.context import ExecutionContext
|
12
|
-
from falyx.
|
39
|
+
from falyx.logger import logger
|
40
|
+
from falyx.themes.colors import OneColors
|
13
41
|
|
14
42
|
|
15
43
|
class ExecutionRegistry:
|
44
|
+
"""
|
45
|
+
Global registry for recording and inspecting Falyx action executions.
|
46
|
+
|
47
|
+
This class captures every `ExecutionContext` generated by a Falyx `Action`,
|
48
|
+
`ChainedAction`, or `ActionGroup`, maintaining both full history and
|
49
|
+
name-indexed access for filtered analysis.
|
50
|
+
|
51
|
+
Methods:
|
52
|
+
- record(context): Stores an ExecutionContext, logging a summary line.
|
53
|
+
- get_all(): Returns the list of all recorded executions.
|
54
|
+
- get_by_name(name): Returns all executions with the given action name.
|
55
|
+
- get_latest(): Returns the most recent execution.
|
56
|
+
- clear(): Wipes the registry for a fresh run.
|
57
|
+
- summary(): Renders a formatted Rich table of all execution results.
|
58
|
+
|
59
|
+
Use Cases:
|
60
|
+
- Debugging chained or factory-generated workflows
|
61
|
+
- Viewing results and exceptions from multiple runs
|
62
|
+
- Embedding a diagnostic command into your CLI for user support
|
63
|
+
|
64
|
+
Note:
|
65
|
+
This registry is in-memory and not persistent. It's reset each time the process
|
66
|
+
restarts or `clear()` is called.
|
67
|
+
|
68
|
+
Example:
|
69
|
+
ExecutionRegistry.record(context)
|
70
|
+
ExecutionRegistry.summary()
|
71
|
+
"""
|
72
|
+
|
16
73
|
_store_by_name: Dict[str, List[ExecutionContext]] = defaultdict(list)
|
17
74
|
_store_all: List[ExecutionContext] = []
|
18
75
|
_console = Console(color_system="auto")
|
@@ -66,10 +123,10 @@ class ExecutionRegistry:
|
|
66
123
|
duration = f"{ctx.duration:.3f}s" if ctx.duration else "n/a"
|
67
124
|
|
68
125
|
if ctx.exception:
|
69
|
-
status = "[
|
126
|
+
status = f"[{OneColors.DARK_RED}]❌ Error"
|
70
127
|
result = repr(ctx.exception)
|
71
128
|
else:
|
72
|
-
status = "[
|
129
|
+
status = f"[{OneColors.GREEN}]✅ Success"
|
73
130
|
result = repr(ctx.result)
|
74
131
|
if len(result) > 1000:
|
75
132
|
result = f"{result[:1000]}..."
|
@@ -77,13 +134,3 @@ class ExecutionRegistry:
|
|
77
134
|
table.add_row(ctx.name, start, end, duration, status, result)
|
78
135
|
|
79
136
|
cls._console.print(table)
|
80
|
-
|
81
|
-
@classmethod
|
82
|
-
def get_history_action(cls) -> "Action":
|
83
|
-
"""Return an Action that prints the execution summary."""
|
84
|
-
from falyx.action import Action
|
85
|
-
|
86
|
-
async def show_history():
|
87
|
-
cls.summary()
|
88
|
-
|
89
|
-
return Action(name="View Execution History", action=show_history)
|