fips-agents-cli 0.8.2__tar.gz → 0.10.0__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.
Files changed (74) hide show
  1. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/CLAUDE.md +6 -1
  2. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/PKG-INFO +74 -33
  3. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/README.md +70 -30
  4. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/pyproject.toml +7 -3
  5. fips_agents_cli-0.10.0/src/fips_agents_cli/commands/add.py +265 -0
  6. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/src/fips_agents_cli/commands/create.py +8 -0
  7. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/src/fips_agents_cli/commands/patch.py +50 -27
  8. fips_agents_cli-0.10.0/src/fips_agents_cli/tools/modality.py +285 -0
  9. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/src/fips_agents_cli/tools/patching.py +156 -26
  10. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/src/fips_agents_cli/tools/project.py +61 -5
  11. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/src/fips_agents_cli/tools/validation.py +41 -2
  12. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/src/fips_agents_cli/version.py +1 -1
  13. fips_agents_cli-0.10.0/tests/fixtures/agent_project/.template-info +13 -0
  14. fips_agents_cli-0.10.0/tests/fixtures/agent_project/agent.yaml +40 -0
  15. fips_agents_cli-0.10.0/tests/fixtures/agent_project/chart/values.yaml +32 -0
  16. fips_agents_cli-0.10.0/tests/fixtures/agent_project/pyproject.toml +17 -0
  17. fips_agents_cli-0.10.0/tests/fixtures/agent_project/src/agent.py +1 -0
  18. fips_agents_cli-0.10.0/tests/fixtures/agent_project/tools/.gitkeep +0 -0
  19. fips_agents_cli-0.10.0/tests/test_modality.py +448 -0
  20. fips_agents_cli-0.10.0/tests/test_patch.py +295 -0
  21. fips_agents_cli-0.8.2/src/fips_agents_cli/commands/add.py +0 -211
  22. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/.claude/commands/create-release.md +0 -0
  23. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/.claude/docs-state.json +0 -0
  24. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/.github/CODEOWNERS +0 -0
  25. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/.github/agents/README.md +0 -0
  26. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/.github/agents/create-release.agent.md +0 -0
  27. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/.github/workflows/test.yml +0 -0
  28. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/.github/workflows/workflow.yaml +0 -0
  29. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/.gitignore +0 -0
  30. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/LICENSE +0 -0
  31. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/RELEASE_CHECKLIST.md +0 -0
  32. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/docs/PUBLISHING.md +0 -0
  33. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/docs/QUICK_START_PUBLISHING.md +0 -0
  34. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/docs/README.md +0 -0
  35. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/llms.txt +0 -0
  36. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/planning/AGENT_FRAMEWORK_PLAN.md +0 -0
  37. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/planning/GENERATOR_IMPLEMENTATION_PLAN.md +0 -0
  38. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/planning/IMPLEMENTATION_SUMMARY.md +0 -0
  39. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/planning/MVP-PLAN.md +0 -0
  40. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/planning/PLAN.md +0 -0
  41. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/planning/PROMPT_ISSUE.md +0 -0
  42. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/planning/agent-registry-roadmap.md +0 -0
  43. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/planning/agent-template-gaps.md +0 -0
  44. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/planning/composable-agent-capabilities.md +0 -0
  45. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/research/BAML_RESEARCH_REPORT.md +0 -0
  46. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/research/Ignite-CLI-Architecture-Analysis.md +0 -0
  47. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/retrospectives/2026-04-06_issue-triage-v0.3.0/RETRO.md +0 -0
  48. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/retrospectives/2026-04-10_full-stack-integration/RETRO.md +0 -0
  49. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/scripts/README.md +0 -0
  50. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/scripts/release.sh +0 -0
  51. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/src/fips_agents_cli/__init__.py +0 -0
  52. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/src/fips_agents_cli/__main__.py +0 -0
  53. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/src/fips_agents_cli/cli.py +0 -0
  54. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/src/fips_agents_cli/commands/__init__.py +0 -0
  55. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/src/fips_agents_cli/commands/generate.py +0 -0
  56. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/src/fips_agents_cli/commands/model_car.py +0 -0
  57. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/src/fips_agents_cli/commands/vendor.py +0 -0
  58. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/src/fips_agents_cli/tools/__init__.py +0 -0
  59. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/src/fips_agents_cli/tools/filesystem.py +0 -0
  60. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/src/fips_agents_cli/tools/generators.py +0 -0
  61. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/src/fips_agents_cli/tools/git.py +0 -0
  62. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/src/fips_agents_cli/tools/github.py +0 -0
  63. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/tests/__init__.py +0 -0
  64. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/tests/conftest.py +0 -0
  65. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/tests/fixtures/middleware_template/component.py.j2 +0 -0
  66. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/tests/fixtures/middleware_template/test.py.j2 +0 -0
  67. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/tests/test_create.py +0 -0
  68. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/tests/test_filesystem.py +0 -0
  69. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/tests/test_generate.py +0 -0
  70. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/tests/test_generators.py +0 -0
  71. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/tests/test_github.py +0 -0
  72. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/tests/test_model_car.py +0 -0
  73. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/tests/test_project.py +0 -0
  74. {fips_agents_cli-0.8.2 → fips_agents_cli-0.10.0}/tests/test_validation.py +0 -0
