requirements-agent 0.0.1__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.
- requirements_agent-0.0.1/PKG-INFO +166 -0
- requirements_agent-0.0.1/README.md +143 -0
- requirements_agent-0.0.1/pyproject.toml +41 -0
- requirements_agent-0.0.1/setup.cfg +4 -0
- requirements_agent-0.0.1/src/requirements_agent/__init__.py +3 -0
- requirements_agent-0.0.1/src/requirements_agent/agent.py +143 -0
- requirements_agent-0.0.1/src/requirements_agent/cli.py +435 -0
- requirements_agent-0.0.1/src/requirements_agent/config.py +360 -0
- requirements_agent-0.0.1/src/requirements_agent/context/__init__.py +3 -0
- requirements_agent-0.0.1/src/requirements_agent/context/aggregate.py +136 -0
- requirements_agent-0.0.1/src/requirements_agent/context/base.py +14 -0
- requirements_agent-0.0.1/src/requirements_agent/context/folder.py +107 -0
- requirements_agent-0.0.1/src/requirements_agent/context/mcp.py +22 -0
- requirements_agent-0.0.1/src/requirements_agent/context/rag.py +22 -0
- requirements_agent-0.0.1/src/requirements_agent/export/__init__.py +3 -0
- requirements_agent-0.0.1/src/requirements_agent/export/markdown.py +53 -0
- requirements_agent-0.0.1/src/requirements_agent/export/pdf.py +82 -0
- requirements_agent-0.0.1/src/requirements_agent/init_cmd.py +191 -0
- requirements_agent-0.0.1/src/requirements_agent/llm/__init__.py +3 -0
- requirements_agent-0.0.1/src/requirements_agent/llm/base.py +47 -0
- requirements_agent-0.0.1/src/requirements_agent/llm/mock.py +116 -0
- requirements_agent-0.0.1/src/requirements_agent/llm/providers.py +127 -0
- requirements_agent-0.0.1/src/requirements_agent/llm/router.py +19 -0
- requirements_agent-0.0.1/src/requirements_agent/models.py +62 -0
- requirements_agent-0.0.1/src/requirements_agent/packs/bmad-core-spec/agents/analyst.md +29 -0
- requirements_agent-0.0.1/src/requirements_agent/packs/bmad-core-spec/agents/architect.md +28 -0
- requirements_agent-0.0.1/src/requirements_agent/packs/bmad-core-spec/agents/bmad-orchestrator.md +26 -0
- requirements_agent-0.0.1/src/requirements_agent/packs/bmad-core-spec/agents/dev.md +27 -0
- requirements_agent-0.0.1/src/requirements_agent/packs/bmad-core-spec/agents/pm.md +27 -0
- requirements_agent-0.0.1/src/requirements_agent/packs/bmad-core-spec/agents/po.md +27 -0
- requirements_agent-0.0.1/src/requirements_agent/packs/bmad-core-spec/agents/qa.md +28 -0
- requirements_agent-0.0.1/src/requirements_agent/packs/bmad-core-spec/agents/sm.md +26 -0
- requirements_agent-0.0.1/src/requirements_agent/packs/bmad-core-spec/checklists/spec-circuit-analyst.md +8 -0
- requirements_agent-0.0.1/src/requirements_agent/packs/bmad-core-spec/checklists/spec-circuit-architect.md +11 -0
- requirements_agent-0.0.1/src/requirements_agent/packs/bmad-core-spec/checklists/spec-circuit-dev.md +11 -0
- requirements_agent-0.0.1/src/requirements_agent/packs/bmad-core-spec/checklists/spec-circuit-orchestrator.md +9 -0
- requirements_agent-0.0.1/src/requirements_agent/packs/bmad-core-spec/checklists/spec-circuit-pm.md +9 -0
- requirements_agent-0.0.1/src/requirements_agent/packs/bmad-core-spec/checklists/spec-circuit-po.md +10 -0
- requirements_agent-0.0.1/src/requirements_agent/packs/bmad-core-spec/checklists/spec-circuit-qa.md +11 -0
- requirements_agent-0.0.1/src/requirements_agent/packs/bmad-core-spec/checklists/spec-circuit-sm.md +8 -0
- requirements_agent-0.0.1/src/requirements_agent/packs/bmad-core-spec/data/bmad-kb.md +19 -0
- requirements_agent-0.0.1/src/requirements_agent/packs/bmad-core-spec/data/requirements-standards-baseline.md +188 -0
- requirements_agent-0.0.1/src/requirements_agent/packs/bmad-core-spec/data/technical-preferences.md +54 -0
- requirements_agent-0.0.1/src/requirements_agent/packs/bmad-core-spec/utils/template-format.md +7 -0
- requirements_agent-0.0.1/src/requirements_agent/packs/bmad-core-spec/workflows/greenfield-fullstack.yml +177 -0
- requirements_agent-0.0.1/src/requirements_agent/pipeline/__init__.py +3 -0
- requirements_agent-0.0.1/src/requirements_agent/pipeline/brd.py +66 -0
- requirements_agent-0.0.1/src/requirements_agent/pipeline/pack.py +233 -0
- requirements_agent-0.0.1/src/requirements_agent/pipeline/prompts.py +124 -0
- requirements_agent-0.0.1/src/requirements_agent/pipeline/quality.py +102 -0
- requirements_agent-0.0.1/src/requirements_agent/pipeline/refine.py +234 -0
- requirements_agent-0.0.1/src/requirements_agent/pipeline/spec_circuit.py +146 -0
- requirements_agent-0.0.1/src/requirements_agent/tui/__init__.py +3 -0
- requirements_agent-0.0.1/src/requirements_agent/tui/app.py +351 -0
- requirements_agent-0.0.1/src/requirements_agent/tui/screens/__init__.py +3 -0
- requirements_agent-0.0.1/src/requirements_agent/tuios_hook.py +41 -0
- requirements_agent-0.0.1/src/requirements_agent.egg-info/PKG-INFO +166 -0
- requirements_agent-0.0.1/src/requirements_agent.egg-info/SOURCES.txt +61 -0
- requirements_agent-0.0.1/src/requirements_agent.egg-info/dependency_links.txt +1 -0
- requirements_agent-0.0.1/src/requirements_agent.egg-info/entry_points.txt +2 -0
- requirements_agent-0.0.1/src/requirements_agent.egg-info/requires.txt +18 -0
- requirements_agent-0.0.1/src/requirements_agent.egg-info/top_level.txt +1 -0
- requirements_agent-0.0.1/tests/test_pipeline.py +116 -0
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: requirements-agent
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: Self-contained Spec Circuit Requirements Agent (CLI + Textual TUI)
|
|
5
|
+
Author: CLI-Agents
|
|
6
|
+
License: MIT
|
|
7
|
+
Requires-Python: >=3.9
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
Requires-Dist: typer>=0.12
|
|
10
|
+
Requires-Dist: rich>=13.7
|
|
11
|
+
Requires-Dist: textual>=0.80
|
|
12
|
+
Requires-Dist: openai>=1.40
|
|
13
|
+
Requires-Dist: httpx>=0.27
|
|
14
|
+
Requires-Dist: pyyaml>=6.0
|
|
15
|
+
Requires-Dist: tomli>=2.0; python_version < "3.11"
|
|
16
|
+
Requires-Dist: fpdf2>=2.7
|
|
17
|
+
Requires-Dist: markdown>=3.5
|
|
18
|
+
Provides-Extra: pdf
|
|
19
|
+
Requires-Dist: weasyprint>=62.0; extra == "pdf"
|
|
20
|
+
Provides-Extra: dev
|
|
21
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
22
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == "dev"
|
|
23
|
+
|
|
24
|
+
# Requirements Agent
|
|
25
|
+
|
|
26
|
+
Self-contained **Spec Circuit** requirements agent: multi-persona BMAD review → quality score → refine → BRD → Markdown/PDF.
|
|
27
|
+
|
|
28
|
+
No Atlas / FastAPI / Mongo dependency. Configure LLMs in JSON, agent settings in YAML, run from CLI or Textual TUI.
|
|
29
|
+
|
|
30
|
+
## Install & init
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
cd Requirement_Agent
|
|
34
|
+
pip install -e ".[dev]"
|
|
35
|
+
|
|
36
|
+
# Scaffold config in the current directory
|
|
37
|
+
req-agent init
|
|
38
|
+
|
|
39
|
+
# Or into ~/.config/requirements-agent/
|
|
40
|
+
req-agent init --global
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### npm launcher (optional)
|
|
44
|
+
|
|
45
|
+
The agent is Python. For `npx` / npm discoverability there is a thin wrapper in [`npm/`](npm/):
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
cd npm && npm install && npm link
|
|
49
|
+
npx req-agent --help
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Publish **PyPI** for the real package; publish **npm** only as the launcher (see [`npm/README.md`](npm/README.md)).
|
|
53
|
+
|
|
54
|
+
One-shot release (same version on both registries; assumes you already ran `twine`/`npm` login):
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
./scripts/publish.sh # current pyproject version
|
|
58
|
+
./scripts/publish.sh 0.2.0 # bump + publish
|
|
59
|
+
./scripts/publish.sh --dry-run # build only
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
`init` writes:
|
|
63
|
+
|
|
64
|
+
| File | Purpose |
|
|
65
|
+
|------|---------|
|
|
66
|
+
| `requirements-agent.yaml` | Agent settings (context, prompts, export, active LLM profile) |
|
|
67
|
+
| `llms.json` | Named LLM profiles (multiple models/providers) |
|
|
68
|
+
| `.env.example` | Env var cheat-sheet for API keys |
|
|
69
|
+
|
|
70
|
+
## Configure LLMs (`llms.json`)
|
|
71
|
+
|
|
72
|
+
```json
|
|
73
|
+
{
|
|
74
|
+
"default": "azure-gpt4o",
|
|
75
|
+
"models": {
|
|
76
|
+
"azure-gpt4o": {
|
|
77
|
+
"provider": "azure",
|
|
78
|
+
"model": "gpt-4o",
|
|
79
|
+
"deployment": "gpt-4o",
|
|
80
|
+
"endpoint": "https://YOUR.openai.azure.com/",
|
|
81
|
+
"api_key_env": "RA_AZURE_API_KEY",
|
|
82
|
+
"temperature": 0.3
|
|
83
|
+
},
|
|
84
|
+
"ollama-llama": {
|
|
85
|
+
"provider": "ollama",
|
|
86
|
+
"model": "llama3.2",
|
|
87
|
+
"endpoint": "http://127.0.0.1:11434/v1"
|
|
88
|
+
},
|
|
89
|
+
"mock": { "provider": "mock", "model": "mock" }
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
List profiles: `req-agent models`
|
|
95
|
+
|
|
96
|
+
## Configure agent (`requirements-agent.yaml`)
|
|
97
|
+
|
|
98
|
+
```yaml
|
|
99
|
+
llm:
|
|
100
|
+
models_file: ./llms.json
|
|
101
|
+
active: azure-gpt4o # or override with --profile
|
|
102
|
+
|
|
103
|
+
context:
|
|
104
|
+
providers: [folder]
|
|
105
|
+
folder_paths: [./docs]
|
|
106
|
+
|
|
107
|
+
prompts:
|
|
108
|
+
personas:
|
|
109
|
+
architect:
|
|
110
|
+
system_extra: "Emphasize zero-trust boundaries."
|
|
111
|
+
|
|
112
|
+
export:
|
|
113
|
+
default_format: both
|
|
114
|
+
out_dir: ./out
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Examples: [`config.example.yaml`](config.example.yaml), [`llms.example.json`](llms.example.json). Legacy TOML still loads if present.
|
|
118
|
+
|
|
119
|
+
Env overrides: `RA_CONFIG`, `RA_LLMS_JSON`, `RA_LLM_PROFILE`, `RA_LLM_PROVIDER`, `RA_LLM_MODEL`, `RA_API_KEY` / `OPENAI_API_KEY` / `RA_AZURE_*`.
|
|
120
|
+
|
|
121
|
+
## CLI
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
# Offline dry-run
|
|
125
|
+
req-agent run \
|
|
126
|
+
--title "Identity Hub SSO" \
|
|
127
|
+
--design-file ./brief.md \
|
|
128
|
+
--profile mock \
|
|
129
|
+
--format both \
|
|
130
|
+
--out ./out/identity-hub
|
|
131
|
+
|
|
132
|
+
# Use a named profile from llms.json
|
|
133
|
+
req-agent run --profile azure-gpt4o --title "..." --design-file brief.md
|
|
134
|
+
|
|
135
|
+
# Interactive TUI
|
|
136
|
+
req-agent tui --profile mock
|
|
137
|
+
|
|
138
|
+
# Stages
|
|
139
|
+
req-agent review --title "..." --design-file brief.md --out ./out
|
|
140
|
+
req-agent score --title "..." --design-file brief.md --report ./out/01-spec-circuit-report.md
|
|
141
|
+
req-agent refine --title "..." --design-file brief.md --report ./out/01-spec-circuit-report.md \
|
|
142
|
+
--message "Add measurable NFRs" --out ./out/01-refined.md
|
|
143
|
+
req-agent consolidate --title "..." --design-file brief.md --report ./out/01-refined.md \
|
|
144
|
+
--out ./out/02-requirements-report.md
|
|
145
|
+
req-agent export --report ./out/02-requirements-report.md --out ./out/report --format both
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## Context injection
|
|
149
|
+
|
|
150
|
+
| Provider | v1 |
|
|
151
|
+
|----------|----|
|
|
152
|
+
| **folder** | `--attach` / `--context-dir` / `folder_paths` |
|
|
153
|
+
| **rag** | Stub (phase 2) |
|
|
154
|
+
| **mcp** | Stub (phase 2) |
|
|
155
|
+
|
|
156
|
+
## Personas
|
|
157
|
+
|
|
158
|
+
Eight BMAD roles (vendored `bmad-core-spec`): orchestrator → analyst → pm → po → architect → dev → qa → sm.
|
|
159
|
+
|
|
160
|
+
## TUIOS
|
|
161
|
+
|
|
162
|
+
Optional: when running inside [tuios](https://github.com/Gaurav-Gosain/tuios), the agent calls `tuios set-agent-state`. Force with `RA_TUIOS_HOOK=1`.
|
|
163
|
+
|
|
164
|
+
## vs Atlas Requirements Architect
|
|
165
|
+
|
|
166
|
+
Same Spec Circuit brain and BMAD pack; Memory AI → local folder (future RAG/MCP); LLMs from `llms.json` instead of Mongo Settings. See [`REQUIREMENTS_ARCHITECT.md`](REQUIREMENTS_ARCHITECT.md).
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# Requirements Agent
|
|
2
|
+
|
|
3
|
+
Self-contained **Spec Circuit** requirements agent: multi-persona BMAD review → quality score → refine → BRD → Markdown/PDF.
|
|
4
|
+
|
|
5
|
+
No Atlas / FastAPI / Mongo dependency. Configure LLMs in JSON, agent settings in YAML, run from CLI or Textual TUI.
|
|
6
|
+
|
|
7
|
+
## Install & init
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
cd Requirement_Agent
|
|
11
|
+
pip install -e ".[dev]"
|
|
12
|
+
|
|
13
|
+
# Scaffold config in the current directory
|
|
14
|
+
req-agent init
|
|
15
|
+
|
|
16
|
+
# Or into ~/.config/requirements-agent/
|
|
17
|
+
req-agent init --global
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
### npm launcher (optional)
|
|
21
|
+
|
|
22
|
+
The agent is Python. For `npx` / npm discoverability there is a thin wrapper in [`npm/`](npm/):
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
cd npm && npm install && npm link
|
|
26
|
+
npx req-agent --help
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Publish **PyPI** for the real package; publish **npm** only as the launcher (see [`npm/README.md`](npm/README.md)).
|
|
30
|
+
|
|
31
|
+
One-shot release (same version on both registries; assumes you already ran `twine`/`npm` login):
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
./scripts/publish.sh # current pyproject version
|
|
35
|
+
./scripts/publish.sh 0.2.0 # bump + publish
|
|
36
|
+
./scripts/publish.sh --dry-run # build only
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
`init` writes:
|
|
40
|
+
|
|
41
|
+
| File | Purpose |
|
|
42
|
+
|------|---------|
|
|
43
|
+
| `requirements-agent.yaml` | Agent settings (context, prompts, export, active LLM profile) |
|
|
44
|
+
| `llms.json` | Named LLM profiles (multiple models/providers) |
|
|
45
|
+
| `.env.example` | Env var cheat-sheet for API keys |
|
|
46
|
+
|
|
47
|
+
## Configure LLMs (`llms.json`)
|
|
48
|
+
|
|
49
|
+
```json
|
|
50
|
+
{
|
|
51
|
+
"default": "azure-gpt4o",
|
|
52
|
+
"models": {
|
|
53
|
+
"azure-gpt4o": {
|
|
54
|
+
"provider": "azure",
|
|
55
|
+
"model": "gpt-4o",
|
|
56
|
+
"deployment": "gpt-4o",
|
|
57
|
+
"endpoint": "https://YOUR.openai.azure.com/",
|
|
58
|
+
"api_key_env": "RA_AZURE_API_KEY",
|
|
59
|
+
"temperature": 0.3
|
|
60
|
+
},
|
|
61
|
+
"ollama-llama": {
|
|
62
|
+
"provider": "ollama",
|
|
63
|
+
"model": "llama3.2",
|
|
64
|
+
"endpoint": "http://127.0.0.1:11434/v1"
|
|
65
|
+
},
|
|
66
|
+
"mock": { "provider": "mock", "model": "mock" }
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
List profiles: `req-agent models`
|
|
72
|
+
|
|
73
|
+
## Configure agent (`requirements-agent.yaml`)
|
|
74
|
+
|
|
75
|
+
```yaml
|
|
76
|
+
llm:
|
|
77
|
+
models_file: ./llms.json
|
|
78
|
+
active: azure-gpt4o # or override with --profile
|
|
79
|
+
|
|
80
|
+
context:
|
|
81
|
+
providers: [folder]
|
|
82
|
+
folder_paths: [./docs]
|
|
83
|
+
|
|
84
|
+
prompts:
|
|
85
|
+
personas:
|
|
86
|
+
architect:
|
|
87
|
+
system_extra: "Emphasize zero-trust boundaries."
|
|
88
|
+
|
|
89
|
+
export:
|
|
90
|
+
default_format: both
|
|
91
|
+
out_dir: ./out
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Examples: [`config.example.yaml`](config.example.yaml), [`llms.example.json`](llms.example.json). Legacy TOML still loads if present.
|
|
95
|
+
|
|
96
|
+
Env overrides: `RA_CONFIG`, `RA_LLMS_JSON`, `RA_LLM_PROFILE`, `RA_LLM_PROVIDER`, `RA_LLM_MODEL`, `RA_API_KEY` / `OPENAI_API_KEY` / `RA_AZURE_*`.
|
|
97
|
+
|
|
98
|
+
## CLI
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
# Offline dry-run
|
|
102
|
+
req-agent run \
|
|
103
|
+
--title "Identity Hub SSO" \
|
|
104
|
+
--design-file ./brief.md \
|
|
105
|
+
--profile mock \
|
|
106
|
+
--format both \
|
|
107
|
+
--out ./out/identity-hub
|
|
108
|
+
|
|
109
|
+
# Use a named profile from llms.json
|
|
110
|
+
req-agent run --profile azure-gpt4o --title "..." --design-file brief.md
|
|
111
|
+
|
|
112
|
+
# Interactive TUI
|
|
113
|
+
req-agent tui --profile mock
|
|
114
|
+
|
|
115
|
+
# Stages
|
|
116
|
+
req-agent review --title "..." --design-file brief.md --out ./out
|
|
117
|
+
req-agent score --title "..." --design-file brief.md --report ./out/01-spec-circuit-report.md
|
|
118
|
+
req-agent refine --title "..." --design-file brief.md --report ./out/01-spec-circuit-report.md \
|
|
119
|
+
--message "Add measurable NFRs" --out ./out/01-refined.md
|
|
120
|
+
req-agent consolidate --title "..." --design-file brief.md --report ./out/01-refined.md \
|
|
121
|
+
--out ./out/02-requirements-report.md
|
|
122
|
+
req-agent export --report ./out/02-requirements-report.md --out ./out/report --format both
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Context injection
|
|
126
|
+
|
|
127
|
+
| Provider | v1 |
|
|
128
|
+
|----------|----|
|
|
129
|
+
| **folder** | `--attach` / `--context-dir` / `folder_paths` |
|
|
130
|
+
| **rag** | Stub (phase 2) |
|
|
131
|
+
| **mcp** | Stub (phase 2) |
|
|
132
|
+
|
|
133
|
+
## Personas
|
|
134
|
+
|
|
135
|
+
Eight BMAD roles (vendored `bmad-core-spec`): orchestrator → analyst → pm → po → architect → dev → qa → sm.
|
|
136
|
+
|
|
137
|
+
## TUIOS
|
|
138
|
+
|
|
139
|
+
Optional: when running inside [tuios](https://github.com/Gaurav-Gosain/tuios), the agent calls `tuios set-agent-state`. Force with `RA_TUIOS_HOOK=1`.
|
|
140
|
+
|
|
141
|
+
## vs Atlas Requirements Architect
|
|
142
|
+
|
|
143
|
+
Same Spec Circuit brain and BMAD pack; Memory AI → local folder (future RAG/MCP); LLMs from `llms.json` instead of Mongo Settings. See [`REQUIREMENTS_ARCHITECT.md`](REQUIREMENTS_ARCHITECT.md).
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "requirements-agent"
|
|
7
|
+
version = "0.0.1"
|
|
8
|
+
description = "Self-contained Spec Circuit Requirements Agent (CLI + Textual TUI)"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.9"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
authors = [{ name = "CLI-Agents" }]
|
|
13
|
+
dependencies = [
|
|
14
|
+
"typer>=0.12",
|
|
15
|
+
"rich>=13.7",
|
|
16
|
+
"textual>=0.80",
|
|
17
|
+
"openai>=1.40",
|
|
18
|
+
"httpx>=0.27",
|
|
19
|
+
"pyyaml>=6.0",
|
|
20
|
+
"tomli>=2.0; python_version < '3.11'",
|
|
21
|
+
"fpdf2>=2.7",
|
|
22
|
+
"markdown>=3.5",
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
[project.optional-dependencies]
|
|
26
|
+
pdf = ["weasyprint>=62.0"]
|
|
27
|
+
dev = ["pytest>=8.0", "pytest-asyncio>=0.23"]
|
|
28
|
+
|
|
29
|
+
[project.scripts]
|
|
30
|
+
req-agent = "requirements_agent.cli:app"
|
|
31
|
+
|
|
32
|
+
[tool.setuptools.packages.find]
|
|
33
|
+
where = ["src"]
|
|
34
|
+
|
|
35
|
+
[tool.setuptools.package-data]
|
|
36
|
+
requirements_agent = ["packs/**/*"]
|
|
37
|
+
|
|
38
|
+
[tool.pytest.ini_options]
|
|
39
|
+
asyncio_mode = "auto"
|
|
40
|
+
testpaths = ["tests"]
|
|
41
|
+
pythonpath = ["src"]
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from typing import Any, Callable, Dict, List, Optional
|
|
5
|
+
|
|
6
|
+
from requirements_agent.config import AppConfig
|
|
7
|
+
from requirements_agent.export.markdown import export_run_artifacts
|
|
8
|
+
from requirements_agent.export.pdf import export_pdf
|
|
9
|
+
from requirements_agent.llm.base import LlmClient
|
|
10
|
+
from requirements_agent.llm.router import build_llm_client
|
|
11
|
+
from requirements_agent.models import QualityScore, ReviewResult
|
|
12
|
+
from requirements_agent.pipeline.brd import BRDConsolidator
|
|
13
|
+
from requirements_agent.pipeline.quality import QualityScorer
|
|
14
|
+
from requirements_agent.pipeline.refine import ReportRefiner
|
|
15
|
+
from requirements_agent.pipeline.spec_circuit import SpecCircuitService
|
|
16
|
+
from requirements_agent.tuios_hook import set_agent_state
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
ProgressCallback = Callable[[Dict[str, Any]], None]
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class RequirementsAgent:
|
|
23
|
+
def __init__(self, config: AppConfig, llm: Optional[LlmClient] = None, *, extra_paths: Optional[List[str]] = None):
|
|
24
|
+
self.config = config
|
|
25
|
+
self.llm = llm or build_llm_client(config.llm)
|
|
26
|
+
self.extra_paths = list(extra_paths or [])
|
|
27
|
+
self.spec = SpecCircuitService.from_app_config(config, self.llm, extra_folder_paths=self.extra_paths)
|
|
28
|
+
self.quality = QualityScorer(self.llm, self.spec.context)
|
|
29
|
+
self.refiner = ReportRefiner(self.llm, self.spec.context)
|
|
30
|
+
self.brd = BRDConsolidator(self.llm, self.spec.context)
|
|
31
|
+
|
|
32
|
+
def review(self, title: str, design: str, *, on_progress: Optional[ProgressCallback] = None) -> ReviewResult:
|
|
33
|
+
set_agent_state("working", detail="Spec Circuit review")
|
|
34
|
+
try:
|
|
35
|
+
return self.spec.review(title, design, on_progress=on_progress)
|
|
36
|
+
finally:
|
|
37
|
+
set_agent_state("idle")
|
|
38
|
+
|
|
39
|
+
def score(
|
|
40
|
+
self,
|
|
41
|
+
title: str,
|
|
42
|
+
design: str,
|
|
43
|
+
report: str,
|
|
44
|
+
*,
|
|
45
|
+
refinement_context: str = "",
|
|
46
|
+
) -> QualityScore:
|
|
47
|
+
set_agent_state("working", detail="Quality score")
|
|
48
|
+
try:
|
|
49
|
+
return self.quality.score(title, design, report, refinement_context=refinement_context)
|
|
50
|
+
finally:
|
|
51
|
+
set_agent_state("idle")
|
|
52
|
+
|
|
53
|
+
def refine(self, title: str, design: str, report: str, message: str, *, history=None) -> Dict[str, Any]:
|
|
54
|
+
set_agent_state("working", detail="Refine report")
|
|
55
|
+
try:
|
|
56
|
+
return self.refiner.refine(title, design, report, message, history=history)
|
|
57
|
+
finally:
|
|
58
|
+
set_agent_state("idle")
|
|
59
|
+
|
|
60
|
+
def questions(self, title: str, design: str, report: str) -> Dict[str, Any]:
|
|
61
|
+
set_agent_state("working", detail="Extract questions")
|
|
62
|
+
try:
|
|
63
|
+
return self.refiner.extract_open_questions(title, design, report)
|
|
64
|
+
finally:
|
|
65
|
+
set_agent_state("idle")
|
|
66
|
+
|
|
67
|
+
def resolve(self, title: str, design: str, report: str, question: str) -> Dict[str, Any]:
|
|
68
|
+
set_agent_state("working", detail="Suggest resolution")
|
|
69
|
+
try:
|
|
70
|
+
return self.refiner.suggest_question_resolution(title, design, report, question)
|
|
71
|
+
finally:
|
|
72
|
+
set_agent_state("idle")
|
|
73
|
+
|
|
74
|
+
def consolidate(self, title: str, design: str, report: str) -> Dict[str, Any]:
|
|
75
|
+
set_agent_state("working", detail="BRD consolidation")
|
|
76
|
+
try:
|
|
77
|
+
return self.brd.consolidate(title, design, report)
|
|
78
|
+
finally:
|
|
79
|
+
set_agent_state("idle")
|
|
80
|
+
|
|
81
|
+
def run(
|
|
82
|
+
self,
|
|
83
|
+
title: str,
|
|
84
|
+
design: str,
|
|
85
|
+
*,
|
|
86
|
+
out_dir: Optional[Path] = None,
|
|
87
|
+
export_format: Optional[str] = None,
|
|
88
|
+
consolidate: bool = True,
|
|
89
|
+
on_progress: Optional[ProgressCallback] = None,
|
|
90
|
+
) -> Dict[str, Any]:
|
|
91
|
+
out = Path(out_dir or self.config.export.out_dir).expanduser()
|
|
92
|
+
fmt = (export_format or self.config.export.default_format or "md").lower()
|
|
93
|
+
|
|
94
|
+
review = self.review(title, design, on_progress=on_progress)
|
|
95
|
+
if not review.success:
|
|
96
|
+
return {"success": False, "error": review.error}
|
|
97
|
+
|
|
98
|
+
quality = self.score(title, design, review.report_markdown)
|
|
99
|
+
brd_md = None
|
|
100
|
+
if consolidate:
|
|
101
|
+
brd_result = self.consolidate(title, design, review.report_markdown)
|
|
102
|
+
if brd_result.get("success"):
|
|
103
|
+
brd_md = brd_result["report_markdown"]
|
|
104
|
+
|
|
105
|
+
quality_dict = {
|
|
106
|
+
"overall_score": quality.overall_score,
|
|
107
|
+
"dimensions": quality.dimensions,
|
|
108
|
+
"rationale": quality.rationale,
|
|
109
|
+
"top_gaps": quality.top_gaps,
|
|
110
|
+
"success": quality.success,
|
|
111
|
+
"error": quality.error,
|
|
112
|
+
}
|
|
113
|
+
paths = export_run_artifacts(
|
|
114
|
+
out,
|
|
115
|
+
spec_circuit=review.report_markdown,
|
|
116
|
+
brd=brd_md,
|
|
117
|
+
quality=quality_dict,
|
|
118
|
+
sections=review.sections,
|
|
119
|
+
meta={
|
|
120
|
+
"title": title,
|
|
121
|
+
"provider": self.config.llm.provider,
|
|
122
|
+
"model": self.config.llm.model,
|
|
123
|
+
"context": review.context.summary() if review.context else None,
|
|
124
|
+
},
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
pdf_paths = []
|
|
128
|
+
if fmt in ("pdf", "both"):
|
|
129
|
+
if review.report_markdown:
|
|
130
|
+
p = export_pdf(review.report_markdown, out / "01-spec-circuit-report.pdf", title=title)
|
|
131
|
+
pdf_paths.append(str(p))
|
|
132
|
+
if brd_md:
|
|
133
|
+
p = export_pdf(brd_md, out / "02-requirements-report.pdf", title=f"{title} — BRD")
|
|
134
|
+
pdf_paths.append(str(p))
|
|
135
|
+
paths["pdf"] = pdf_paths
|
|
136
|
+
|
|
137
|
+
return {
|
|
138
|
+
"success": True,
|
|
139
|
+
"paths": paths,
|
|
140
|
+
"quality": quality_dict,
|
|
141
|
+
"report_markdown": review.report_markdown,
|
|
142
|
+
"brd_markdown": brd_md,
|
|
143
|
+
}
|