Skip to content

Commit 195fac3

Browse files
vldcmp-uipathclaude
andcommitted
fix(cli): warn instead of erroring when several frameworks are installed
Environments with more than one agent framework package scaffolded fine before `--type` existed — the first discovered integration claimed the project. Turning that into an error would be a breaking change, so the old outcome stays: `uipath new` warns, names all the installed frameworks and the one it picked, and scaffolds with the first discovered. `--agent-framework` remains the way to choose deliberately. The pick is dispatched to that framework's middleware directly, so the warning always names the integration that actually scaffolds. Discovery order is the entry-point order (a filesystem accident, stable per environment); listings shown to the user stay sorted. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 129c451 commit 195fac3

5 files changed

Lines changed: 35 additions & 23 deletions

File tree

‎packages/uipath/docs/cli/index.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,9 @@ Scaffolds a project in the current directory. `--type` selects what gets created
8383
|----------------------------------|------------------------|------------------------------|
8484
| none | coded function project | error: install an agent framework |
8585
| one | that framework's coded agent project | that framework's coded agent project |
86-
| several | error: pick one with `--agent-framework` | error: pick one with `--agent-framework` |
86+
| several | warns, scaffolds with the first discovered | warns, scaffolds with the first discovered |
8787

88-
With one framework installed there is nothing to choose, so `uipath new` uses it. With several, it cannot tell which you meant and asks you to name one:
88+
With one framework installed there is nothing to choose, so `uipath new` uses it. With several, it warns and scaffolds with the first one discovered — pass `--agent-framework` to choose deliberately:
8989

9090
```shell
9191
uipath new my-agent --type agent --agent-framework uipath-langchain

‎packages/uipath/docs/core/agents.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ The example below uses LangChain. Swap `uipath-langchain` for the framework of y
9595
uipath new agent --type agent
9696
```
9797

98-
With several framework integrations installed in the same environment, name the one to scaffold with:
98+
With several framework integrations installed in the same environment, `uipath new` warns and uses the first one discovered; name the one you want instead with:
9999

100100
```shell
101101
uipath new agent --type agent --agent-framework uipath-langchain

‎packages/uipath/docs/core/studio_web.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ Selected tenant: Tenant1
224224
That's it, your agent should now be visible in Studio Web.
225225
226226
/// info
227-
`uipath new` defaults to `--type auto`, which lets the installed framework integration claim the scaffold. Pass `--type agent` to require an agent project — it fails rather than creating a function project when no framework is installed. With several integrations installed, name the one to scaffold with: `uipath new agent --type agent --agent-framework uipath-langchain`.
227+
`uipath new` defaults to `--type auto`, which lets the installed framework integration claim the scaffold. Pass `--type agent` to require an agent project — it fails rather than creating a function project when no framework is installed. With several integrations installed, `uipath new` warns and uses the first one discovered; pick explicitly with `uipath new agent --type agent --agent-framework uipath-langchain`.
228228
///
229229
230230
#### Coded Function

‎packages/uipath/src/uipath/_cli/cli_new.py‎

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ def generate_uipath_json(target_directory):
6262

6363

6464
def installed_agent_frameworks() -> list[AgentFramework]:
65-
"""Agent frameworks that can scaffold a project in this environment."""
65+
"""Agent frameworks that can scaffold a project, in discovery order."""
6666
packages: dict[str, str] = {}
6767
for entry_point in importlib.metadata.entry_points(group="uipath.middlewares"):
6868
if entry_point.dist is not None:
@@ -73,7 +73,7 @@ def installed_agent_frameworks() -> list[AgentFramework]:
7373
package = packages.get(middleware.__module__.split(".")[0])
7474
if package is not None:
7575
frameworks.append(AgentFramework(package=package, scaffold=middleware))
76-
return sorted(frameworks, key=lambda framework: framework.package)
76+
return frameworks
7777

7878

7979
def _select_agent_framework(
@@ -85,7 +85,9 @@ def _select_agent_framework(
8585
return framework
8686

8787
installed = (
88-
"Installed: " + ", ".join(framework.package for framework in frameworks) + "."
88+
"Installed: "
89+
+ ", ".join(sorted(framework.package for framework in frameworks))
90+
+ "."
8991
if frameworks
9092
else "No agent framework is installed."
9193
)
@@ -108,13 +110,15 @@ def _scaffold_agent(name: str, agent_framework: str | None) -> MiddlewareResult:
108110
return _select_agent_framework(installed, agent_framework).scaffold(name)
109111

110112
if len(installed) > 1:
111-
console.error(
113+
first = installed[0]
114+
console.warning(
112115
"Multiple agent frameworks are installed: "
113116
+ ", ".join(framework.package for framework in installed)
114-
+ f".\nPick one with `uipath new {name} --type agent "
115-
"--agent-framework <framework>`, or run "
116-
f"`uipath new {name} --type function` to create a function project."
117+
+ f".\nScaffolding with the first one discovered: '{first.package}'. "
118+
f"To pick a different one, run `uipath new {name} --type agent "
119+
"--agent-framework <framework>`."
117120
)
121+
return first.scaffold(name)
118122