@@ -6,7 +6,12 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
6
6
 
7
7
  **fips-agents-cli** is a Python-based CLI tool for scaffolding FIPS-compliant AI agent projects. It scaffolds MCP (Model Context Protocol) servers and AI agent projects from production-ready templates, customizes them for new projects, and prepares them for immediate development use.
8
8
 
9
- **Current Status:** Scaffolding commands implemented: `create mcp-server`, `create agent`, `create gateway`, `create ui`, `create sandbox`, `create model-car`. Post-scaffolding commands: `generate` (tool, resource, prompt, middleware), `patch` (check, generators, core, docs, build, all), `add` (code-executor), `vendor`. Note: `create workflow` exists in code but is not yet working.
9
+ **Current Status:** Scaffolding commands implemented: `create mcp-server`, `create agent`, `create gateway`, `create ui`, `create sandbox`, `create model-car`. Post-scaffolding commands: `generate` (tool, resource, prompt, middleware), `patch` (check, all + type-specific category subcommands — see below), `add` (code-executor, files), `vendor`. Note: `create workflow` exists in code but is not yet working.
10
+
11
+ The `patch` command is type-aware via `template.type` in `.template-info`:
12
+ - **MCP server** projects expose `patch generators | core | docs | build`.
13
+ - **Agent / workflow** projects expose `patch chart | docs | build | claude`.
14
+ Running an MCP-only subcommand inside an agent project (or vice versa) exits with a clear "available categories" error. `patch check` and `patch all` work for any supported type.
10
15
 
11
16
  ## Development Commands
12
17
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fips-agents-cli
3
- Version: 0.8.2
3
+ Version: 0.10.0
4
4
  Summary: CLI tool for creating and managing FIPS-compliant AI agent projects
5
5
  Project-URL: Homepage, https://github.com/fips-agents/fips-agents-cli
6
6
  Project-URL: Repository, https://github.com/fips-agents/fips-agents-cli
@@ -23,12 +23,13 @@ Requires-Dist: click>=8.1.0
23
23
  Requires-Dist: gitpython>=3.1.0
24
24
  Requires-Dist: jinja2>=3.1.2
25
25
  Requires-Dist: rich>=13.0.0
26
+ Requires-Dist: ruamel-yaml<0.19,>=0.18
26
27
  Requires-Dist: tomlkit>=0.12.0
27
28
  Provides-Extra: dev
28
- Requires-Dist: black>=23.0.0; extra == 'dev'
29
+ Requires-Dist: black<27,>=26; extra == 'dev'
29
30
  Requires-Dist: pytest-cov>=4.1.0; extra == 'dev'
30
31
  Requires-Dist: pytest>=7.4.0; extra == 'dev'
31
- Requires-Dist: ruff>=0.1.0; extra == 'dev'
32
+ Requires-Dist: ruff<0.12,>=0.11; extra == 'dev'
32
33
  Description-Content-Type: text/markdown
33
34
 
34
35
  # FIPS Agents CLI
@@ -557,7 +558,9 @@ When using `--params` with `generate tool` or `generate prompt`, provide a JSON
557
558
 
558
559
  ### Patch Commands
559
560
 
560
- The `patch` command group updates files in existing MCP server projects from the upstream template repository without overwriting your custom code. It shows interactive diffs for files that may contain customizations.
561
+ The `patch` command group updates files in existing projects from the upstream template repository without overwriting your custom code. It shows interactive diffs for files that may contain customizations.
562
+
563
+ Supported project types: **MCP server**, **agent**, **workflow**. The available category subcommands depend on the project type — `patch` reads `template.type` from `.template-info` and surfaces a clear error if you run a category that doesn't apply (e.g. `patch generators` inside an agent project).
561
564
 
562
565
  Run these commands from within your project directory.
563
566
 
@@ -567,57 +570,68 @@ Run these commands from within your project directory.
567
570
  fips-agents patch check
568
571
  ```
569
572
 
570
- Check for available template updates. Shows what files have changed in the template since your project was created, organized by category.
573
+ Check for available template updates. Shows what files have changed in the template since your project was created, organized by category. Works for any supported project type.
571
574
 
572
- #### `patch generators`
575
+ #### `patch all`
573
576
 
574
577
  ```bash
