robotcode 2.8.0.dev677__tar.gz → 2.9.0.dev68__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.
@@ -6,6 +6,148 @@ All notable changes to this project will be documented in this file. See [conven
6
6
 
7
7
  ### <!-- 0 -->Features
8
8
 
9
+ #### PyCharm
10
+
11
+ - Debug the Python code of libraries with "Attach Python" ([cb3354c](https://github.com/robotcodedev/robotcode/commit/cb3354cf9faa195d2b74c196f38f33698689ac46))
12
+
13
+ A Debug run of a Robot Framework run configuration can now also stop at Python
14
+ breakpoints in the code of libraries and keywords. The new option "Attach
15
+ Python", off by default, on the Debug settings page or per run configuration,
16
+ starts the run under PyCharm's own Python debugger in either debugger mode,
17
+ with nothing to install, and shows its Python session in a tab "Python <name>"
18
+ beside the Robot Framework session; Stop and Rerun in either tab act on the
19
+ whole run.
20
+
21
+ - Show a keyword's usages on Ctrl+click on its definition ([6b29872](https://github.com/robotcodedev/robotcode/commit/6b298725de829e1843ef24ca507799b1e02f0f3d))
22
+
23
+ In PyCharm, Ctrl+click and Navigate | Declaration or Usages on the name
24
+ of a keyword definition now list the keyword's usages, as Show Usages
25
+ does, instead of "Cannot find declaration to go to". Ctrl+hover on the
26
+ name shows the keyword's documentation, as on a call (#677).
27
+
28
+
29
+ #### REPL
30
+
31
+ - Show the result of each statement and the prompt for AI agents ([3842b1f](https://github.com/robotcodedev/robotcode/commit/3842b1f482ea7c14f42b8787dd93567d2ab3bc54))
32
+
33
+ `robotcode repl` now prints what a statement returned as `=> <value>`, as the debugger's `(rdb)` prompt does; at both prompts `None` and assignments show no such line. In the session of an AI agent the REPL also shows its `>>>` prompt on piped input, so the agent sees when a statement has ended; `--show-prompt` and `--no-show-prompt` switch it for piped input in any session.
34
+
35
+
36
+ #### RobotCode
37
+
38
+ - Write errors that stop a command as [ ERROR ] ([c2add74](https://github.com/robotcodedev/robotcode/commit/c2add74cdf9ca82b90f37e28e5c3d819b27d2eb0))
39
+
40
+ An error that stops a command, such as a mistyped profile or option, now looks like the errors robotcode reports and
41
+ goes on after: `[ ERROR ] No profile matches 'typo'.`, with ERROR in red on a terminal, instead of `Error: …`. Debug
42
+ sessions show it the same way, and the exit codes stay.
43
+
44
+
45
+
46
+ ### <!-- 1 -->Bug Fixes
47
+
48
+ #### PyCharm
49
+
50
+ - End a debug session with the Terminal tab in front ([0d6b972](https://github.com/robotcodedev/robotcode/commit/0d6b972ec1bbd4d171b94a96791b56e1e8343df1))
51
+
52
+ A debug session in PyCharm now ends with the Terminal tab in front, as a
53
+ run does, instead of the Debug Console. An error that stops the session
54
+ before Robot Framework runs, such as a selected profile that robot.toml
55
+ does not define, is then in view.
56
+
57
+
58
+ #### REPL
59
+
60
+ - Start robotcode when only the replserver extra is installed ([c9255a3](https://github.com/robotcodedev/robotcode/commit/c9255a36131ae4e4ea058a55948f9e8043f9119a))
61
+
62
+ With `robotcode[replserver]` or `robotcode-repl-server` installed
63
+ without `robotcode-repl`, every robotcode command failed, even
64
+ `robotcode --version`, with "No module named 'robotcode.repl'". The
65
+ REPL server package now installs `robotcode-repl` with it.
66
+
67
+
68
+ #### Robot
69
+
70
+ - Find a library class whose name differs from its module ([598239d](https://github.com/robotcodedev/robotcode/commit/598239d4a35cd7faf605b0e34271a4a45609abe2))
71
+
72
+ Since Robot Framework 7.2 a library module may hold its library class
73
+ under another name when it is the only class marked with @library or
74
+ ROBOT_AUTO_KEYWORDS. RobotCode now loads that class as robot does, so its
75
+ keywords are no longer reported as missing (#678). A failed library
76
+ import now reads "Importing library 'X' failed", as in robot's message.
77
+
78
+ - Render documentation links and images whose target contains a space ([e5c66d7](https://github.com/robotcodedev/robotcode/commit/e5c66d7b8ddecfc826fe1aa599aa52fefad67d69))
79
+
80
+ A link or an image in Robot Framework documentation whose target contains a
81
+ space, such as `[images/doc/my image.png|Title]`, showed up as raw Markdown
82
+ text in hovers and in the Documentation Viewer instead of a link or an image.
83
+
84
+
85
+ #### VS Code
86
+
87
+ - Stay quiet in folders without Robot Framework ([9691d40](https://github.com/robotcodedev/robotcode/commit/9691d40e180a7a68a85f94ab94a15667877123d4))
88
+
89
+ In a workspace folder without Robot Framework, such as a TypeScript project in which a Markdown file or a debug
90
+ session activated RobotCode, RobotCode no longer shows its environment message, starts no Python processes and shows
91
+ nothing in the Testing view. A folder that becomes a Robot Framework project during the session, through a robot.toml,
92
+ a dependency in pyproject.toml or requirements.txt, or a first .robot file, gets its language server and tests without
93
+ a reload, and the update notification waits for such a folder.
94
+
95
+ - Keep errors that end the REPL in its terminal ([21f1a9f](https://github.com/robotcodedev/robotcode/commit/21f1a9f4c29acaca08ceeaa417397ec1c96ebee9))
96
+
97
+ An error that ends the REPL, such as a selected configuration profile that the folder does not define, now stays in
98
+ the REPL's terminal until you press a key. Before, a notification came instead of the REPL, or VS Code closed the
99
+ terminal and only reported its exit code.
100
+
101
+
102
+
103
+ ### <!-- 2 -->Documentation
104
+
105
+ #### VS Code
106
+
107
+ - Say that errors that end the REPL stay in its terminal ([2013cdc](https://github.com/robotcodedev/robotcode/commit/2013cdc7f5ecf5dc7fcbee8cb49aecdcd4f76460))
108
+
109
+ #### Website
110
+
111
+ - Describe "Attach Python" in the PyCharm guide ([c683167](https://github.com/robotcodedev/robotcode/commit/c683167b3aa38cce6522c1cb2e924e41bc63c903))
112
+
113
+ The debugging page explains how to debug the Python code of libraries in a
114
+ second session of PyCharm's Python debugger, and the configuration, running and
115
+ comparison pages list the option.
116
+
117
+ - Move Finding Robot Files into Project Configuration ([80949f7](https://github.com/robotcodedev/robotcode/commit/80949f7f5763879f66407343881d801e998f04c5))
118
+
119
+ The guide on which files RobotCode finds is now a page of the Project
120
+ Configuration group, after Files and Project Root, and its Quick start
121
+ describes the project root as that page does. The group Robot Framework
122
+ Tips is now called Tips & Tricks.
123
+
124
+ - Group the guides by tool and topic ([81b22b8](https://github.com/robotcodedev/robotcode/commit/81b22b8aa0cb3c98710bf17bb234383fac9fb52e))
125
+
126
+ The Guides area now has a group per tool and topic: the command guides
127
+ and the wrapper guide moved to /guides/cli/ under an overview, the
128
+ Robot Framework tips to /guides/tips/ and the highlighting tip into the
129
+ VS Code group, and the robot.toml group and the .robotignore guide are
130
+ named by their subject. Getting Started has a page for the command
131
+ line. The old paths are not redirected.
132
+
133
+ - Add a security.txt ([8f11e99](https://github.com/robotcodedev/robotcode/commit/8f11e9946cdf8c23d65de272a4e2ae594985b1d1))
134
+
135
+ robotcode.io/.well-known/security.txt names the contacts for security
136
+ reports from SECURITY.md. The Pages upload now includes hidden
137
+ directories, which it leaves out by default.
138
+
139
+ - Add a robots.txt and keep the old sitemap.xml address ([4056212](https://github.com/robotcodedev/robotcode/commit/40562125c751ca89aea7ad47d0fdbd436622aad1))
140
+
141
+ The robots.txt tells search engines where the sitemap is. /sitemap.xml,
142
+ the sitemap address of the VitePress site, answers again and points to
143
+ the pages of the new sitemap.
144
+
145
+
146
+
147
+ ## [2.8.0](https://github.com/robotcodedev/robotcode/compare/v2.7.0..v2.8.0) - 2026-10-25
148
+
149
+ ### <!-- 0 -->Features
150
+
9
151
  #### Analyze
10
152
 
11
153
  - Add hidden dump-model command to inspect the semantic model ([23ad07c](https://github.com/robotcodedev/robotcode/commit/23ad07c8ffbddf3b6429d94f958537cdd39bf0c6))
@@ -48,6 +190,10 @@ All notable changes to this project will be documented in this file. See [conven
48
190
 
49
191
  #### Language Server
50
192
 
193
+ - Show the errors of the configuration in the editor ([3bbd793](https://github.com/robotcodedev/robotcode/commit/3bbd79367cabf8b2a2104c7aa04b27c893839405))
194
+
195
+ The language server now starts also when robot.toml cannot be loaded or a profile name selects nothing, and shows such errors of the configuration as error messages in the editor instead of only in its log. Names of the editor's own profile selection are left to the editor, which reports them with a way to fix them.
196
+
51
197
  - Highlight uses of keyword arguments as parameters ([e4ae168](https://github.com/robotcodedev/robotcode/commit/e4ae168c607daa0398e78e4c69a443b06a38e830))
52
198
 
53
199
  Uses of an argument declared in [Arguments] now get the semantic token
@@ -148,6 +294,17 @@ All notable changes to this project will be documented in this file. See [conven
148
294
 
149
295
  #### PyCharm
150
296
 
297
+ - Report selected profiles that robot.toml does not define ([3489863](https://github.com/robotcodedev/robotcode/commit/3489863203ae585da40268ca094e6ade6ea814dc))
298
+
299
+ When the selection names a profile that robot.toml does not define, a notification says so and offers Remove from Selection and Select Configuration Profiles..., also in place of the notification about a failed discovery. The profile list keeps patterns and hidden profiles in the selection, and messages of the language server show characters such as * and < as they are.
300
+
301
+ - Complete robot.toml and highlight robot code blocks in Markdown ([aa1af47](https://github.com/robotcodedev/robotcode/commit/aa1af472c9bd27aa10f8ee4475c206fdaf128f20))
302
+
303
+ PyCharm now completes the settings of robot.toml and .robot.toml from
304
+ RobotCode's JSON schema without a schema mapping by hand, as VS Code does.
305
+ Markdown code blocks marked robot, like those marked robotframework, are
306
+ highlighted as Robot Framework code in the editor and the preview.
307
+
151
308
  - Use the interpreter of the Robot Framework module ([1c77903](https://github.com/robotcodedev/robotcode/commit/1c77903e1757b875d142e3c34baf0827e95d42f8))
152
309
 
153
310
  In a project with several modules, RobotCode now takes the interpreter
@@ -274,6 +431,10 @@ All notable changes to this project will be documented in this file. See [conven
274
431
 
275
432
  #### REPL
276
433
 
434
+ - Name the file and line of each keyword in the JSON of robotcode doc ([7124234](https://github.com/robotcodedev/robotcode/commit/7124234d715b8922d2cd66fe66b65247ebc05c2c))
435
+
436
+ The keyword entries in the JSON of `robotcode doc` now carry `source` and `lineno`, the file that defines the keyword and its line there, empty and `-1` when they are unknown. A tool that reads the JSON can open the definition of a keyword from them.
437
+
277
438
  - Handle Ctrl-C like Python's REPL and pdb ([27124be](https://github.com/robotcodedev/robotcode/commit/27124be4aef8453a03df8891611dd545fa59baf0))
278
439
 
279
440
  Ctrl-C at the `>>>`, `(rdb)` and `(com)` prompts used to end the session, resume the run or store the typed commands; it now drops what was typed and shows the prompt again. While a run executes with the debugger attached, Ctrl-C pauses at the next keyword instead of failing the keyword that runs.
@@ -373,6 +534,34 @@ All notable changes to this project will be documented in this file. See [conven
373
534
 
374
535
  #### VS Code
375
536
 
537
+ - Show or open a Documentation Viewer from the Documentation Bookmarks view ([bc9855f](https://github.com/robotcodedev/robotcode/commit/bc9855f7569a0272444c7fa1b1e549eaec79a278))
538
+
539
+ The title of the Documentation Bookmarks view has two buttons: Show Documentation Viewer brings the viewer that the actions use to the front with the focus, also from another window, or opens one when there is none, and New Documentation Viewer opens a new one. Show Documentation Viewer is a command of the palette too.
540
+
541
+ - Add a context menu to the outline of the Documentation Viewer ([8a1b212](https://github.com/robotcodedev/robotcode/commit/8a1b212773b1b29e9f7242729b4c910a9b4dda6d))
542
+
543
+ A right-click on an entry of the outline, the context menu key or Shift+F10 opens a menu that shows the entry in the same or in a new viewer, bookmarks it without going there, and for a keyword opens the file that defines it at its line, also a library of the Python environment such as `Collections.py`.
544
+
545
+ - Report selected profiles that a folder does not define ([10ef5c8](https://github.com/robotcodedev/robotcode/commit/10ef5c813dcbc6624272a9fa49af724d3d8b54a7))
546
+
547
+ When robotcode.profiles names a profile that a folder's configuration does not define, a notification says so and offers Remove from Selection and Select Configuration Profiles, the Testing view shows a hint instead of an error item, and the REPL shows the notification instead of a terminal that closes with the error. Select Configuration Profiles keeps patterns and hidden profiles in the selection and stores long profile names in full.
548
+
549
+ - Bookmark places in the Documentation Viewer ([9f56212](https://github.com/robotcodedev/robotcode/commit/9f56212038429dcffce77ebb9a2a8db898186367))
550
+
551
+ A star after the target field bookmarks the place a viewer shows, in its
552
+ workspace folder. The Explorer view Documentation Bookmarks lists, opens
553
+ and removes the bookmarks and moves them to All Workspaces, which
554
+ Settings Sync takes to other machines; the first start bookmarks the
555
+ standard libraries. The target field shows the place after a #, as a
556
+ browser's address bar does, and offers the bookmarks before its
557
+ completions.
558
+
559
+ - Complete the target in the Documentation Viewer ([16e6fbb](https://github.com/robotcodedev/robotcode/commit/16e6fbba7d76c00982e09c291e4fecb2e53a4614))
560
+
561
+ While you type in the target field of the Documentation Viewer, a list under
562
+ it completes the names of libraries, resources and suite files, as the editor
563
+ does for imports. Enter or Tab takes the selected suggestion.
564
+
376
565
  - Copy the versions in use for a report ([1e0d8f8](https://github.com/robotcodedev/robotcode/commit/1e0d8f8b32589035e61f652c428cdcea9e40268e))
377
566
  - Open a new Documentation Viewer from a viewer's toolbar ([e4c6fe7](https://github.com/robotcodedev/robotcode/commit/e4c6fe78d11d654676ee0857ad8d77ec0ed84569))
378
567
 
@@ -503,6 +692,10 @@ All notable changes to this project will be documented in this file. See [conven
503
692
 
504
693
  #### Config
505
694
 
695
+ - Stop at a profile name that selects no profile ([dd3fb9c](https://github.com/robotcodedev/robotcode/commit/dd3fb9c45646da1760903c6226f7789d7fe8f706))
696
+
697
+ A profile name or pattern from -p, ROBOTCODE_PROFILES, an editor's selection or inherits that selects no profile now stops robotcode before it runs anything, as an invalid robot.toml does: run exits with 252 and reports "No profile matches 'typo'.". Until now the command went on without the profile, so a mistyped profile on a CI server ran with another configuration. A name in default-profiles is only reported, an exact name also selects a profile with *, ? or [ in its name, and profiles that inherit each other stop with an error instead of a crash.
698
+
506
699
  - Apply none of the profiles a disabled profile inherits from ([edaa183](https://github.com/robotcodedev/robotcode/commit/edaa183792ecbb1f9de72d6f68731e8fafc61545))
507
700
 
508
701
  Selecting a disabled profile still applied the profiles two or more levels up
@@ -517,6 +710,10 @@ All notable changes to this project will be documented in this file. See [conven
517
710
 
518
711
  #### Debugger
519
712
 
713
+ - Show an error before the run in the Debug Console ([e7f9a61](https://github.com/robotcodedev/robotcode/commit/e7f9a61bb460c9cf1bd0ba959f11e29112ed01f0))
714
+
715
+ With the internal console, a run that robotcode stops before Robot Framework runs, for example because of an error in robot.toml, now shows the error in the Debug Console. Until now the debug session ended first and the error was lost.
716
+
520
717
  - Let a run's variable replace an inherited one of any case on Windows ([82ea39e](https://github.com/robotcodedev/robotcode/commit/82ea39e6265b79dd44252f8ddc46e8bd72fbd4f9))
521
718
 
522
719
  On Windows, a variable that a run's environment sets, such as `path` in
@@ -622,6 +819,13 @@ All notable changes to this project will be documented in this file. See [conven
622
819
 
623
820
  #### PyCharm
624
821
 
822
+ - Show the report and the log in the preview in PyCharm's theme ([c0f92e4](https://github.com/robotcodedev/robotcode/commit/c0f92e42351b9558c8bc7fc0fbda4a2766951eb1))
823
+
824
+ With Robot Framework 7.0 or later, the built-in preview shows the report
825
+ and the log in PyCharm's light or dark theme and follows a change of the
826
+ theme, also in an open tab. A theme chosen with the switch of the report
827
+ or the log stays until PyCharm's theme changes.
828
+
625
829
  - Name the run configuration in the texts about its interpreter ([9e905c4](https://github.com/robotcodedev/robotcode/commit/9e905c4110bdc5b99e05d35be99f28705b0c639f))
626
830
 
627
831
  When a Robot Framework run configuration has an interpreter other than the
@@ -984,6 +1188,36 @@ All notable changes to this project will be documented in this file. See [conven
984
1188
 
985
1189
  #### Runner
986
1190
 
1191
+ - Don't double the backslashes in results log links with spaces ([15cdb24](https://github.com/robotcodedev/robotcode/commit/15cdb248b2e2d4418748ce32bd04f6115b4428ec))
1192
+
1193
+ On Windows, with html-to-markdown installed, `robotcode results log` showed
1194
+ links to files outside the output directory with doubled backslashes when the
1195
+ path contains a space.
1196
+
1197
+ - Take the wrapper from the configuration of the command ([aee1e50](https://github.com/robotcodedev/robotcode/commit/aee1e505428ef82a3a549e10914971a1fcf71d7a))
1198
+
1199
+ Commands that run Robot Framework take the wrapper from the configuration
1200
+ they use, found from their paths, and load that configuration once. A run
1201
+ of a project's tests from the root of a monorepo now runs under that
1202
+ project's wrapper, and -v shows the loading once. A configuration that
1203
+ cannot be loaded starts no wrapper, also not one given with --wrapper.
1204
+
1205
+ - Resolve encoded and file: links and videos in results log ([85ddc4c](https://github.com/robotcodedev/robotcode/commit/85ddc4c6a8372c4daf5af4635aa9dea5ed460a50))
1206
+
1207
+ robotcode results log now finds files whose names are URL-encoded, such as
1208
+ screenshots named after a test, follows the file: links OperatingSystem logs
1209
+ for files in the output directory, and extracts the videos Browser records.
1210
+ Linked screenshots no longer get an extra skipped entry, embedded files keep
1211
+ the name of their download attribute, and every message that links an
1212
+ extracted file points to the copy.
1213
+
1214
+ - Keep screenshot messages when an old html-to-markdown is installed ([1d719bc](https://github.com/robotcodedev/robotcode/commit/1d719bcf1c0745136f5147d5a9e0bc01277d8202))
1215
+
1216
+ With html-to-markdown older than 3.18 installed, robotcode results log showed
1217
+ the screenshot messages of SeleniumLibrary and Browser as empty lines, and
1218
+ --extract left its directory empty. Such versions are now ignored in favour of
1219
+ the built-in converter, and the html extra requires html-to-markdown 3.18.
1220
+
987
1221
  - Discover tests without a line number ([9f3077d](https://github.com/robotcodedev/robotcode/commit/9f3077d8adb868db8bbcb1dc34a08b6a0cfad275))
988
1222
 
989
1223
  `robotcode discover` no longer fails as a whole when a custom parser or
@@ -1046,6 +1280,10 @@ All notable changes to this project will be documented in this file. See [conven
1046
1280
 
1047
1281
  #### VS Code
1048
1282
 
1283
+ - Shorten the description of the Documentation Viewer's openLocation setting ([db4a080](https://github.com/robotcodedev/robotcode/commit/db4a080e7b975c468b2daa94f61a83225ae47c19))
1284
+
1285
+ It now only says where a new viewer opens: beside the active editor or in the active editor group.
1286
+
1049
1287
  - Fill the Keywords view once the language server has started ([599ad73](https://github.com/robotcodedev/robotcode/commit/599ad73808c54bc7ddf77703acd7d831316004fc))
1050
1288
 
1051
1289
  When VS Code restores an open Robot Framework file at startup, the Keywords
@@ -1253,6 +1491,10 @@ All notable changes to this project will be documented in this file. See [conven
1253
1491
 
1254
1492
  #### REPL
1255
1493
 
1494
+ - Design the native REPL and notebooks ([6929f4c](https://github.com/robotcodedev/robotcode/commit/6929f4c81d454abdfc33cd3dd83c60052ea88920))
1495
+
1496
+ dev-docs/repl-and-notebooks.md collects the decisions for a Robot Framework REPL in VS Code's Interactive Window and for notebooks, the execution layer they share with robotcode repl, the facts they rest on and the open questions. It gets cut into OpenSpec changes later.
1497
+
1256
1498
  - Correct the REPL and robot-debug guides ([e794706](https://github.com/robotcodedev/robotcode/commit/e794706e5b7c07155cfa33bcb83d8ed5c4f186a5))
1257
1499
 
1258
1500
  Corrects the dot-command prefixes, the flags only `robotcode repl` has, several prompt features of both backends, the example outputs, that `-l` needs `-o`, and where `--stop-on-entry` stops.
@@ -1307,6 +1549,14 @@ All notable changes to this project will be documented in this file. See [conven
1307
1549
 
1308
1550
  #### VS Code
1309
1551
 
1552
+ - Show the Documentation Bookmarks view in the guide ([e6fc968](https://github.com/robotcodedev/robotcode/commit/e6fc968841a1587c83164baa2cb169dfd75cee8a))
1553
+
1554
+ The page Documentation Viewer shows the view in the Explorer, with its groups and buttons, beside a viewer at the selected bookmark.
1555
+
1556
+ - List the new commands of the Documentation Viewer and retake its media ([fe31be3](https://github.com/robotcodedev/robotcode/commit/fe31be3bc6e65856d6476006d66fe704352f2f4e))
1557
+
1558
+ The command table of the overview lists Show Documentation Viewer and Reset Documentation Bookmarks. The screenshot and the recording of the Documentation Viewer show the star of the bookmarks, the place in the target field and the new icon of New Documentation Viewer.
1559
+
1310
1560
  - Describe the button for a new Documentation Viewer ([35a20c0](https://github.com/robotcodedev/robotcode/commit/35a20c0ecf37c56934c63ae51d2eaac2d22eca84))
1311
1561
 
1312
1562
  The guide and the command table use the renamed commands, the guide describes
@@ -1361,6 +1611,56 @@ All notable changes to this project will be documented in this file. See [conven
1361
1611
 
1362
1612
  #### Website
1363
1613
 
1614
+ - Show the documentation bookmarks in the v2.8.0 release notes ([018fb51](https://github.com/robotcodedev/robotcode/commit/018fb511faeb37854801d59d69f96ff28db7e7ff))
1615
+
1616
+ The post now presents the Documentation Bookmarks view with a screenshot,
1617
+ gives PyCharm a longer entry higher up in the highlights and shortens the
1618
+ breaking change for profile names that select no profile.
1619
+
1620
+ - Let the spiders ask for a poke during the Halloween season ([a548ae1](https://github.com/robotcodedev/robotcode/commit/a548ae17fa6723861a9129f2de0f8711ff5658d2))
1621
+
1622
+ During the Halloween season a spider of the home page or a news page now
1623
+ and then says "Trick or treat? Poke me!" in a speech bubble, so that
1624
+ visitors find the RobotCode tips that clicked creatures leave as treats.
1625
+ The spiders take turns and stop asking once the visitor has got a treat.
1626
+
1627
+ - Add the v2.8.0 release notes ([2717523](https://github.com/robotcodedev/robotcode/commit/27175235ef39fd707beb39606dad42e609f9b4e8))
1628
+
1629
+ Announce the Robot Framework 7.5 support, the Documentation Viewer, the
1630
+ Python environments in VS Code, the biggest update of the PyCharm plugin
1631
+ and the new website, with screenshots of the new features.
1632
+
1633
+ - Link the contribution guide and the dev builds on Support & Contribute ([5cb2af5](https://github.com/robotcodedev/robotcode/commit/5cb2af59e975c94601f4c8199d778ec20338d5e3))
1634
+
1635
+ The page now points contributors to CONTRIBUTING.md and testers to the page about the dev builds.
1636
+
1637
+ - Add nine posters to the Halloween gallery of the home page ([6cd6d52](https://github.com/robotcodedev/robotcode/commit/6cd6d52d8a73efacfa3b32dfe795e08bc485e4a2))
1638
+
1639
+ During the Halloween season the gallery of the home page shows nine new posters, from The Suite to A Nightmare on CI Street; the poster after Nosferatu (2024) is gone.
1640
+
1641
+ - Describe what happens when a profile name selects no profile ([aaa65fb](https://github.com/robotcodedev/robotcode/commit/aaa65fb61fa08d43cfcec6fecc93b9b74690a10e))
1642
+
1643
+ The robot.toml troubleshooting page and the VS Code and PyCharm guides say when such a name stops a command, what the language server shows, and how the editors report a name of their selection.
1644
+
1645
+ - Describe how results log --extract resolves links and names files ([39eafe7](https://github.com/robotcodedev/robotcode/commit/39eafe7f5698b54965a0313893d84ab4cb3b2bd8))
1646
+
1647
+ The --extract section now says how encoded names, file: links, folders,
1648
+ videos and repeated references are handled, and that an embedded file keeps
1649
+ the name from its download attribute.
1650
+
1651
+ - Say that the PyCharm preview shows report and log in the IDE's theme ([10b6537](https://github.com/robotcodedev/robotcode/commit/10b6537875cbc61cb3e88b585d36f7560122b756))
1652
+
1653
+ The page on running tests says that the preview shows the report and the
1654
+ log in PyCharm's theme, follows a change of it, and keeps the theme chosen
1655
+ with the page's own switch until PyCharm's theme changes.
1656
+
1657
+ - Say that PyCharm completes robot.toml and highlights robot code blocks ([5b11695](https://github.com/robotcodedev/robotcode/commit/5b116950b7994d1e8ab54778606499fec9e8689d))
1658
+
1659
+ The configuration pages say that PyCharm completes robot.toml and
1660
+ .robot.toml without further setup, and the comparison with VS Code gets
1661
+ rows for the completion in robot.toml and for Robot Framework code blocks
1662
+ in Markdown.
1663
+
1364
1664
  - Say which module's interpreter RobotCode uses in PyCharm ([978fd75](https://github.com/robotcodedev/robotcode/commit/978fd75e5bec2bb9967d1694565e2b314843cdd1))
1365
1665
 
1366
1666
  The PyCharm guide now says that RobotCode takes the interpreter of the module
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: robotcode
3
- Version: 2.8.0-dev.677
3
+ Version: 2.9.0-dev.68
4
4
  Summary: Command line interface for RobotCode
5
5
  Project-URL: Homepage, https://robotcode.io
6
6
  Project-URL: Donate, https://opencollective.com/robotcode
@@ -34,35 +34,35 @@ Classifier: Topic :: Text Editors :: Integrated Development Environments (IDE)
34
34
  Classifier: Topic :: Utilities
35
35
  Classifier: Typing :: Typed
36
36
  Requires-Python: >=3.10
37
- Requires-Dist: robotcode-core==2.8.0-dev.677
38
- Requires-Dist: robotcode-plugin==2.8.0-dev.677
39
- Requires-Dist: robotcode-robot==2.8.0-dev.677
37
+ Requires-Dist: robotcode-core==2.9.0-dev.68
38
+ Requires-Dist: robotcode-plugin==2.9.0-dev.68
39
+ Requires-Dist: robotcode-robot==2.9.0-dev.68
40
40
  Provides-Extra: all
41
41
  Requires-Dist: docutils; extra == 'all'
42
42
  Requires-Dist: pyyaml>=5.4; extra == 'all'
43
- Requires-Dist: robotcode-analyze==2.8.0-dev.677; extra == 'all'
44
- Requires-Dist: robotcode-debugger==2.8.0-dev.677; extra == 'all'
45
- Requires-Dist: robotcode-language-server==2.8.0-dev.677; extra == 'all'
46
- Requires-Dist: robotcode-repl-server==2.8.0-dev.677; extra == 'all'
47
- Requires-Dist: robotcode-repl==2.8.0-dev.677; extra == 'all'
48
- Requires-Dist: robotcode-runner==2.8.0-dev.677; extra == 'all'
43
+ Requires-Dist: robotcode-analyze==2.9.0-dev.68; extra == 'all'
44
+ Requires-Dist: robotcode-debugger==2.9.0-dev.68; extra == 'all'
45
+ Requires-Dist: robotcode-language-server==2.9.0-dev.68; extra == 'all'
46
+ Requires-Dist: robotcode-repl-server==2.9.0-dev.68; extra == 'all'
47
+ Requires-Dist: robotcode-repl==2.9.0-dev.68; extra == 'all'
48
+ Requires-Dist: robotcode-runner==2.9.0-dev.68; extra == 'all'
49
49
  Requires-Dist: robotframework-robocop>=6.0.0; extra == 'all'
50
50
  Provides-Extra: analyze
51
- Requires-Dist: robotcode-analyze==2.8.0-dev.677; extra == 'analyze'
51
+ Requires-Dist: robotcode-analyze==2.9.0-dev.68; extra == 'analyze'
52
52
  Provides-Extra: debugger
53
- Requires-Dist: robotcode-debugger==2.8.0-dev.677; extra == 'debugger'
53
+ Requires-Dist: robotcode-debugger==2.9.0-dev.68; extra == 'debugger'
54
54
  Provides-Extra: languageserver
55
- Requires-Dist: robotcode-language-server==2.8.0-dev.677; extra == 'languageserver'
55
+ Requires-Dist: robotcode-language-server==2.9.0-dev.68; extra == 'languageserver'
56
56
  Provides-Extra: lint
57
57
  Requires-Dist: robotframework-robocop>=2.0.0; extra == 'lint'
58
58
  Provides-Extra: repl
59
- Requires-Dist: robotcode-repl==2.8.0-dev.677; extra == 'repl'
59
+ Requires-Dist: robotcode-repl==2.9.0-dev.68; extra == 'repl'
60
60
  Provides-Extra: replserver
61
- Requires-Dist: robotcode-repl-server==2.8.0-dev.677; extra == 'replserver'
61
+ Requires-Dist: robotcode-repl-server==2.9.0-dev.68; extra == 'replserver'
62
62
  Provides-Extra: rest
63
63
  Requires-Dist: docutils; extra == 'rest'
64
64
  Provides-Extra: runner
65
- Requires-Dist: robotcode-runner==2.8.0-dev.677; extra == 'runner'
65
+ Requires-Dist: robotcode-runner==2.9.0-dev.68; extra == 'runner'
66
66
  Provides-Extra: yaml
67
67
  Requires-Dist: pyyaml>=5.4; extra == 'yaml'
68
68
  Description-Content-Type: text/markdown
@@ -185,7 +185,7 @@ For CI pipelines, the command line, or LSP-compatible editors like Neovim, Subli
185
185
  pip install "robotcode[runner,analyze]"
186
186
  ```
187
187
 
188
- Pick the extras that match your use case — see the [CLI reference](https://robotcode.io/reference/cli/) for the available packages and how to install them.
188
+ Pick the extras that match your use case — see [Get Started on the Command Line](https://robotcode.io/getting-started/command-line/) for the commands each extra brings, installing with pip or uv and a first run, and the [CLI reference](https://robotcode.io/reference/cli/) for every command and option.
189
189
 
190
190
 
191
191
  ## Documentation
@@ -193,7 +193,7 @@ Pick the extras that match your use case — see the [CLI reference](https://rob
193
193
  For detailed instructions, visit our **[official documentation](https://robotcode.io)**. Additional resources:
194
194
 
195
195
  - **[Q&A](https://github.com/robotcodedev/robotcode/discussions/categories/q-a):** Answers to common questions about RobotCode.
196
- - **[Guides](https://robotcode.io/guides/):** How to use RobotCode's commands and set up projects, plus common pitfalls and editor customization.
196
+ - **[Guides](https://robotcode.io/guides/):** How to work with RobotCode in VS Code, in PyCharm and on the command line, how to set up projects with `robot.toml`, and tips for Robot Framework code.
197
197
  - **[Command Line Tools Reference](https://robotcode.io/reference/cli/):** Comprehensive documentation on using RobotCode's CLI tools.
198
198
  - **[Changelog](https://github.com/robotcodedev/robotcode/blob/main/CHANGELOG.md):** Track changes, updates, and new features in each release.
199
199
  - **[Support & Contribute](https://robotcode.io/contributing/):** Ways to back the project — financial, code, feedback.
@@ -116,7 +116,7 @@ For CI pipelines, the command line, or LSP-compatible editors like Neovim, Subli
116
116
  pip install "robotcode[runner,analyze]"
117
117
  ```
118
118
 
119
- Pick the extras that match your use case — see the [CLI reference](https://robotcode.io/reference/cli/) for the available packages and how to install them.
119
+ Pick the extras that match your use case — see [Get Started on the Command Line](https://robotcode.io/getting-started/command-line/) for the commands each extra brings, installing with pip or uv and a first run, and the [CLI reference](https://robotcode.io/reference/cli/) for every command and option.
120
120
 
121
121
 
122
122
  ## Documentation
@@ -124,7 +124,7 @@ Pick the extras that match your use case — see the [CLI reference](https://rob
124
124
  For detailed instructions, visit our **[official documentation](https://robotcode.io)**. Additional resources:
125
125
 
126
126
  - **[Q&A](https://github.com/robotcodedev/robotcode/discussions/categories/q-a):** Answers to common questions about RobotCode.
127
- - **[Guides](https://robotcode.io/guides/):** How to use RobotCode's commands and set up projects, plus common pitfalls and editor customization.
127
+ - **[Guides](https://robotcode.io/guides/):** How to work with RobotCode in VS Code, in PyCharm and on the command line, how to set up projects with `robot.toml`, and tips for Robot Framework code.
128
128
  - **[Command Line Tools Reference](https://robotcode.io/reference/cli/):** Comprehensive documentation on using RobotCode's CLI tools.
129
129
  - **[Changelog](https://github.com/robotcodedev/robotcode/blob/main/CHANGELOG.md):** Track changes, updates, and new features in each release.
130
130
  - **[Support & Contribute](https://robotcode.io/contributing/):** Ways to back the project — financial, code, feedback.
@@ -203,6 +203,9 @@ get-release-version = ["python scripts/get_release_version.py"]
203
203
  bump = ["cz bump {args}"]
204
204
  install-bundled-editable = "python ./scripts/install_bundled_editable.py"
205
205
  sync-chat-plugin = ["python scripts/sync_chat_plugin.py {args}"]
206
+ check-chat-plugin-release = ["python scripts/chat_plugin_release.py check {args}"]
207
+ prepare-chat-plugin-release = ["python scripts/chat_plugin_release.py prepare {args}"]
208
+ verify-chat-plugin-release = ["python scripts/chat_plugin_release.py verify-published {args}"]
206
209
 
207
210
 
208
211
  [envs.hatch-static-analysis]
@@ -49,26 +49,26 @@ classifiers = [
49
49
  "Framework :: Robot Framework :: Tool",
50
50
  ]
51
51
  requires-python = ">=3.10"
52
- dependencies = ["robotcode-core==2.8.0-dev.677", "robotcode-plugin==2.8.0-dev.677", "robotcode-robot==2.8.0-dev.677"]
52
+ dependencies = ["robotcode-core==2.9.0-dev.68", "robotcode-plugin==2.9.0-dev.68", "robotcode-robot==2.9.0-dev.68"]
53
53
  dynamic = ["version"]
54
54
 
55
55
  [project.optional-dependencies]
56
- debugger = ["robotcode-debugger==2.8.0-dev.677"]
57
- languageserver = ["robotcode-language-server==2.8.0-dev.677"]
58
- runner = ["robotcode-runner==2.8.0-dev.677"]
59
- analyze = ["robotcode-analyze==2.8.0-dev.677"]
56
+ debugger = ["robotcode-debugger==2.9.0-dev.68"]
57
+ languageserver = ["robotcode-language-server==2.9.0-dev.68"]
58
+ runner = ["robotcode-runner==2.9.0-dev.68"]
59
+ analyze = ["robotcode-analyze==2.9.0-dev.68"]
60
60
  yaml = ["PyYAML>=5.4"]
61
61
  lint = ["robotframework-robocop>=2.0.0"]
62
62
  rest = ["docutils"]
63
- repl = ["robotcode-repl==2.8.0-dev.677"]
64
- replserver = ["robotcode-repl-server==2.8.0-dev.677"]
63
+ repl = ["robotcode-repl==2.9.0-dev.68"]
64
+ replserver = ["robotcode-repl-server==2.9.0-dev.68"]
65
65
  all = [
66
- "robotcode-debugger==2.8.0-dev.677",
67
- "robotcode-language-server==2.8.0-dev.677",
68
- "robotcode-runner==2.8.0-dev.677",
69
- "robotcode-analyze==2.8.0-dev.677",
70
- "robotcode-repl==2.8.0-dev.677",
71
- "robotcode-repl-server==2.8.0-dev.677",
66
+ "robotcode-debugger==2.9.0-dev.68",
67
+ "robotcode-language-server==2.9.0-dev.68",
68
+ "robotcode-runner==2.9.0-dev.68",
69
+ "robotcode-analyze==2.9.0-dev.68",
70
+ "robotcode-repl==2.9.0-dev.68",
71
+ "robotcode-repl-server==2.9.0-dev.68",
72
72
  "PyYAML>=5.4",
73
73
  "robotframework-robocop>=6.0.0",
74
74
  "docutils"
@@ -84,7 +84,7 @@ repl = ["robotcode-repl"]
84
84
  yaml = ["PyYAML>=5.4"]
85
85
  lint = ["robotframework-robocop>=6.0.0"]
86
86
  rest = ["docutils"]
87
- html = ["html-to-markdown>=2.0"]
87
+ html = ["html-to-markdown>=3.18"]
88
88
  all = [
89
89
  { "include-group" = "debugger" },
90
90
  { "include-group" = "languageserver" },
@@ -358,11 +358,13 @@ changelog_merge_prerelease = true
358
358
  gpg_sign = true
359
359
  annotated_tag = true
360
360
  pre_bump_hooks = [
361
+ "hatch run build:check-chat-plugin-release",
361
362
  "hatch env remove lint",
362
363
  "hatch run build:update-git-versions",
363
364
  "hatch run build:update-changelog",
364
365
  "git add .",
365
366
  ]
367
+ post_bump_hooks = ["hatch run build:prepare-chat-plugin-release"]
366
368
 
367
369
 
368
370
  [tool.robotcode-analyze.extend-modifiers]
@@ -2,11 +2,8 @@ import json
2
2
  import logging
3
3
  import logging.config
4
4
  import os
5
- import shlex
6
- import subprocess
7
- import sys
8
5
  from pathlib import Path
9
- from typing import IO, Any, List, Literal, Optional
6
+ from typing import IO, Any, List, Literal, Mapping, Optional
10
7
 
11
8
  import click
12
9
 
@@ -17,12 +14,13 @@ from robotcode.plugin import (
17
14
  ColoredOutput,
18
15
  OutputFormat,
19
16
  pass_application,
17
+ show_error,
20
18
  )
21
19
  from robotcode.plugin._agent_detection import is_running_in_ai_agent
22
20
  from robotcode.plugin.click_helper.aliases import AliasedGroup
23
21
  from robotcode.plugin.click_helper.exit_codes import has_robot_exit_codes
24
22
  from robotcode.plugin.click_helper.types import EnumChoice
25
- from robotcode.plugin.click_helper.wrappable import WRAPPER_APPLIED_ENV, is_wrappable
23
+ from robotcode.plugin.click_helper.wrappable import WRAPPER_APPLIED_ENV, invoked_command_is_wrappable, is_wrappable
26
24
  from robotcode.plugin.manager import PluginManager
27
25
 
28
26
  from .__version__ import __version__
@@ -51,125 +49,77 @@ class RobotCodeFormatter(logging.Formatter):
51
49
  super().__init__(*args, defaults=defaults, **kwargs)
52
50
 
53
51
 
54
- def _maybe_reexec_under_wrapper(
55
- ctx: click.Context, app: Application, cli_wrapper: Optional[str] = None, no_wrapper: bool = False
56
- ) -> None:
57
- """Re-execute this process through a configured ``wrapper`` command.
58
-
59
- When a ``wrapper`` is configured - either via ``--wrapper`` on the command
60
- line (``cli_wrapper``) or the selected profile's ``wrapper`` (e.g. to run
61
- the tests inside a specific X11/Wayland session) - and the invoked command
62
- is ``@wrappable`` (i.e. it executes Robot Framework), the process
63
- re-executes itself **once** through that command before Robot Framework
64
- starts. ``--wrapper`` overrides the profile; ``--no-wrapper`` disables
65
- wrapping for this run. The guard env var prevents infinite recursion and
66
- lets an outer layer suppress the re-exec by setting it itself.
52
+ def _warn_about_ignored_wrapper(ctx: click.Context, app: Application) -> None:
53
+ """Warn about a ``--wrapper`` that does not apply.
54
+
55
+ The command itself starts robotcode under the ``wrapper``, once it has loaded its
56
+ configuration (see `robotcode.plugin.click_helper.wrappable.run_under_wrapper`).
67
57
  """
68
- if no_wrapper:
69
- if cli_wrapper:
58
+ if app.config.no_wrapper:
59
+ if app.config.wrapper:
70
60
  app.warning("Ignoring --wrapper because --no-wrapper was given.")
71
61
  return
72
- if os.environ.get(WRAPPER_APPLIED_ENV):
62
+ if not app.config.wrapper or os.environ.get(WRAPPER_APPLIED_ENV) or not ctx.invoked_subcommand:
73
63
  return
64
+ if not invoked_command_is_wrappable(ctx):
65
+ app.warning(f"Ignoring --wrapper: '{ctx.invoked_subcommand}' does not execute Robot Framework.")
74
66
 
75
- sub_name = ctx.invoked_subcommand
76
- if not sub_name:
77
- return
78
- # The command itself opts in via @wrappable; aliases resolve to the same
79
- # command object, so this is alias-safe and needs no central name list.
80
- sub_cmd = ctx.command.get_command(ctx, sub_name) if isinstance(ctx.command, click.Group) else None
81
- if sub_cmd is None or not is_wrappable(sub_cmd):
82
- if cli_wrapper:
83
- app.warning(f"Ignoring --wrapper: '{sub_name}' does not execute Robot Framework.")
84
- return
85
67
 
86
- from robotcode.robot.config.loader import load_robot_config_from_path
87
- from robotcode.robot.config.utils import get_config_files
88
-
89
- profile_wrapper = None
90
- try:
91
- config_files, _, _ = get_config_files(
92
- config_files=app.config.config_files,
93
- root_folder=app.config.root,
94
- no_vcs=app.config.no_vcs,
95
- verbose_callback=app.verbose,
96
- )
97
- # `evaluated_with_env` also applies the profile's `env` to `os.environ`,
98
- # so the wrapper command can rely on it. Profile errors are swallowed
99
- # here: the command loads the config again and reports them, so they
100
- # show up once. (Without a callback they would raise, and an unknown
101
- # profile would make us skip the wrapper of a valid one.)
102
- profile = (
103
- load_robot_config_from_path(*config_files, verbose_callback=app.verbose)
104
- .combine_profiles(*(app.config.profiles or []), verbose_callback=app.verbose, error_callback=lambda _: None)
105
- .evaluated_with_env(verbose_callback=app.verbose, error_callback=lambda _: None)
106
- )
107
- profile_wrapper = profile.wrapper
108
- except Exception as e:
109
- # Don't fail early on config problems here; the actual command loads the
110
- # config again and reports errors properly. An explicit --wrapper is
111
- # still honored below.
112
- message = str(e)
113
- app.verbose(lambda: f"Skipping profile wrapper detection: {message}")
114
-
115
- # `--wrapper` overrides the profile's `wrapper`. The evaluated profile turns
116
- # StringExpression entries into plain strings.
117
- if cli_wrapper:
118
- wrapper = shlex.split(cli_wrapper)
119
- elif profile_wrapper:
120
- wrapper = [str(w) for w in profile_wrapper]
68
+ def _set_output_options(app: Application, color: Optional[bool], pager: Optional[bool]) -> None:
69
+ """Set the colour and pager choice of `app` from `--color/--no-color` and `--pager/--no-pager`."""
70
+ if color is None:
71
+ app.config.colored_output = ColoredOutput.AUTO
72
+ elif color:
73
+ app.config.colored_output = ColoredOutput.YES
121
74
  else:
122
- return
75
+ app.config.colored_output = ColoredOutput.NO
76
+ app.config.pager = pager
123
77
 
124
- # A dry run must not start the wrapper: it would set up and tear down the
125
- # real environment. Show it instead; the command itself then prints its own
126
- # dry-run output.
127
- if app.config.dry:
128
- app.echo(f"Dry run, not executing the wrapper. Would run robotcode under: {' '.join(wrapper)}")
129
- return
78
+ # AI-agent auto-detect: when running inside a known agent session
79
+ # (Claude Code, Copilot, OpenCode, …) demote colour and pager
80
+ # defaults so the agent's stdout capture stays clean. Explicit CLI
81
+ # flags and `NO_COLOR` / `FORCE_COLOR` keep their precedence.
82
+ if is_running_in_ai_agent():
83
+ if color is None and not os.environ.get("NO_COLOR") and not os.environ.get("FORCE_COLOR"):
84
+ app.config.colored_output = ColoredOutput.NO
85
+ if pager is None:
86
+ app.config.pager = False
130
87
 
131
- # Rebuild the invocation the way this process was actually started, so the
132
- # re-exec finds robotcode even when it runs from a bundled path (VS Code) and
133
- # is not installed in the interpreter. `launcher_script` is set only when we
134
- # were started through a bundled entry (its `__main__` sets it) or an explicit
135
- # `--launcher-script`; otherwise robotcode is importable directly and
136
- # `-m robotcode.cli` is correct. We deliberately do NOT consult the
137
- # ROBOTCODE_BUNDLED_ROBOTCODE_MAIN env var: VS Code sets it in every terminal,
138
- # so a directly started robotcode would be diverted to the bundled copy.
139
- # Mirrors the debug launcher's `debugger_script` handling.
140
- entry = [str(app.config.launcher_script)] if app.config.launcher_script else ["-m", "robotcode.cli"]
141
- command = [*wrapper, sys.executable, *entry, *sys.argv[1:]]
142
- app.verbose(lambda: "Running under wrapper: " + " ".join(command))
143
-
144
- # Run robotcode again under the wrapper; the guard env stops the spawned
145
- # robotcode from wrapping a second time. On POSIX we replace this process with
146
- # execvp (no extra process); Windows has no such exec, so there we spawn the
147
- # command, wait, and forward its exit code.
148
- os.environ[WRAPPER_APPLIED_ENV] = "1"
149
- try:
150
- if sys.platform == "win32":
151
- sys.exit(subprocess.run(command).returncode)
152
- os.execvp(command[0], command)
153
- except OSError as e:
154
- raise click.ClickException(f"Failed to execute wrapper command {wrapper!r}: {e}") from e
155
-
156
-
157
- class RobotDataError(click.ClickException):
158
- """An error robotcode reports itself for a command that passes on Robot Framework's
159
- exit codes.
160
88
 
161
- Shows the original error unchanged, but exits with Robot Framework's code for invalid
162
- data or command line options instead of Click's 1 or 2.
163
- """
89
+ def _application_for(params: Mapping[str, Any]) -> Application:
90
+ """An `Application` for an error that comes before the root command has set one up,
91
+ set up from robotcode's own options `params` as far as they are known."""
92
+ app = Application()
93
+ _set_output_options(app, params.get("color"), params.get("pager"))
94
+ return app
95
+
164
96
 
165
- exit_code = 252
97
+ class RobotCodeError(click.ClickException):
98
+ """An error that stops a robotcode command, written as robotcode writes the errors it
99
+ reports (`robotcode.plugin.show_error`). Keeps the exit code of the error."""
166
100
 
167
- def __init__(self, error: click.ClickException) -> None:
101
+ def __init__(self, error: click.ClickException, app: Application) -> None:
168
102
  super().__init__(error.message)
169
103
  self.error = error
104
+ self.app = app
105
+ # click declares the exit code on the class; this one is the code of the error
106
+ self.exit_code = error.exit_code # type: ignore[misc]
170
107
 
171
108
  def show(self, file: Optional[IO[Any]] = None) -> None:
172
- self.error.show(file)
109
+ show_error(self.app, self.error, file)
110
+
111
+
112
+ class RobotDataError(RobotCodeError):
113
+ """An error robotcode reports itself for a command that passes on Robot Framework's
114
+ exit codes.
115
+
116
+ Exits with Robot Framework's code for invalid data or command line options instead of
117
+ Click's 1 or 2.
118
+ """
119
+
120
+ def __init__(self, error: click.ClickException, app: Application) -> None:
121
+ super().__init__(error, app)
122
+ self.exit_code = 252 # type: ignore[misc]
173
123
 
174
124
 
175
125
  class RobotCodeGroup(AliasedGroup):
@@ -182,15 +132,40 @@ class RobotCodeGroup(AliasedGroup):
182
132
  invalid option - exits with Robot Framework's 252 instead. Robot Framework's own exit
183
133
  codes never arrive as Click errors, so they pass through unchanged, and so does any
184
134
  other code.
135
+
136
+ Every Click error of a command or of the group's own options is written as
137
+ `[ ERROR ] <message>`, with the `Application` of the command. An error that comes
138
+ before the root command has set it up - a command name that does not exist or is
139
+ missing, an invalid option of robotcode itself - gets one set up from robotcode's own
140
+ options, so that `--no-color` and AI-agent sessions apply to it too.
185
141
  """
186
142
 
143
+ def make_context(
144
+ self, info_name: Optional[str], args: List[str], parent: Optional[click.Context] = None, **extra: Any
145
+ ) -> click.Context:
146
+ # Click's parser takes the arguments out of the list it gets
147
+ command_line = list(args)
148
+ try:
149
+ return super().make_context(info_name, args, parent, **extra)
150
+ except click.ClickException as e:
151
+ # Click stops at an invalid option before it takes any value; read robotcode's
152
+ # own options again as Click's shell completion does, without errors or
153
+ # callbacks, passing over unknown options
154
+ lenient = {**extra, "resilient_parsing": True, "ignore_unknown_options": True}
155
+ try:
156
+ params = super().make_context(info_name, command_line, parent, **lenient).params
157
+ except click.ClickException:
158
+ params = {}
159
+ raise RobotCodeError(e, _application_for(params)) from e
160
+
187
161
  def invoke(self, ctx: click.Context) -> Any:
188
162
  try:
189
163
  return super().invoke(ctx)
190
164
  except click.ClickException as e:
165
+ app = ctx.find_object(Application) or _application_for(ctx.params)
191
166
  if e.exit_code in (1, 2) and self._passes_on_robot_exit_codes(ctx):
192
- raise RobotDataError(e) from e
193
- raise
167
+ raise RobotDataError(e, app) from e
168
+ raise RobotCodeError(e, app) from e
194
169
 
195
170
  def _passes_on_robot_exit_codes(self, ctx: click.Context) -> bool:
196
171
  name = ctx.invoked_subcommand
@@ -443,31 +418,17 @@ def robotcode(
443
418
  app.config.root = root
444
419
  app.config.no_vcs = no_vcs
445
420
 
446
- if color is None:
447
- app.config.colored_output = ColoredOutput.AUTO
448
- elif color:
449
- app.config.colored_output = ColoredOutput.YES
450
- else:
451
- app.config.colored_output = ColoredOutput.NO
452
- app.config.pager = pager
453
-
454
- # AI-agent auto-detect: when running inside a known agent session
455
- # (Claude Code, Copilot, OpenCode, …) demote colour and pager
456
- # defaults so the agent's stdout capture stays clean. Explicit CLI
457
- # flags and `NO_COLOR` / `FORCE_COLOR` keep their precedence.
458
- if is_running_in_ai_agent():
459
- if color is None and not os.environ.get("NO_COLOR") and not os.environ.get("FORCE_COLOR"):
460
- app.config.colored_output = ColoredOutput.NO
461
- if pager is None:
462
- app.config.pager = False
421
+ _set_output_options(app, color, pager)
463
422
  app.config.output_format = format
464
423
  app.config.launcher_script = launcher_script
465
424
  app.config.default_paths = default_path
466
425
  app.config.log_enabled = log
467
426
  app.config.log_level = log_level
468
427
  app.config.log_calls = log_calls
428
+ app.config.wrapper = wrapper
429
+ app.config.no_wrapper = no_wrapper
469
430
 
470
- _maybe_reexec_under_wrapper(ctx, app, wrapper, no_wrapper)
431
+ _warn_about_ignored_wrapper(ctx, app)
471
432
 
472
433
  if log_config:
473
434
  if log_calls:
@@ -0,0 +1 @@
1
+ __version__ = "2.9.0-dev.68"
@@ -13,6 +13,7 @@ from robotcode.robot.config.loader import (
13
13
  DiscoverdBy,
14
14
  load_robot_config_from_path,
15
15
  )
16
+ from robotcode.robot.config.model import UnknownProfile
16
17
  from robotcode.robot.config.utils import get_config_files
17
18
 
18
19
 
@@ -85,8 +86,20 @@ def list(app: Application, paths: List[Path], show_hidden: bool = False, sort_by
85
86
 
86
87
  config = load_robot_config_from_path(*config_files, verbose_callback=app.verbose)
87
88
 
89
+ # the editors fill their profile lists with this command, also when their selection names a profile that is
90
+ # gone, so a name that selects no profile is only reported, and those of the selection are listed for them
91
+ unknown_selected: List[str] = []
92
+
93
+ def report_unknown(unknown: UnknownProfile) -> None:
94
+ app.error(unknown.message)
95
+ if unknown.selected:
96
+ unknown_selected.append(unknown.name)
97
+
88
98
  _, selected_profiles, enabled_names = config.combine_profiles_ex(
89
- *(app.config.profiles or []), verbose_callback=app.verbose, error_callback=app.error
99
+ *(app.config.profiles or []),
100
+ verbose_callback=app.verbose,
101
+ error_callback=app.error,
102
+ unknown_profile_callback=report_unknown,
90
103
  )
91
104
 
92
105
  selected_names = [k for k in selected_profiles.keys()]
@@ -121,6 +134,8 @@ def list(app: Application, paths: List[Path], show_hidden: bool = False, sort_by
121
134
  messages += ["No profiles defined."]
122
135
  if messages:
123
136
  result["messages"] = messages
137
+ if unknown_selected:
138
+ result["unknownSelected"] = unknown_selected
124
139
 
125
140
  if app.config.output_format is None or app.config.output_format == OutputFormat.TEXT:
126
141
  for v in result["profiles"]:
@@ -1 +0,0 @@
1
- __version__ = "2.8.0-dev.677"