119123
return Middlewares.next("new", name)
120124

@@ -137,8 +141,8 @@ def _scaffold_agent(name: str, agent_framework: str | None) -> MiddlewareResult:
137141
"agent_framework",
138142
default=None,
139143
help="Agent framework to scaffold with, named by its package (e.g. "
140-
"`uipath-langchain`). Only valid together with `--type agent`; needed "
141-
"when several frameworks are installed, optional otherwise.",
144+
"`uipath-langchain`). Only valid together with `--type agent`; picks "
145+
"which framework scaffolds when several are installed.",
142146
)
143147
@track_command("new")
144148
def new(name: str, project_type: str, agent_framework: str | None):

‎packages/uipath/tests/cli/test_new.py‎

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -183,30 +183,38 @@ def test_new_type_agent_without_a_framework_errors(
183183
assert not os.path.exists("main.py")
184184
assert not os.path.exists("uipath.json")
185185

186-
def test_new_multiple_frameworks_installed_require_a_choice(
186+
def test_new_multiple_frameworks_warn_and_use_the_first_discovered(
187187
self, runner: CliRunner, temp_dir: str
188188
) -> None:
189-
"""Several frameworks installed must not resolve by registration order."""
189+
"""Several frameworks installed: warn, then scaffold with the first.
190+
191+
Erroring here would break environments that scaffolded fine before
192+
`--type` existed, so the old behaviour stays the default and the
193+
warning points at `--agent-framework` for choosing explicitly.
194+
"""
190195
with runner.isolated_filesystem(temp_dir=temp_dir):
191196
for extra_args in ([], ["--type", "auto"], ["--type", "agent"]):
197+
first = _framework("uipath-llamaindex")
198+
other = _framework("uipath-langchain")
192199
with (
193200
patch("uipath._cli.cli_new.Middlewares.next") as mock_middleware,
194201
patch(
195202
"uipath._cli.cli_new.installed_agent_frameworks",
196-
return_value=[
197-
_framework("uipath-langchain"),
198-
_framework("uipath-llamaindex"),
199-
],
203+
return_value=[first, other],
200204
),
201205
):
202206
result = runner.invoke(cli, ["new", "my_agent"] + extra_args)
203-
assert result.exit_code == 1
207+
assert result.exit_code == 0
204208
assert "Multiple agent frameworks are installed" in result.output
205-
assert "uipath-langchain, uipath-llamaindex" in result.output
209+
# listed in discovery order, so the first named is the pick
210+
assert "uipath-llamaindex, uipath-langchain" in result.output
211+
assert "first one discovered: 'uipath-llamaindex'" in result.output
206212
assert "--agent-framework" in result.output
207-
assert "--type function" in result.output
208-
assert not os.path.exists("main.py")
213+
_scaffold_of(first).assert_called_once_with("my_agent")
214+
_scaffold_of(other).assert_not_called()
209215
mock_middleware.assert_not_called()
216+
# claimed by the framework: no base function scaffold
217+
assert not os.path.exists("uipath.json")
210218

211219
def test_agent_framework_scaffolds_with_the_chosen_one_only(
212220
self, runner: CliRunner, temp_dir: str

0 commit comments

Comments
 (0)