575
- fips-agents patch generators [--dry-run]
578
+ fips-agents patch all [--dry-run] [--skip-confirmation]
576
579
  ```
577
580
 
578
- Update code generator templates (Jinja2 templates in `.fips-agents-cli/generators/`).
581
+ Update every category that applies to the current project type. Prompts for confirmation before starting unless `--skip-confirmation` is passed.
579
582
 
580
- #### `patch core`
583
+ #### MCP server categories
581
584
 
582
- ```bash
583
- fips-agents patch core [--dry-run]
584
- ```
585
+ | Subcommand | Patches |
586
+ |----------------------|--------------------------------------------------------------------------|
587
+ | `patch generators` | Jinja2 templates in `.fips-agents-cli/generators/` |
588
+ | `patch core` | Core infrastructure (loaders, server bootstrap) |
589
+ | `patch docs` | Documentation files and examples |
590
+ | `patch build` | Build and deployment files (Makefile, Containerfile) |
585
591
 
586
- Update core infrastructure files (loaders, server bootstrap).
592
+ #### Agent / workflow categories
587
593
 
588
- #### `patch docs`
594
+ | Subcommand | Patches |
595
+ |----------------|-------------------------------------------------------------------------------|
596
+ | `patch chart` | Helm chart templates (`chart/templates/**`, `chart/Chart.yaml`) |
597
+ | `patch docs` | `CLAUDE.md`, `AGENTS.md`, `docs/**` |
598
+ | `patch build` | `Makefile`, `Containerfile`, `deploy.sh`, `redeploy.sh` |
599
+ | `patch claude` | Claude Code slash commands shipped with the template (`.claude/commands/**`) |
589
600
 
590
- ```bash
591
- fips-agents patch docs [--dry-run]
592
- ```
601
+ User-customized files are never patched: for MCP this means `src/tools/`, `src/resources/`, `src/prompts/`, `src/middleware/`, `pyproject.toml`, etc. For agent/workflow it means `src/agent.py`, `agent.yaml`, `chart/values.yaml`, `src/fipsagents/**` (managed by `fips-agents vendor`), and `pyproject.toml`.
602
+
603
+ All patch subcommands (except `check`) accept `--dry-run` to preview changes without modifying files.
593
604
 
594
- Update documentation files and examples.
605
+ ---
595
606
 
596
- #### `patch build`
607
+ ### Add Commands
597
608
 
598
- ```bash
599
- fips-agents patch build [--dry-run]
600
- ```
609
+ The `add` command group wires optional capabilities into existing agent projects created with `fips-agents create agent`.
601
610
 
602
- Update build and deployment files (Makefile, Containerfile).
611
+ **Run these commands from within your agent project directory.** The CLI locates the project root by looking for `.template-info` (or `agent.yaml` for legacy projects).
603
612
 
604
- #### `patch all`
613
+ #### `add files`
605
614
 
606
615
  ```bash
607
- fips-agents patch all [--dry-run] [--skip-confirmation]
616
+ fips-agents add files
608
617
  ```
609
618
 
610
- Update all patchable file categories at once. Prompts for confirmation before starting unless `--skip-confirmation` is passed.
619
+ Enables file upload + attachment support. Flips `server.files.enabled` in `agent.yaml` and `files.enabled` in `chart/values.yaml`. The agent template already ships the rest of the files surface (storage backends, optional S3 bytes backend, ClamAV virus-scanner sidecar, Docling PDF/text extraction, pgvector chunking) — this command only wires up the toggles.
611
620
 
612
- All patch subcommands (except `check`) accept `--dry-run` to preview changes without modifying files.
613
-
614
- ---
621
+ **What it does:**
615
622
 
616
- ### Add Commands
623
+ 1. Sets `server.files.enabled: true` in `agent.yaml`
624
+ 2. Sets `files.enabled: true` in `chart/values.yaml`
625
+ 3. Prints next steps for installing the `[files]` extra, choosing a backend (`sqlite` / `postgres`), enabling ClamAV, and enabling persistence
617
626
 
618
- The `add` command group wires optional capabilities into existing agent projects created with `fips-agents create agent`.
627
+ **Example:**
619
628
 
620
- **Run these commands from within your agent project directory.** The CLI locates the project root by looking for `agent.yaml`.
629
+ ```bash
630
+ cd my-research-agent
631
+ fips-agents add files
632
+ pip install -e '.[files]'
633
+ export FILES_BACKEND=sqlite
634
+ ```
621
635
 
622
636
  #### `add code-executor`
623
637
 
@@ -822,7 +836,7 @@ fips-agents-cli/
822
836
  │ ├── cli.py # Main CLI application
823
837
  │ ├── version.py # Version information
824
838
  │ ├── commands/ # CLI command implementations
825
- │ │ ├── add.py # add code-executor (wire capabilities)
839
+ │ │ ├── add.py # add files / code-executor (wire capabilities)
826
840
  │ │ ├── create.py # create mcp-server, agent, gateway, ui
827
841
  │ │ ├── generate.py # generate tool/resource/prompt/middleware
828
842
  │ │ ├── model_car.py # create model-car
@@ -946,6 +960,33 @@ MIT License - see LICENSE file for details
946
960
 
947
961
  ## Changelog
948
962
 
963
+ ### Version 0.10.0
964
+
965
+ - Feature: New `tools/modality.py` helper exposing `ModalitySpec` + `apply_modality()` — declarative API for composable `add` subcommands that toggle agent.yaml / chart/values.yaml fields, drop in source files, and register pyproject.toml extras. Uses ruamel.yaml round-trip to preserve comments and `${VAR:-default}` substitutions; tomlkit for TOML edits. Idempotent, with a `precondition` hook for cross-modality dependency checks (#37)
966
+ - Feature: New `fips-agents add files` command enables file upload + attachment support in existing agent projects. Flips `server.files.enabled` (agent.yaml) and `files.enabled` (chart/values.yaml); the agent template already ships the rest of the surface — storage backends, optional S3 bytes backend, ClamAV virus-scanner sidecar, Docling text extraction, pgvector chunking — so the command only owns the toggles (#19, #38)
967
+ - Improvement: `add code-executor` refactored onto the new `ModalitySpec` helper. Brittle string-replace on `enabled: false` is replaced with structured ruamel.yaml round-trip; behavior preserved
968
+ - Improvement: `_find_agent_project_root()` promoted from `commands/add.py` to `tools/project.py` as public `find_agent_project_root()`. Now recognizes both `.template-info` (`template.type=="agent"`) and legacy `agent.yaml` presence
969
+ - Chore: Pin dev tools to `black>=26,<27` and `ruff>=0.11,<0.12` so local environments cannot silently drift past CI's formatter/linter major versions (#36)
970
+ - Chore: New runtime dependency `ruamel.yaml>=0.18,<0.19` (used by the modality helper for comment-preserving YAML edits)
971
+ - Chore: Descope governance issues #23 (cost tracking), #24 (HITL approval), #25 (compliance audit logging) — OGX (the new name for LlamaStack) handles these well; fips-agents-cli will not duplicate that surface
972
+ - Tests: 29 new tests in `tests/test_modality.py` covering yaml toggles (top-level + nested), idempotency, missing-section warnings, source-file drops, pyproject extra add/merge, preconditions, and end-to-end runs of `add code-executor` and `add files`. New committed `tests/fixtures/agent_project/` provides an offline structural snapshot of the agent-template layout (precedent: `tests/fixtures/middleware_template/`)
973
+
974
+ ### Version 0.9.1
975
+
976
+ - Chore: Realign `tests/` formatting with black 26.3.1 to match CI (v0.9.0's release pipeline failed because local black 24.x produced different output than CI's 26.x; no functional change)
977
+
978
+ ### Version 0.9.0
979
+
980
+ - Feature: `fips-agents patch` now supports agent and workflow projects in addition to MCP servers (#12)
981
+ - Feature: New `patch chart` and `patch claude` subcommands for agent/workflow projects (#15)
982
+ - Feature: `.template-info` now records `template.type` and (for monorepo templates) `template.subdir` so post-scaffolding commands can route by project type (#13)
983
+ - Feature: New `find_fips_project_root()` walks up to `.template-info`, replacing the MCP-only fastmcp-dependency probe in patch commands (#14)
984
+ - Improvement: `_clone_template_for_patch()` resolves the monorepo subdir during patching, so glob/compare runs against `templates/agent-loop/` instead of the monorepo root (#16)
985
+ - Improvement: Running an MCP-only subcommand inside an agent project (or vice versa) now exits with a clear "available categories" error
986
+ - Improvement: `patch all` enumerates the project's actual category set instead of assuming MCP layout
987
+ - Backwards compat: Projects scaffolded before `template.type` existed default to `mcp-server`; no migration required
988
+ - Tests: 20 new tests in `tests/test_patch.py` covering the type-aware patch flow end-to-end against a fake-scaffolded agent project
989
+
949
990
  ### Version 0.8.2
950
991
 
951
992
  - Test: New `TestGenerateMiddlewareRealTemplate` integration test renders the real v3.x middleware Jinja2 template against each `--hook-type` and the no-flag case, with templates committed under `tests/fixtures/middleware_template/` so the suite runs offline (#3)
@@ -524,7 +524,9 @@ When using `--params` with `generate tool` or `generate prompt`, provide a JSON
524
524
 
525
525
  ### Patch Commands
526
526
 
527
- The `patch` command group updates files in existing MCP server projects from the upstream template repository without overwriting your custom code. It shows interactive diffs for files that may contain customizations.
527
+ The `patch` command group updates files in existing projects from the upstream template repository without overwriting your custom code. It shows interactive diffs for files that may contain customizations.
528
+
529
+ Supported project types: **MCP server**, **agent**, **workflow**. The available category subcommands depend on the project type — `patch` reads `template.type` from `.template-info` and surfaces a clear error if you run a category that doesn't apply (e.g. `patch generators` inside an agent project).
528
530
 
529
531
  Run these commands from within your project directory.
530
532
 
@@ -534,57 +536,68 @@ Run these commands from within your project directory.
534
536
  fips-agents patch check
535
537
  ```
536
538
 
537
- Check for available template updates. Shows what files have changed in the template since your project was created, organized by category.
539
+ Check for available template updates. Shows what files have changed in the template since your project was created, organized by category. Works for any supported project type.
538
540
 
539
- #### `patch generators`
541
+ #### `patch all`
540
542
 
541
543
  ```bash
542
- fips-agents patch generators [--dry-run]
544
+ fips-agents patch all [--dry-run] [--skip-confirmation]
543
545
  ```
544
546
 
545
- Update code generator templates (Jinja2 templates in `.fips-agents-cli/generators/`).
547
+ Update every category that applies to the current project type. Prompts for confirmation before starting unless `--skip-confirmation` is passed.
546
548
 
547
- #### `patch core`
549
+ #### MCP server categories
548
550
 
549
- ```bash
550
- fips-agents patch core [--dry-run]
551
- ```
551
+ | Subcommand | Patches |
552
+ |----------------------|--------------------------------------------------------------------------|
553
+ | `patch generators` | Jinja2 templates in `.fips-agents-cli/generators/` |
554
+ | `patch core` | Core infrastructure (loaders, server bootstrap) |
555
+ | `patch docs` | Documentation files and examples |
556
+ | `patch build` | Build and deployment files (Makefile, Containerfile) |
552
557
 
553
- Update core infrastructure files (loaders, server bootstrap).
558
+ #### Agent / workflow categories
554
559
 
555
- #### `patch docs`
560
+ | Subcommand | Patches |
561
+ |----------------|-------------------------------------------------------------------------------|
562
+ | `patch chart` | Helm chart templates (`chart/templates/**`, `chart/Chart.yaml`) |
563
+ | `patch docs` | `CLAUDE.md`, `AGENTS.md`, `docs/**` |
564
+ | `patch build` | `Makefile`, `Containerfile`, `deploy.sh`, `redeploy.sh` |
565
+ | `patch claude` | Claude Code slash commands shipped with the template (`.claude/commands/**`) |
556
566
 
557
- ```bash
558
- fips-agents patch docs [--dry-run]
559
- ```
567
+ User-customized files are never patched: for MCP this means `src/tools/`, `src/resources/`, `src/prompts/`, `src/middleware/`, `pyproject.toml`, etc. For agent/workflow it means `src/agent.py`, `agent.yaml`, `chart/values.yaml`, `src/fipsagents/**` (managed by `fips-agents vendor`), and `pyproject.toml`.
568
+
569
+ All patch subcommands (except `check`) accept `--dry-run` to preview changes without modifying files.
560
570
 
561
- Update documentation files and examples.
571
+ ---
562
572
 
563
- #### `patch build`
573
+ ### Add Commands
564
574
 
565
- ```bash
566
- fips-agents patch build [--dry-run]
567
- ```
575
+ The `add` command group wires optional capabilities into existing agent projects created with `fips-agents create agent`.
568
576
 
569
- Update build and deployment files (Makefile, Containerfile).
577
+ **Run these commands from within your agent project directory.** The CLI locates the project root by looking for `.template-info` (or `agent.yaml` for legacy projects).
570
578
 
571
- #### `patch all`
579
+ #### `add files`
572
580
 
573
581
  ```bash
574
- fips-agents patch all [--dry-run] [--skip-confirmation]
582
+ fips-agents add files
575
583
  ```
576
584
 
577
- Update all patchable file categories at once. Prompts for confirmation before starting unless `--skip-confirmation` is passed.
585
+ Enables file upload + attachment support. Flips `server.files.enabled` in `agent.yaml` and `files.enabled` in `chart/values.yaml`. The agent template already ships the rest of the files surface (storage backends, optional S3 bytes backend, ClamAV virus-scanner sidecar, Docling PDF/text extraction, pgvector chunking) — this command only wires up the toggles.
578
586
 
579
- All patch subcommands (except `check`) accept `--dry-run` to preview changes without modifying files.
580
-
581
- ---
587
+ **What it does:**
582
588
 
583
- ### Add Commands
589
+ 1. Sets `server.files.enabled: true` in `agent.yaml`
590
+ 2. Sets `files.enabled: true` in `chart/values.yaml`
591
+ 3. Prints next steps for installing the `[files]` extra, choosing a backend (`sqlite` / `postgres`), enabling ClamAV, and enabling persistence
584
592
 
585
- The `add` command group wires optional capabilities into existing agent projects created with `fips-agents create agent`.
593
+ **Example:**
586
594
 
587
- **Run these commands from within your agent project directory.** The CLI locates the project root by looking for `agent.yaml`.
595
+ ```bash
596
+ cd my-research-agent
597
+ fips-agents add files
598
+ pip install -e '.[files]'
599
+ export FILES_BACKEND=sqlite
600
+ ```
588
601
 
589
602
  #### `add code-executor`
590
603
 
@@ -789,7 +802,7 @@ fips-agents-cli/
789
802
  │ ├── cli.py # Main CLI application
790
803
  │ ├── version.py # Version information
791
804
  │ ├── commands/ # CLI command implementations
792
- │ │ ├── add.py # add code-executor (wire capabilities)
805
+ │ │ ├── add.py # add files / code-executor (wire capabilities)
793
806
  │ │ ├── create.py # create mcp-server, agent, gateway, ui
794
807
  │ │ ├── generate.py # generate tool/resource/prompt/middleware
795
808
  │ │ ├── model_car.py # create model-car
@@ -913,6 +926,33 @@ MIT License - see LICENSE file for details
913
926
 
914
927
  ## Changelog
915
928
 
929
+ ### Version 0.10.0
930
+
931
+ - Feature: New `tools/modality.py` helper exposing `ModalitySpec` + `apply_modality()` — declarative API for composable `add` subcommands that toggle agent.yaml / chart/values.yaml fields, drop in source files, and register pyproject.toml extras. Uses ruamel.yaml round-trip to preserve comments and `${VAR:-default}` substitutions; tomlkit for TOML edits. Idempotent, with a `precondition` hook for cross-modality dependency checks (#37)
932
+ - Feature: New `fips-agents add files` command enables file upload + attachment support in existing agent projects. Flips `server.files.enabled` (agent.yaml) and `files.enabled` (chart/values.yaml); the agent template already ships the rest of the surface — storage backends, optional S3 bytes backend, ClamAV virus-scanner sidecar, Docling text extraction, pgvector chunking — so the command only owns the toggles (#19, #38)
933
+ - Improvement: `add code-executor` refactored onto the new `ModalitySpec` helper. Brittle string-replace on `enabled: false` is replaced with structured ruamel.yaml round-trip; behavior preserved
934
+ - Improvement: `_find_agent_project_root()` promoted from `commands/add.py` to `tools/project.py` as public `find_agent_project_root()`. Now recognizes both `.template-info` (`template.type=="agent"`) and legacy `agent.yaml` presence
935
+ - Chore: Pin dev tools to `black>=26,<27` and `ruff>=0.11,<0.12` so local environments cannot silently drift past CI's formatter/linter major versions (#36)
936
+ - Chore: New runtime dependency `ruamel.yaml>=0.18,<0.19` (used by the modality helper for comment-preserving YAML edits)
937
+ - Chore: Descope governance issues #23 (cost tracking), #24 (HITL approval), #25 (compliance audit logging) — OGX (the new name for LlamaStack) handles these well; fips-agents-cli will not duplicate that surface
938
+ - Tests: 29 new tests in `tests/test_modality.py` covering yaml toggles (top-level + nested), idempotency, missing-section warnings, source-file drops, pyproject extra add/merge, preconditions, and end-to-end runs of `add code-executor` and `add files`. New committed `tests/fixtures/agent_project/` provides an offline structural snapshot of the agent-template layout (precedent: `tests/fixtures/middleware_template/`)
939
+
940
+ ### Version 0.9.1
941
+
942
+ - Chore: Realign `tests/` formatting with black 26.3.1 to match CI (v0.9.0's release pipeline failed because local black 24.x produced different output than CI's 26.x; no functional change)
943
+
944
+ ### Version 0.9.0
945
+
946
+ - Feature: `fips-agents patch` now supports agent and workflow projects in addition to MCP servers (#12)
947
+ - Feature: New `patch chart` and `patch claude` subcommands for agent/workflow projects (#15)
948
+ - Feature: `.template-info` now records `template.type` and (for monorepo templates) `template.subdir` so post-scaffolding commands can route by project type (#13)
949
+ - Feature: New `find_fips_project_root()` walks up to `.template-info`, replacing the MCP-only fastmcp-dependency probe in patch commands (#14)
950
+ - Improvement: `_clone_template_for_patch()` resolves the monorepo subdir during patching, so glob/compare runs against `templates/agent-loop/` instead of the monorepo root (#16)
951
+ - Improvement: Running an MCP-only subcommand inside an agent project (or vice versa) now exits with a clear "available categories" error
952
+ - Improvement: `patch all` enumerates the project's actual category set instead of assuming MCP layout
953
+ - Backwards compat: Projects scaffolded before `template.type` existed default to `mcp-server`; no migration required
954
+ - Tests: 20 new tests in `tests/test_patch.py` covering the type-aware patch flow end-to-end against a fake-scaffolded agent project
955
+
916
956
  ### Version 0.8.2
917
957
 
918
958
  - Test: New `TestGenerateMiddlewareRealTemplate` integration test renders the real v3.x middleware Jinja2 template against each `--hook-type` and the no-flag case, with templates committed under `tests/fixtures/middleware_template/` so the suite runs offline (#3)
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "fips-agents-cli"
7
- version = "0.8.2"
7
+ version = "0.10.0"
8
8
  description = "CLI tool for creating and managing FIPS-compliant AI agent projects"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -30,14 +30,18 @@ dependencies = [
30
30
  "gitpython>=3.1.0",
31
31
  "tomlkit>=0.12.0",
32
32
  "jinja2>=3.1.2",
33
+ "ruamel.yaml>=0.18,<0.19",
33
34
  ]
34
35
 
35
36
  [project.optional-dependencies]
36
37
  dev = [
37
38
  "pytest>=7.4.0",
38
39
  "pytest-cov>=4.1.0",
39
- "black>=23.0.0",
40
- "ruff>=0.1.0",
40
+ # Pin formatter/linter major versions so local environments cannot drift
41
+ # from CI silently. v0.9.0's release was broken by black 24.x vs CI's 26.x
42
+ # producing different output; v0.9.1 was a same-day patch to recover.
43
+ "black>=26,<27",
44
+ "ruff>=0.11,<0.12",
41
45
  ]
42
46
 
43
47
  [project.scripts]
@@ -0,0 +1,265 @@
1
+ """Add command group for wiring capabilities into existing agent projects."""
2
+
3
+ import sys
4
+ from pathlib import Path
5
+
6
+ import click
7
+ from rich.console import Console
8
+ from rich.panel import Panel
9
+
10
+ from fips_agents_cli.tools.modality import (
11
+ ModalityError,
12
+ ModalityResult,
13
+ ModalitySpec,
14
+ SourceFile,
15
+ apply_modality,
16
+ )
17
+ from fips_agents_cli.tools.project import find_agent_project_root
18
+
19
+ console = Console()
20
+
21
+
22
+ # The code_executor tool source, embedded directly to avoid network dependencies.
23
+ # Source: agent-template/examples/code-sandbox-agent/tools/code_executor.py
24
+ CODE_EXECUTOR_TOOL_SOURCE = '''\
25
+ """Code execution tool — sends Python code to the sandbox sidecar."""
26
+
27
+ import os
28
+
29
+ import httpx
30
+
31
+ from fipsagents.baseagent.tools import tool
32
+
33
+ SANDBOX_URL = os.environ.get("SANDBOX_URL", "http://localhost:8000")
34
+
35
+
36
+ @tool(
37
+ description="Execute Python code in an isolated sandbox and return the output. "
38
+ "Use this for any computation, math, data processing, or logic that "
39
+ "benefits from exact results. The code runs in a restricted environment "
40
+ "with access to: math, statistics, itertools, functools, re, datetime, "
41
+ "collections, json, csv, string, textwrap, decimal, fractions, random, "
42
+ "operator, typing. Use print() to produce output.",
43
+ visibility="llm_only",
44
+ )
45
+ async def code_executor(code: str, timeout: float = 10.0) -> str:
46
+ """Execute Python code in the sandbox sidecar.
47
+
48
+ Args:
49
+ code: Python source code to execute. Must use print() for output.
50
+ timeout: Maximum execution time in seconds (1-30).
51
+ """
52
+ timeout = max(1.0, min(timeout, 30.0))
53
+
54
+ async with httpx.AsyncClient(timeout=timeout + 5) as client:
55
+ try:
56
+ resp = await client.post(
57
+ f"{SANDBOX_URL}/execute",
58
+ json={"code": code, "timeout": timeout},
59
+ )
60
+ except httpx.ConnectError:
61
+ return (
62
+ "ERROR: Cannot connect to sandbox sidecar at "
63
+ f"{SANDBOX_URL}. Is it running?"
64
+ )
65
+ except httpx.TimeoutException:
66
+ return "ERROR: Request to sandbox timed out."
67
+
68
+ data = resp.json()
69
+
70
+ if resp.status_code == 400:
71
+ if "violations" in data:
72
+ violations = "\\n".join(f" - {v}" for v in data["violations"])
73
+ return f"CODE BLOCKED by sandbox guardrails:\\n{violations}"
74
+ return f"ERROR: {data.get(\'error\', \'Unknown error\')}"
75
+
76
+ stdout = data.get("stdout", "").strip()
77
+ stderr = data.get("stderr", "").strip()
78
+ exit_code = data.get("exit_code", -1)
79
+ timed_out = data.get("timed_out", False)
80
+
81
+ if timed_out:
82
+ return f"TIMEOUT: Code exceeded {timeout}s limit.\\nPartial output:\\n{stdout}"
83
+
84
+ parts = []
85
+ if stdout:
86
+ parts.append(stdout)
87
+ if stderr:
88
+ parts.append(f"STDERR:\\n{stderr}")
89
+ if exit_code != 0:
90
+ parts.append(f"(exit code {exit_code})")
91
+
92
+ return "\\n".join(parts) if parts else "(no output — did you forget print()?)"
93
+ '''
94
+
95
+
96
+ CODE_EXECUTOR_NEXT_STEPS = (
97
+ "1. Build or deploy the sandbox sidecar:",
98
+ " [dim]fips-agents create sandbox my-sandbox[/dim]",
99
+ " or use the pre-built image from fips-agents/code-sandbox",
100
+ "",
101
+ "2. Configure the sandbox URL for your agent:",
102
+ "",
103
+ " [bold]Sidecar mode[/bold] (same pod, default):",
104
+ " The tool defaults to http://localhost:8000",
105
+ " No extra config needed if sandbox runs as a sidecar container.",
106
+ "",
107
+ " [bold]Remote service mode[/bold] (separate deployment):",
108
+ " Set the SANDBOX_URL environment variable:",
109
+ " [dim]export SANDBOX_URL=http://sandbox-service:8000[/dim]",
110
+ "",
111
+ "3. The agent will auto-discover tools/code_executor.py.",
112
+ " Use it in your agent's step() by calling:",
113
+ ' [dim]await self.use_tool("code_executor", code="print(1+1)")[/dim]',
114
+ )
115
+
116
+
117
+ CODE_EXECUTOR_SPEC = ModalitySpec(
118
+ name="code-executor",
119
+ description="Sandbox code execution",
120
+ chart_values_enable="sandbox.enabled",
121
+ source_files=(
122
+ SourceFile(
123
+ relative_path="tools/code_executor.py",
124
+ content=CODE_EXECUTOR_TOOL_SOURCE,
125
+ ),
126
+ ),
127
+ next_steps=CODE_EXECUTOR_NEXT_STEPS,
128
+ )
129
+
130
+
131
+ FILES_NEXT_STEPS = (
132
+ r"1. Install the \[files] extra (pulls in docling + python-magic):",
133
+ r" [dim]pip install -e '.\[files]'[/dim]",
134
+ "",
135
+ "2. Choose a persistence backend by setting FILES_BACKEND:",
136
+ " [bold]sqlite[/bold] (dev / single-replica)",
137
+ " [dim]export FILES_BACKEND=sqlite[/dim]",
138
+ " [bold]postgres[/bold] (production / multi-replica)",
139
+ " [dim]export FILES_BACKEND=postgres[/dim]",
140
+ " [dim]export DATABASE_URL=postgresql://...[/dim]",
141
+ "",
142
+ "3. (Optional) For multi-replica deployments use the S3 bytes backend:",
143
+ " [dim]chart/values.yaml: files.bytesBackend.type=s3 + bucket/region/credentials[/dim]",
144
+ "",
145
+ "4. (Optional) Enable the ClamAV virus-scanner sidecar:",
146
+ " [dim]chart/values.yaml: files.virusScanner.enabled=true[/dim]",
147
+ "",
148
+ "5. (Optional) Persist uploaded bytes across pod restarts (PVC):",
149
+ " [dim]chart/values.yaml: files.persistence.enabled=true[/dim]",
150
+ "",
151
+ "6. Upload a file and reference it in chat completions:",
152
+ " [dim]curl -F file=@doc.pdf $AGENT_URL/v1/files[/dim]",
153
+ " The response carries a file_id; pass it on subsequent",
154
+ " /v1/chat/completions requests via the file_ids field.",
155
+ )
156
+
157
+
158
+ FILES_SPEC = ModalitySpec(
159
+ name="files",
160
+ description="File upload and attachment support",
161
+ agent_yaml_enable="server.files.enabled",
162
+ chart_values_enable="files.enabled",
163
+ next_steps=FILES_NEXT_STEPS,
164
+ )
165
+
166
+
167
+ def _print_modality_result(spec: ModalitySpec, result: ModalityResult) -> None:
168
+ """Render the per-action lines + the success panel for an applied spec."""
169
+ for action in result.actions:
170
+ console.print(f"[green]+[/green] {action}")
171
+ for skipped in result.skipped:
172
+ console.print(f"[dim]{skipped}[/dim]")
173
+ for warning in result.warnings:
174
+ console.print(f"[yellow]Warning:[/yellow] {warning}")
175
+
176
+ body_lines = [f"[bold green]{spec.description} added.[/bold green]", ""]
177
+ if spec.next_steps:
178
+ body_lines.append("[bold cyan]Next Steps:[/bold cyan]")
179
+ body_lines.append("")
180
+ body_lines.extend(f" {line}" for line in spec.next_steps)
181
+
182
+ console.print(
183
+ Panel(
184
+ "\n".join(body_lines),
185
+ border_style="green",
186
+ padding=(1, 2),
187
+ )
188
+ )
189
+
190
+
191
+ def _resolve_agent_project_or_exit() -> Path:
192
+ project_root = find_agent_project_root()
193
+ if project_root is None:
194
+ console.print(
195
+ "[red]Error:[/red] Not in an agent project directory.\n"
196
+ "Could not find agent.yaml or .template-info in this directory or any parent.\n\n"
197
+ "[yellow]Hint:[/yellow] Run this command from an agent project "
198
+ "created with [dim]fips-agents create agent[/dim]."
199
+ )
200
+ sys.exit(1)
201
+ return project_root
202
+
203
+
204
+ @click.group()
205
+ def add():
206
+ """Add capabilities to an existing agent project."""
207
+ pass
208
+
209
+
210
+ def _run_modality(spec: ModalitySpec) -> None:
211
+ """Shared implementation for every `add <modality>` subcommand."""
212
+ try:
213
+ project_root = _resolve_agent_project_or_exit()
214
+ console.print(f"[green]Found project root:[/green] {project_root}")
215
+
216
+ try:
217
+ result = apply_modality(project_root, spec)
218
+ except ModalityError as e:
219
+ console.print(f"\n[red]Error:[/red] {e}")
220
+ sys.exit(1)
221
+
222
+ _print_modality_result(spec, result)
223
+
224
+ except KeyboardInterrupt:
225
+ console.print("\n[yellow]Operation cancelled.[/yellow]")
226
+ sys.exit(130)
227
+ except Exception as e:
228
+ console.print(f"\n[red]Error:[/red] {e}")
229
+ sys.exit(1)
230
+
231
+
232
+ @add.command("code-executor")
233
+ def code_executor_cmd():
234
+ """Wire sandbox code execution into the current agent project.
235
+
236
+ Adds the code_executor tool to tools/ and enables the sandbox sidecar
237
+ in chart/values.yaml. Run from your agent project root directory.
238
+
239
+ Example:
240
+
241
+ cd my-research-agent
242
+
243
+ fips-agents add code-executor
244
+ """
245
+ _run_modality(CODE_EXECUTOR_SPEC)
246
+
247
+
248
+ @add.command("files")
249
+ def files_cmd():
250
+ """Enable file upload + attachment support in the current agent project.
251
+
252
+ Flips ``server.files.enabled`` in agent.yaml and ``files.enabled`` in
253
+ chart/values.yaml. The agent template already ships the rest of the
254
+ files surface (storage backends, S3, ClamAV sidecar, Docling parsing,
255
+ pgvector chunking) — this command only wires up the toggles. Follow
256
+ the printed next-steps to install the ``[files]`` extra and choose a
257
+ persistence backend.
258
+
259
+ Example:
260
+
261
+ cd my-research-agent
262
+
263
+ fips-agents add files
264
+ """
265
+ _run_modality(FILES_SPEC)