fdsx 0.2.2__tar.gz → 0.2.3__tar.gz
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.
- {fdsx-0.2.2 → fdsx-0.2.3}/PKG-INFO +27 -7
- {fdsx-0.2.2 → fdsx-0.2.3}/README.md +27 -7
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/data/skills/fdsx/SKILL.md +47 -6
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/data/skills/fdsx/references/yaml-schema.md +76 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx.egg-info/PKG-INFO +27 -7
- {fdsx-0.2.2 → fdsx-0.2.3}/.github/dependabot.yml +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/.github/workflows/publish.yml +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/.github/workflows/test.yml +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/.pre-commit-config.yaml +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/AGENTS.md +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/CLAUDE.md +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/GEMINI.md +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/LICENSE +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/MANIFEST.in +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/examples/self-improve/README.md +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/examples/self-improve/analyze.md +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/examples/self-improve/collect_data.sh +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/examples/self-improve/research.md +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/examples/self-improve/workflow.yaml +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/examples/self-improve/write_lessons.md +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/pyproject.toml +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/setup.cfg +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/__init__.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/checkpoint/__init__.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/checkpoint/manager.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/cli/__init__.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/cli/init_interactive.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/cli/main.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/core/__init__.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/core/batch.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/core/compiler/__init__.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/core/compiler/aggregation.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/core/compiler/compile.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/core/compiler/execution.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/core/compiler/helpers.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/core/compiler/map_iteration.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/core/compiler/nodes.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/core/compiler/parallel.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/core/compiler/routing.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/core/config.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/core/engine/__init__.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/core/engine/batch.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/core/engine/interrupts.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/core/engine/results.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/core/engine/resume.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/core/engine/run.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/core/engine/signals.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/core/engine/tasks_dir.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/core/engine/validate.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/core/extraction.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/core/graph_utils.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/core/hooks.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/core/init.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/core/loader.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/core/paths.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/core/profiles.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/core/selector.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/core/thread_id.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/core/variables.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/data/__init__.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/data/skills/__init__.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/display/__init__.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/display/terminal.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/examples/__init__.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/examples/workflows/__init__.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/examples/workflows/full-impl/finalize.md +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/examples/workflows/full-impl/fix.md +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/examples/workflows/full-impl/implement.md +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/examples/workflows/full-impl/plan.md +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/examples/workflows/full-impl/replan.md +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/examples/workflows/full-impl/review-code-quality.md +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/examples/workflows/full-impl/review-security.md +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/examples/workflows/full-impl/workflow.yaml +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/examples/workflows/self-improve/README.md +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/examples/workflows/self-improve/analyze.md +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/examples/workflows/self-improve/collect_data.sh +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/examples/workflows/self-improve/research.md +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/examples/workflows/self-improve/workflow.yaml +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/examples/workflows/self-improve/write_lessons.md +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/examples/workflows/simple-impl/finalize.md +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/examples/workflows/simple-impl/fix.md +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/examples/workflows/simple-impl/implement.md +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/examples/workflows/simple-impl/plan.md +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/examples/workflows/simple-impl/replan.md +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/examples/workflows/simple-impl/review-general.md +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/examples/workflows/simple-impl/workflow.yaml +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/logging/__init__.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/logging/recorder.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/logging/stream_logger.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/models/__init__.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/models/flow.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/models/init.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/models/task.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/models/validators.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/notify/__init__.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/notify/webhook.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/providers/__init__.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/providers/base.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/providers/claude.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/providers/codex.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/providers/gemini.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/providers/opencode.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/providers/system.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx/py.typed +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx.egg-info/SOURCES.txt +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx.egg-info/dependency_links.txt +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx.egg-info/entry_points.txt +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx.egg-info/requires.txt +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/src/fdsx.egg-info/top_level.txt +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/__init__.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/conftest.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/e2e/__init__.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/e2e/cli_test_utils.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/e2e/conftest.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/e2e/test_add_cli.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/e2e/test_auto_init.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/e2e/test_batch_backward_compat.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/e2e/test_batch_edge_cases.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/e2e/test_batch_error_messages.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/e2e/test_batch_full_pipeline.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/e2e/test_cli_batch_split.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/e2e/test_cli_batch_tasks.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/e2e/test_cli_flow_types.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/e2e/test_cli_map_flow.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/e2e/test_cli_signal_handling.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/e2e/test_cli_thread_id.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/e2e/test_cli_validation_and_run.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/e2e/test_cli_wait_and_resume.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/e2e/test_cli_workflow_name.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/fixtures/batch_flow.yaml +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/fixtures/checkpoint_flow.yaml +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/fixtures/choice_flow.yaml +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/fixtures/choice_flow_default.yaml +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/fixtures/claude_stream.ndjson +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/fixtures/codex_stream.jsonl +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/fixtures/extraction_flow.yaml +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/fixtures/input_flow.yaml +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/fixtures/invalid_flows/bad_next_ref.yaml +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/fixtures/invalid_flows/missing_start_at.yaml +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/fixtures/invalid_flows/mutual_exclusive.yaml +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/fixtures/json_codeblock_extraction_flow.yaml +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/fixtures/json_extraction_flow.yaml +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/fixtures/loop_flow.yaml +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/fixtures/map_basic.yaml +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/fixtures/map_empty_items.yaml +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/fixtures/map_fail_fast_false.yaml +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/fixtures/map_inside_parallel.yaml +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/fixtures/max_iterations_flow.yaml +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/fixtures/max_iterations_wait_flow.yaml +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/fixtures/parallel_min_success.yaml +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/fixtures/parallel_review.yaml +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/fixtures/profile_flow.yaml +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/fixtures/profile_parallel_flow.yaml +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/fixtures/prompt_file_test/flow.yaml +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/fixtures/prompt_file_test/prompt.txt +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/fixtures/regex_extraction_flow.yaml +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/fixtures/sample_tasks.md +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/fixtures/self_improve_flow/collect_data.sh +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/fixtures/self_improve_flow/workflow.yaml +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/fixtures/simple_flow.yaml +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/fixtures/wait_approval.yaml +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/fixtures/wait_resume_flow.yaml +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/fixtures/wait_webhook.yaml +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/fixtures/workflows_name_display/alpha.yaml +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/fixtures/workflows_name_display/beta/workflow.yaml +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/fixtures/workflows_name_display/gamma.yaml +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/integration/__init__.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/integration/test_add_single_task.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/integration/test_auto_init.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/integration/test_auto_init_cli.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/integration/test_auto_select.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/integration/test_checkpoint_resume.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/integration/test_choice_flow.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/integration/test_claude_streaming.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/integration/test_codex_stream_lifecycle.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/integration/test_codex_streaming.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/integration/test_default_tasks_dir.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/integration/test_extraction_flow.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/integration/test_gemini_provider.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/integration/test_hook_streaming_interaction.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/integration/test_hooks_integration.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/integration/test_inactivity_timeout.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/integration/test_init.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/integration/test_init_cli.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/integration/test_init_full_flow.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/integration/test_init_interactive.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/integration/test_init_templates.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/integration/test_iteration_logs.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/integration/test_large_command.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/integration/test_linear_flow.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/integration/test_lock_atomicity.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/integration/test_loop_enforcement.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/integration/test_loop_flow.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/integration/test_map_checkpoint.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/integration/test_map_flow.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/integration/test_max_iterations_flow.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/integration/test_parallel_flow.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/integration/test_profile_assignment.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/integration/test_profile_flow.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/integration/test_provider_options.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/integration/test_quiet_mode.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/integration/test_result_file.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/integration/test_resume_interrupt.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/integration/test_scaffold_gitignore.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/integration/test_scenario_flows.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/integration/test_self_improve_flow.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/integration/test_single_task_confirm.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/integration/test_skill_install.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/integration/test_split.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/integration/test_split_spinner.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/integration/test_stream_output.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/integration/test_subprocess_completion.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/integration/test_system_prompt.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/integration/test_tasks_dir.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/integration/test_tool_use_streaming.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/integration/test_universal_scaffold_trigger.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/integration/test_wait_resume.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/integration/test_workflow_persistence.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/unit/__init__.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/unit/test_aggregation.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/unit/test_backoff.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/unit/test_batch.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/unit/test_checkpoint.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/unit/test_claude_options.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/unit/test_claude_stream_parser.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/unit/test_cli_version.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/unit/test_codex_stream_parser.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/unit/test_compiler_merge.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/unit/test_config.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/unit/test_config_generation.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/unit/test_engine.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/unit/test_execution.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/unit/test_extraction.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/unit/test_format_tool_input_summary.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/unit/test_gemini_options.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/unit/test_gemini_stream.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/unit/test_gitignore.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/unit/test_graph_utils.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/unit/test_hooks.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/unit/test_loader.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/unit/test_map_model.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/unit/test_max_iterations.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/unit/test_models.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/unit/test_paths.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/unit/test_profile_fixtures.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/unit/test_profiles.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/unit/test_prompt_file.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/unit/test_provider_options.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/unit/test_provider_stdin_fallback.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/unit/test_recorder.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/unit/test_result_file.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/unit/test_resume_display.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/unit/test_selector.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/unit/test_selector_name.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/unit/test_signal_handler.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/unit/test_spinner.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/unit/test_stream_callback.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/unit/test_stream_logger.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/unit/test_stream_logger_iteration.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/unit/test_subprocess_completion.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/unit/test_subprocess_realtime_streaming.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/unit/test_subprocess_stdin.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/unit/test_task_model.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/unit/test_task_splitter_prompt.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/unit/test_terminal.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/unit/test_thread_id.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/unit/test_variables.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/unit/test_webhook.py +0 -0
- {fdsx-0.2.2 → fdsx-0.2.3}/tests/unit/test_workflow_cui.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fdsx
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.3
|
|
4
4
|
Summary: Declarative AI agent workflow execution framework
|
|
5
5
|
Author: kenfdev
|
|
6
6
|
License-Expression: MIT
|
|
@@ -50,8 +50,10 @@ fdsx enables you to define AI agent workflows in YAML, combining the durability
|
|
|
50
50
|
|
|
51
51
|
**Key features:**
|
|
52
52
|
- Declarative YAML-based workflow definition
|
|
53
|
+
- Interactive project initialization and scaffolding
|
|
53
54
|
- Stateful execution with checkpoint/resume
|
|
54
55
|
- Parallel execution with branch aggregation
|
|
56
|
+
- Map state for iterating over arrays with sub-workflows
|
|
55
57
|
- Batch task processing (in-memory and persistent)
|
|
56
58
|
- Multiple LLM provider support (Claude, Codex, Gemini, OpenCode, and system commands)
|
|
57
59
|
- Named profiles for reusable provider/model configuration
|
|
@@ -74,6 +76,14 @@ uv tool install fdsx
|
|
|
74
76
|
|
|
75
77
|
## Quick Start
|
|
76
78
|
|
|
79
|
+
Initialize a new project:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
fdsx init
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
This interactively scaffolds a `.fdsx/` directory with configuration and example workflows.
|
|
86
|
+
|
|
77
87
|
Create a simple YAML workflow file:
|
|
78
88
|
|
|
79
89
|
```yaml
|
|
@@ -286,7 +296,7 @@ states:
|
|
|
286
296
|
result_path: $.iter.step2
|
|
287
297
|
retry: 0
|
|
288
298
|
fail_fast: true # (bool, default: true) stop all iterations on first failure
|
|
289
|
-
result_path: $.map_results # (string,
|
|
299
|
+
result_path: $.map_results # (string, REQUIRED) JSONPath for the results array
|
|
290
300
|
max_iterations: 10 # (int, optional) max times this state can be re-entered
|
|
291
301
|
hooks: # (optional)
|
|
292
302
|
next: after_map # next / end — same rules as task
|
|
@@ -446,6 +456,10 @@ workflows_dir: .fdsx/workflows # (string, default: ".fdsx/workflows")
|
|
|
446
456
|
# must be relative, no ".." components
|
|
447
457
|
# where `fdsx run --tasks-dir` discovers workflows
|
|
448
458
|
|
|
459
|
+
# --- Default tasks directory ---
|
|
460
|
+
default_tasks_dir: .fdsx/tasks # (string, optional) default directory for bare `fdsx run`
|
|
461
|
+
# when no workflow, --tasks, or --tasks-dir is given
|
|
462
|
+
|
|
449
463
|
# --- Auto-workflow selection ---
|
|
450
464
|
auto_workflow: false # (bool, default: false) skip interactive confirmation UI
|
|
451
465
|
|
|
@@ -457,7 +471,7 @@ workflow_selector:
|
|
|
457
471
|
extra_instructions: | # (string, optional) appended to the selection prompt
|
|
458
472
|
Prefer simple-impl for small tasks.
|
|
459
473
|
|
|
460
|
-
# --- Task splitter: LLM used by `fdsx split` ---
|
|
474
|
+
# --- Task splitter: LLM used by `fdsx add --split` ---
|
|
461
475
|
task_splitter:
|
|
462
476
|
profile: smarty # (string, optional) profile ref — mutually exclusive with provider/model
|
|
463
477
|
# provider: claude # (string, default: "claude")
|
|
@@ -477,6 +491,8 @@ providers:
|
|
|
477
491
|
dangerously_skip_permissions: true # (bool, default: false)
|
|
478
492
|
allowed_tools: [] # (list of strings, default: []) tool allowlist
|
|
479
493
|
disallowed_tools: [] # (list of strings, default: []) tool denylist
|
|
494
|
+
system_prompt: "Custom system prompt" # (string, optional) override the default system prompt
|
|
495
|
+
append_system_prompt: "Extra instructions" # (string, optional) append to the default system prompt
|
|
480
496
|
inactivity_timeout: 600 # (int, optional) seconds before killing inactive subprocess
|
|
481
497
|
|
|
482
498
|
codex:
|
|
@@ -526,6 +542,9 @@ hooks:
|
|
|
526
542
|
|
|
527
543
|
| Command | Description |
|
|
528
544
|
|---------|-------------|
|
|
545
|
+
| `fdsx init` | Initialize a new fdsx project with interactive setup |
|
|
546
|
+
| `fdsx init --skill` | Install the /fdsx Claude Code skill only (skip scaffold) |
|
|
547
|
+
| `fdsx run` | Execute tasks from default tasks directory (`default_tasks_dir` or `.fdsx/tasks/`) |
|
|
529
548
|
| `fdsx run <workflow.yaml>` | Execute a workflow |
|
|
530
549
|
| `fdsx run <workflow.yaml> --input key=value` | Pass input variables |
|
|
531
550
|
| `fdsx run <workflow.yaml> --tasks tasks.yaml` | In-memory batch execution |
|
|
@@ -538,8 +557,9 @@ hooks:
|
|
|
538
557
|
| `fdsx validate <workflow.yaml>` | Validate YAML syntax |
|
|
539
558
|
| `fdsx list` | List recent runs |
|
|
540
559
|
| `fdsx list --base-dir <dir>` | List runs from custom base directory |
|
|
541
|
-
| `fdsx
|
|
542
|
-
| `fdsx
|
|
560
|
+
| `fdsx add <task_file>` | Add a task file to the batch execution queue (single task) |
|
|
561
|
+
| `fdsx add <task_file> --split` | Split a task file into individual task files |
|
|
562
|
+
| `fdsx add <task_file> --split --force` | Clear existing tasks directory before splitting |
|
|
543
563
|
|
|
544
564
|
## Example Workflow
|
|
545
565
|
|
|
@@ -610,8 +630,8 @@ states:
|
|
|
610
630
|
|
|
611
631
|
Run this example:
|
|
612
632
|
```bash
|
|
613
|
-
#
|
|
614
|
-
fdsx
|
|
633
|
+
# Initialize the project (creates .fdsx/ with config and example workflows):
|
|
634
|
+
fdsx init
|
|
615
635
|
|
|
616
636
|
# Then run the scaffolded example workflow:
|
|
617
637
|
fdsx run .fdsx/workflows/plan-implement-review/workflow.yaml --input task="Build a web calculator"
|
|
@@ -10,8 +10,10 @@ fdsx enables you to define AI agent workflows in YAML, combining the durability
|
|
|
10
10
|
|
|
11
11
|
**Key features:**
|
|
12
12
|
- Declarative YAML-based workflow definition
|
|
13
|
+
- Interactive project initialization and scaffolding
|
|
13
14
|
- Stateful execution with checkpoint/resume
|
|
14
15
|
- Parallel execution with branch aggregation
|
|
16
|
+
- Map state for iterating over arrays with sub-workflows
|
|
15
17
|
- Batch task processing (in-memory and persistent)
|
|
16
18
|
- Multiple LLM provider support (Claude, Codex, Gemini, OpenCode, and system commands)
|
|
17
19
|
- Named profiles for reusable provider/model configuration
|
|
@@ -34,6 +36,14 @@ uv tool install fdsx
|
|
|
34
36
|
|
|
35
37
|
## Quick Start
|
|
36
38
|
|
|
39
|
+
Initialize a new project:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
fdsx init
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
This interactively scaffolds a `.fdsx/` directory with configuration and example workflows.
|
|
46
|
+
|
|
37
47
|
Create a simple YAML workflow file:
|
|
38
48
|
|
|
39
49
|
```yaml
|
|
@@ -246,7 +256,7 @@ states:
|
|
|
246
256
|
result_path: $.iter.step2
|
|
247
257
|
retry: 0
|
|
248
258
|
fail_fast: true # (bool, default: true) stop all iterations on first failure
|
|
249
|
-
result_path: $.map_results # (string,
|
|
259
|
+
result_path: $.map_results # (string, REQUIRED) JSONPath for the results array
|
|
250
260
|
max_iterations: 10 # (int, optional) max times this state can be re-entered
|
|
251
261
|
hooks: # (optional)
|
|
252
262
|
next: after_map # next / end — same rules as task
|
|
@@ -406,6 +416,10 @@ workflows_dir: .fdsx/workflows # (string, default: ".fdsx/workflows")
|
|
|
406
416
|
# must be relative, no ".." components
|
|
407
417
|
# where `fdsx run --tasks-dir` discovers workflows
|
|
408
418
|
|
|
419
|
+
# --- Default tasks directory ---
|
|
420
|
+
default_tasks_dir: .fdsx/tasks # (string, optional) default directory for bare `fdsx run`
|
|
421
|
+
# when no workflow, --tasks, or --tasks-dir is given
|
|
422
|
+
|
|
409
423
|
# --- Auto-workflow selection ---
|
|
410
424
|
auto_workflow: false # (bool, default: false) skip interactive confirmation UI
|
|
411
425
|
|
|
@@ -417,7 +431,7 @@ workflow_selector:
|
|
|
417
431
|
extra_instructions: | # (string, optional) appended to the selection prompt
|
|
418
432
|
Prefer simple-impl for small tasks.
|
|
419
433
|
|
|
420
|
-
# --- Task splitter: LLM used by `fdsx split` ---
|
|
434
|
+
# --- Task splitter: LLM used by `fdsx add --split` ---
|
|
421
435
|
task_splitter:
|
|
422
436
|
profile: smarty # (string, optional) profile ref — mutually exclusive with provider/model
|
|
423
437
|
# provider: claude # (string, default: "claude")
|
|
@@ -437,6 +451,8 @@ providers:
|
|
|
437
451
|
dangerously_skip_permissions: true # (bool, default: false)
|
|
438
452
|
allowed_tools: [] # (list of strings, default: []) tool allowlist
|
|
439
453
|
disallowed_tools: [] # (list of strings, default: []) tool denylist
|
|
454
|
+
system_prompt: "Custom system prompt" # (string, optional) override the default system prompt
|
|
455
|
+
append_system_prompt: "Extra instructions" # (string, optional) append to the default system prompt
|
|
440
456
|
inactivity_timeout: 600 # (int, optional) seconds before killing inactive subprocess
|
|
441
457
|
|
|
442
458
|
codex:
|
|
@@ -486,6 +502,9 @@ hooks:
|
|
|
486
502
|
|
|
487
503
|
| Command | Description |
|
|
488
504
|
|---------|-------------|
|
|
505
|
+
| `fdsx init` | Initialize a new fdsx project with interactive setup |
|
|
506
|
+
| `fdsx init --skill` | Install the /fdsx Claude Code skill only (skip scaffold) |
|
|
507
|
+
| `fdsx run` | Execute tasks from default tasks directory (`default_tasks_dir` or `.fdsx/tasks/`) |
|
|
489
508
|
| `fdsx run <workflow.yaml>` | Execute a workflow |
|
|
490
509
|
| `fdsx run <workflow.yaml> --input key=value` | Pass input variables |
|
|
491
510
|
| `fdsx run <workflow.yaml> --tasks tasks.yaml` | In-memory batch execution |
|
|
@@ -498,8 +517,9 @@ hooks:
|
|
|
498
517
|
| `fdsx validate <workflow.yaml>` | Validate YAML syntax |
|
|
499
518
|
| `fdsx list` | List recent runs |
|
|
500
519
|
| `fdsx list --base-dir <dir>` | List runs from custom base directory |
|
|
501
|
-
| `fdsx
|
|
502
|
-
| `fdsx
|
|
520
|
+
| `fdsx add <task_file>` | Add a task file to the batch execution queue (single task) |
|
|
521
|
+
| `fdsx add <task_file> --split` | Split a task file into individual task files |
|
|
522
|
+
| `fdsx add <task_file> --split --force` | Clear existing tasks directory before splitting |
|
|
503
523
|
|
|
504
524
|
## Example Workflow
|
|
505
525
|
|
|
@@ -570,8 +590,8 @@ states:
|
|
|
570
590
|
|
|
571
591
|
Run this example:
|
|
572
592
|
```bash
|
|
573
|
-
#
|
|
574
|
-
fdsx
|
|
593
|
+
# Initialize the project (creates .fdsx/ with config and example workflows):
|
|
594
|
+
fdsx init
|
|
575
595
|
|
|
576
596
|
# Then run the scaffolded example workflow:
|
|
577
597
|
fdsx run .fdsx/workflows/plan-implement-review/workflow.yaml --input task="Build a web calculator"
|
|
@@ -592,4 +612,4 @@ fdsx list
|
|
|
592
612
|
|
|
593
613
|
## License
|
|
594
614
|
|
|
595
|
-
MIT License.
|
|
615
|
+
MIT License.
|
|
@@ -4,10 +4,11 @@ description: >
|
|
|
4
4
|
Expert guide for authoring, validating, and running fdsx declarative AI agent
|
|
5
5
|
workflow YAML files. Use when writing fdsx workflows, editing workflow YAML,
|
|
6
6
|
configuring fdsx providers (claude, codex, opencode, gemini), setting up
|
|
7
|
-
profiles, adding hooks, using choice/parallel/loop/wait/pass states, running
|
|
7
|
+
profiles, adding hooks, using choice/parallel/loop/wait/pass/map states, running
|
|
8
8
|
fdsx CLI commands, debugging workflow validation errors, or asking about fdsx
|
|
9
9
|
YAML schema. Also triggers on: "fdsx", "workflow YAML", "declarative agent
|
|
10
|
-
workflow", "multi-step AI pipeline", "provider options", "checkpoint resume"
|
|
10
|
+
workflow", "multi-step AI pipeline", "provider options", "checkpoint resume",
|
|
11
|
+
"map state", "iterator".
|
|
11
12
|
---
|
|
12
13
|
|
|
13
14
|
# fdsx Workflow Authoring Guide
|
|
@@ -56,6 +57,7 @@ Read `references/yaml-schema.md` for the complete field-by-field schema referenc
|
|
|
56
57
|
| `parallel` | Execute multiple branches concurrently | `branches`, `result_path`, `result_file`, `min_success` |
|
|
57
58
|
| `pass` | Data transformation / aggregation | `parameters`, `aggregate` |
|
|
58
59
|
| `wait` | Human input via terminal prompt | `mode: prompt`, `message`, `choices`, `result_path` |
|
|
60
|
+
| `map` | Iterate over an array, execute sub-workflow per item | `items_path`, `iterator`, `result_path`, `fail_fast` |
|
|
59
61
|
|
|
60
62
|
Every state except `choice` supports `next` (go to state) or `end: true` (terminate flow). These are mutually exclusive.
|
|
61
63
|
|
|
@@ -97,7 +99,7 @@ states:
|
|
|
97
99
|
|
|
98
100
|
`profile` and explicit `provider`/`model` are mutually exclusive (XOR). Profiles can also be defined in `.fdsx/config.yaml` and are merged (workflow-level overrides config-level).
|
|
99
101
|
|
|
100
|
-
Profile shorthand is supported on task states, parallel branches, and extract fallback configurations.
|
|
102
|
+
Profile shorthand is supported on task states, parallel branches, and extract fallback configurations. Note: profile shorthand is **not** supported on map iterator task states.
|
|
101
103
|
|
|
102
104
|
## Variable Substitution
|
|
103
105
|
|
|
@@ -131,17 +133,24 @@ extract:
|
|
|
131
133
|
## CLI Commands
|
|
132
134
|
|
|
133
135
|
```
|
|
134
|
-
fdsx run <workflow.yaml> [--input KEY=VALUE] [--tasks <file>] [--tasks-dir <dir>] [--thread-id <id>] [--quiet] [--auto-workflow] [--confirm-workflow]
|
|
136
|
+
fdsx run [<workflow.yaml>] [--input KEY=VALUE] [--tasks <file>] [--tasks-dir <dir>] [--thread-id <id>] [--quiet] [--auto-workflow] [--confirm-workflow]
|
|
135
137
|
fdsx validate <workflow.yaml>
|
|
136
138
|
fdsx resume --thread-id <id> [--base-dir <path>]
|
|
137
139
|
fdsx list [--base-dir <path>]
|
|
138
|
-
fdsx
|
|
140
|
+
fdsx add <task-file> [--split] [--force]
|
|
141
|
+
fdsx init [--skill]
|
|
139
142
|
fdsx --version
|
|
140
143
|
fdsx --ci | --interactive # global flags (mutually exclusive)
|
|
141
144
|
```
|
|
142
145
|
|
|
143
146
|
`--auto-workflow` and `--confirm-workflow` are mutually exclusive. `--auto-workflow` skips interactive workflow confirmation; `--confirm-workflow` forces the confirmation UI.
|
|
144
147
|
|
|
148
|
+
When `fdsx run` is invoked with no workflow, no `--tasks-dir`, no `--tasks`, and no `--input`, it falls back to the `default_tasks_dir` config value (default: `.fdsx/tasks/`) and runs in tasks-dir mode.
|
|
149
|
+
|
|
150
|
+
`fdsx add <task-file>` adds a task file to the batch execution queue. Use `--split` to invoke the LLM task splitter to break the file into multiple task files in `.fdsx/tasks/`. Use `--force` to clear existing tasks before writing.
|
|
151
|
+
|
|
152
|
+
`fdsx init` initializes a new fdsx project with interactive provider and template selection. Use `--skill` to install only the Claude Code skill without scaffolding `.fdsx/`.
|
|
153
|
+
|
|
145
154
|
## Hooks
|
|
146
155
|
|
|
147
156
|
Shell commands that run before/after state or flow execution:
|
|
@@ -169,6 +178,7 @@ Hook data files are written to `.fdsx/runs/<thread-id>/hooks/<state-name>/input.
|
|
|
169
178
|
```yaml
|
|
170
179
|
auto_workflow: false # skip workflow confirmation UI (default: false)
|
|
171
180
|
workflows_dir: .fdsx/workflows # directory for workflow discovery
|
|
181
|
+
default_tasks_dir: .fdsx/tasks/ # default tasks directory for no-arg fdsx run
|
|
172
182
|
workflow_selector:
|
|
173
183
|
provider: claude # LLM for auto-selecting workflows
|
|
174
184
|
model: claude-sonnet-4-6
|
|
@@ -192,6 +202,36 @@ Use `parallel` → `pass` (with `aggregate`) → `choice` to fan out reviews, ag
|
|
|
192
202
|
**Human gate:**
|
|
193
203
|
Use `wait` state with `mode: prompt` to pause for user input, then route with `choice`.
|
|
194
204
|
|
|
205
|
+
**Map over items (e.g., process each file):**
|
|
206
|
+
Use a preceding state to produce an array, then `map` to iterate over it with a sub-workflow per item:
|
|
207
|
+
|
|
208
|
+
```yaml
|
|
209
|
+
states:
|
|
210
|
+
collect:
|
|
211
|
+
type: task
|
|
212
|
+
provider: system
|
|
213
|
+
command: "echo '[{\"path\":\"a.py\"},{\"path\":\"b.py\"}]'"
|
|
214
|
+
result_path: $.files
|
|
215
|
+
next: process_each
|
|
216
|
+
|
|
217
|
+
process_each:
|
|
218
|
+
type: map
|
|
219
|
+
items_path: $.files
|
|
220
|
+
iterator:
|
|
221
|
+
states:
|
|
222
|
+
- type: task
|
|
223
|
+
name: review
|
|
224
|
+
provider: claude
|
|
225
|
+
model: claude-sonnet-4-6
|
|
226
|
+
prompt_template: "Review file: {item.path}"
|
|
227
|
+
result_path: $.review
|
|
228
|
+
result_path: $.reviews
|
|
229
|
+
fail_fast: true
|
|
230
|
+
end: true
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
Inside iterator states, `{item}` refers to the current array element. Use `{item.field}` for nested access.
|
|
234
|
+
|
|
195
235
|
## Validation Rules
|
|
196
236
|
|
|
197
237
|
- `start_at` must reference an existing state name
|
|
@@ -200,4 +240,5 @@ Use `wait` state with `mode: prompt` to pause for user input, then route with `c
|
|
|
200
240
|
- `prompt_template` and `prompt_file` are mutually exclusive
|
|
201
241
|
- `next` and `end` are mutually exclusive
|
|
202
242
|
- `result_file` must be a top-level `$.varname` path (no nesting)
|
|
203
|
-
- Extract `result_path` must not use reserved keys: `output`, `exit_code`, `error`
|
|
243
|
+
- Extract `result_path` must not use reserved keys: `output`, `exit_code`, `error`
|
|
244
|
+
- Map iterator states must all have `type: task` and unique `name` fields
|
|
@@ -10,6 +10,9 @@ Complete field-by-field reference for fdsx workflow YAML files, derived from the
|
|
|
10
10
|
- [ParallelState](#parallelstate)
|
|
11
11
|
- [PassState](#passstate)
|
|
12
12
|
- [WaitState](#waitstate)
|
|
13
|
+
- [MapState](#mapstate)
|
|
14
|
+
- [IteratorDef](#iteratordef)
|
|
15
|
+
- [IteratorTaskState](#iteratortaskstate)
|
|
13
16
|
- [Branch (parallel)](#branch)
|
|
14
17
|
- [ExtractRule](#extractrule)
|
|
15
18
|
- [ChoiceRule](#choicerule)
|
|
@@ -35,6 +38,8 @@ hooks?: HookConfig # optional — flow-level hooks
|
|
|
35
38
|
profiles?: {name: {k: v}} # optional — raw provider/model/extras dicts
|
|
36
39
|
```
|
|
37
40
|
|
|
41
|
+
**State** is a discriminated union on the `type` field: `TaskState | ChoiceState | ParallelState | PassState | WaitState | MapState`.
|
|
42
|
+
|
|
38
43
|
**Profiles at workflow level** are raw YAML dicts (`{provider, model, ...extras}`), not validated `ProfileConfig` objects. Profile resolution happens pre-validation: `profile` references in tasks/branches are expanded into `provider`/`model`/`provider_options` fields before Pydantic validation runs. Workflow-level profiles override config-level profiles (full replacement per name, not deep merge).
|
|
39
44
|
|
|
40
45
|
**Validation:**
|
|
@@ -148,6 +153,77 @@ notify:
|
|
|
148
153
|
|
|
149
154
|
---
|
|
150
155
|
|
|
156
|
+
## MapState
|
|
157
|
+
|
|
158
|
+
```yaml
|
|
159
|
+
type: "map" # literal discriminator
|
|
160
|
+
items_path: string # required — JSONPath to input array
|
|
161
|
+
iterator: IteratorDef # required — sub-workflow to execute for each item
|
|
162
|
+
result_path: string # required — JSONPath for results array
|
|
163
|
+
fail_fast?: bool # default: true — stop on first failure
|
|
164
|
+
max_iterations?: int # optional — >=1, max times this state can be entered
|
|
165
|
+
hooks?: HookConfig # optional — per-state hooks
|
|
166
|
+
next?: string # XOR with end — target state
|
|
167
|
+
end?: bool # XOR with next — terminate flow
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
**Variable context inside iterator:** Each iterator state receives the current array element as `{item}`. References like `{item.field}` access nested fields of the current element. Variables from preceding states in the outer flow are also available.
|
|
171
|
+
|
|
172
|
+
**Validation:**
|
|
173
|
+
- `next` and `end` are mutually exclusive
|
|
174
|
+
- `items_path` must reference a variable set by a preceding state
|
|
175
|
+
- Iterator states must all have `type: "task"` (no nested choice/parallel/pass/wait/map)
|
|
176
|
+
- Iterator state names must be unique within the iterator
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## IteratorDef
|
|
181
|
+
|
|
182
|
+
Used inside `MapState.iterator`:
|
|
183
|
+
|
|
184
|
+
```yaml
|
|
185
|
+
iterator:
|
|
186
|
+
states: [IteratorTaskState] # required — min 1 item, ordered list of task states
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
**Validation:**
|
|
190
|
+
- All states must have `type: "task"` (non-task types are rejected)
|
|
191
|
+
- State names must be unique within the iterator
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
## IteratorTaskState
|
|
196
|
+
|
|
197
|
+
Used inside `IteratorDef.states`:
|
|
198
|
+
|
|
199
|
+
```yaml
|
|
200
|
+
type: "task" # literal discriminator (only "task" allowed)
|
|
201
|
+
name: string # required — state name within the iterator
|
|
202
|
+
provider: string # required — claude|codex|opencode|gemini|system
|
|
203
|
+
model?: string # required for LLM providers, forbidden for system
|
|
204
|
+
prompt_template?: string # XOR with prompt_file; required for LLM providers
|
|
205
|
+
prompt_file?: string # XOR with prompt_template; relative path
|
|
206
|
+
command?: string # required for system, forbidden for LLM providers
|
|
207
|
+
result_path: string # required — JSONPath for result
|
|
208
|
+
result_file?: string # optional — top-level $.varname only (no nesting)
|
|
209
|
+
extract?: ExtractRule # optional — output extraction
|
|
210
|
+
retry?: int # default: 3
|
|
211
|
+
timeout_seconds?: int # optional — per-state timeout override
|
|
212
|
+
provider_options?: {k: v} # optional — per-task provider option overrides
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
**Differences from TaskState:** Has a required `name` field. Does not support `max_iterations`, `hooks`, `next`, or `end` (iteration order is determined by list position).
|
|
216
|
+
|
|
217
|
+
**Note:** Profile shorthand (`profile: <name>`) is not currently supported on iterator task states. Use explicit `provider`/`model` fields.
|
|
218
|
+
|
|
219
|
+
**Validation:**
|
|
220
|
+
- `prompt_template` and `prompt_file` are mutually exclusive
|
|
221
|
+
- `result_path` and `extract.result_path` must not overlap
|
|
222
|
+
- `result_file` must match `$.varname` (no dots or brackets after `$.`)
|
|
223
|
+
- Same provider field validation rules as TaskState
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
151
227
|
## Branch
|
|
152
228
|
|
|
153
229
|
Used inside `ParallelState.branches`:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fdsx
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.3
|
|
4
4
|
Summary: Declarative AI agent workflow execution framework
|
|
5
5
|
Author: kenfdev
|
|
6
6
|
License-Expression: MIT
|
|
@@ -50,8 +50,10 @@ fdsx enables you to define AI agent workflows in YAML, combining the durability
|
|
|
50
50
|
|
|
51
51
|
**Key features:**
|
|
52
52
|
- Declarative YAML-based workflow definition
|
|
53
|
+
- Interactive project initialization and scaffolding
|
|
53
54
|
- Stateful execution with checkpoint/resume
|
|
54
55
|
- Parallel execution with branch aggregation
|
|
56
|
+
- Map state for iterating over arrays with sub-workflows
|
|
55
57
|
- Batch task processing (in-memory and persistent)
|
|
56
58
|
- Multiple LLM provider support (Claude, Codex, Gemini, OpenCode, and system commands)
|
|
57
59
|
- Named profiles for reusable provider/model configuration
|
|
@@ -74,6 +76,14 @@ uv tool install fdsx
|
|
|
74
76
|
|
|
75
77
|
## Quick Start
|
|
76
78
|
|
|
79
|
+
Initialize a new project:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
fdsx init
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
This interactively scaffolds a `.fdsx/` directory with configuration and example workflows.
|
|
86
|
+
|
|
77
87
|
Create a simple YAML workflow file:
|
|
78
88
|
|
|
79
89
|
```yaml
|
|
@@ -286,7 +296,7 @@ states:
|
|
|
286
296
|
result_path: $.iter.step2
|
|
287
297
|
retry: 0
|
|
288
298
|
fail_fast: true # (bool, default: true) stop all iterations on first failure
|
|
289
|
-
result_path: $.map_results # (string,
|
|
299
|
+
result_path: $.map_results # (string, REQUIRED) JSONPath for the results array
|
|
290
300
|
max_iterations: 10 # (int, optional) max times this state can be re-entered
|
|
291
301
|
hooks: # (optional)
|
|
292
302
|
next: after_map # next / end — same rules as task
|
|
@@ -446,6 +456,10 @@ workflows_dir: .fdsx/workflows # (string, default: ".fdsx/workflows")
|
|
|
446
456
|
# must be relative, no ".." components
|
|
447
457
|
# where `fdsx run --tasks-dir` discovers workflows
|
|
448
458
|
|
|
459
|
+
# --- Default tasks directory ---
|
|
460
|
+
default_tasks_dir: .fdsx/tasks # (string, optional) default directory for bare `fdsx run`
|
|
461
|
+
# when no workflow, --tasks, or --tasks-dir is given
|
|
462
|
+
|
|
449
463
|
# --- Auto-workflow selection ---
|
|
450
464
|
auto_workflow: false # (bool, default: false) skip interactive confirmation UI
|
|
451
465
|
|
|
@@ -457,7 +471,7 @@ workflow_selector:
|
|
|
457
471
|
extra_instructions: | # (string, optional) appended to the selection prompt
|
|
458
472
|
Prefer simple-impl for small tasks.
|
|
459
473
|
|
|
460
|
-
# --- Task splitter: LLM used by `fdsx split` ---
|
|
474
|
+
# --- Task splitter: LLM used by `fdsx add --split` ---
|
|
461
475
|
task_splitter:
|
|
462
476
|
profile: smarty # (string, optional) profile ref — mutually exclusive with provider/model
|
|
463
477
|
# provider: claude # (string, default: "claude")
|
|
@@ -477,6 +491,8 @@ providers:
|
|
|
477
491
|
dangerously_skip_permissions: true # (bool, default: false)
|
|
478
492
|
allowed_tools: [] # (list of strings, default: []) tool allowlist
|
|
479
493
|
disallowed_tools: [] # (list of strings, default: []) tool denylist
|
|
494
|
+
system_prompt: "Custom system prompt" # (string, optional) override the default system prompt
|
|
495
|
+
append_system_prompt: "Extra instructions" # (string, optional) append to the default system prompt
|
|
480
496
|
inactivity_timeout: 600 # (int, optional) seconds before killing inactive subprocess
|
|
481
497
|
|
|
482
498
|
codex:
|
|
@@ -526,6 +542,9 @@ hooks:
|
|
|
526
542
|
|
|
527
543
|
| Command | Description |
|
|
528
544
|
|---------|-------------|
|
|
545
|
+
| `fdsx init` | Initialize a new fdsx project with interactive setup |
|
|
546
|
+
| `fdsx init --skill` | Install the /fdsx Claude Code skill only (skip scaffold) |
|
|
547
|
+
| `fdsx run` | Execute tasks from default tasks directory (`default_tasks_dir` or `.fdsx/tasks/`) |
|
|
529
548
|
| `fdsx run <workflow.yaml>` | Execute a workflow |
|
|
530
549
|
| `fdsx run <workflow.yaml> --input key=value` | Pass input variables |
|
|
531
550
|
| `fdsx run <workflow.yaml> --tasks tasks.yaml` | In-memory batch execution |
|
|
@@ -538,8 +557,9 @@ hooks:
|
|
|
538
557
|
| `fdsx validate <workflow.yaml>` | Validate YAML syntax |
|
|
539
558
|
| `fdsx list` | List recent runs |
|
|
540
559
|
| `fdsx list --base-dir <dir>` | List runs from custom base directory |
|
|
541
|
-
| `fdsx
|
|
542
|
-
| `fdsx
|
|
560
|
+
| `fdsx add <task_file>` | Add a task file to the batch execution queue (single task) |
|
|
561
|
+
| `fdsx add <task_file> --split` | Split a task file into individual task files |
|
|
562
|
+
| `fdsx add <task_file> --split --force` | Clear existing tasks directory before splitting |
|
|
543
563
|
|
|
544
564
|
## Example Workflow
|
|
545
565
|
|
|
@@ -610,8 +630,8 @@ states:
|
|
|
610
630
|
|
|
611
631
|
Run this example:
|
|
612
632
|
```bash
|
|
613
|
-
#
|
|
614
|
-
fdsx
|
|
633
|
+
# Initialize the project (creates .fdsx/ with config and example workflows):
|
|
634
|
+
fdsx init
|
|
615
635
|
|
|
616
636
|
# Then run the scaffolded example workflow:
|
|
617
637
|
fdsx run .fdsx/workflows/plan-implement-review/workflow.yaml --input task="Build a web calculator"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|