Repository navigation
Conversation
Registers an aiActions service in the plugin context that resolves the available actions for the work package description editor, and ships the rebuilt CKEditor bundle containing the Assistant dropdown, which stays hidden while the action list is empty. Part of the AI-101 editor integration. https://community.openproject.org/work_packages/77784
The AI-100 backend now ships its action list as HAL collections under API v3 (AI-134): one endpoint scoped to an existing work package and one scoped to a project and type for unsaved work packages. The editor service consumes those instead of the earlier plain JSON draft, resolving the project and type from the work package's links. The dropdown plugin in the CKEditor build is unaffected: it still only renders labels. https://community.openproject.org/work_packages/77784
Until AI-137 wires the text transform gateway to the LLM connection, the null gateway reports "not configured" and every action list is empty, so the Assistant dropdown never shows up locally. Setting OPENPROJECT_AI_TEXT_TRANSFORM_ECHO_GATEWAY=true outside production swaps in a gateway that is always ready and streams the submitted text back, which is enough to exercise the dropdown and, later, the run flow. https://community.openproject.org/work_packages/77784
First cut of the execute flow. Selecting an action creates a run through the text transform API, polls it with an adaptive interval until it reaches a terminal status, and replaces the editor content with the completed text through the editor model, so a single undo restores the previous text. The editor is read-only while the run is in flight and a toast reports progress, success or the run's error message. Errors and cancellations never touch the editor content. Diff preview, accept and reject and a cancel control are the follow-up from the AI-101 spec. https://community.openproject.org/work_packages/77784
The text transform port now takes a gateway factory, which the LLM module registers on boot. Its gateway resolves the description assistant through Llm::Runtime, streams the completion with the action's prompt as instructions and the submitted content as the user message, and maps the module's error classes onto the port's reasons. Cancellations and budget errors raised by the consumer pass through untranslated. Without the module the port still falls back to the null gateway, and the echo gateway keeps overriding both for local development. Covers AI-137 ahead of its own ticket so the editor can run against a real model. https://community.openproject.org/work_packages/77784 https://community.openproject.org/work_packages/79470
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9aa3a77ec9
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
The dropdown stays clickable while the editor is read-only, so a second selection used to start another run on the same content and both results raced for the same lock. The service now remembers the editors with an active run and ignores further selections until that run ends. Follow-up from the Codex review of #25770. https://community.openproject.org/work_packages/77784
The gateway factory is a block so that reloading in development resolves the module's current class, and the editor content is replaced through the model because setData would drop the undo history. Both reasons now live here instead of in comments. Follow-up from the Codex review of #25770. https://community.openproject.org/work_packages/77784
Deploying openproject with ⚡ PullPreview
|
The preview environment already enables the feature flags for the text transform actions and the LLM connection. With the two admin toggles on as well, a reviewer only has to connect an LLM server in the preview's administration to see the Assistant dropdown. https://community.openproject.org/work_packages/77784
Settings supplied through the environment are locked in the administration, so forcing the assistant and the LLM features on would have made it impossible to review the switched-off state on a preview. The preview keeps only the feature flags; reviewers switch the two toggles on themselves, as on a fresh installation. This reverts commit 8b338ca. https://community.openproject.org/work_packages/77784
|
Warning Flaky specs
🤖 Ask Copilot to investigateCopy the prompt below into a new comment on this PR to delegate the investigation to GitHub Copilot. It will look into the flakiness and open a separate pull request with you as reviewer. |
|
Warning Flaky specs
🤖 Ask Copilot to investigateCopy the prompt below into a new comment on this PR to delegate the investigation to GitHub Copilot. It will look into the flakiness and open a separate pull request with you as reviewer. |
Updates the CKEditor bundle from commonmark-ckeditor-build to 49.0.0. CKEditor 49 removes the Watchdog. Creates the editor directly and observes errors with onEditorError(). After an error, the editor becomes read-only and keeps the content the user entered, and the message asks the user to copy any text and reload the page. Passes the initial data as config.root.initialData, because v49 deprecates the top-level config.initialData. The bundle loads the legacy theme preset, so the editor keeps its look. Reads --ck-radius-base, because v49 no longer declares --ck-border-radius. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Updates the CKEditor stylesheet, which no longer contains the legacy theme preset. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Fixes the no-explicit-any lint error on the changed line. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The read-only lock only covered CKEditor. The source mode uses a separate CodeMirror instance, which stayed editable. Makes CodeMirror read-only after an error, also when the source mode opens later. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Editor#destroy() returns a promise, so the try/catch did not catch a rejected teardown. Types destroy() as returning a promise and logs a rejection. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…to code-maintenance/ckeditor-49
[OP-20447] Update CKEditor to 49.0.0
…ata-in-wp-auto-completer [DREAM-811] Harmonise user data in WP auto completer
…butehelptext-page-to-primer [OP-20413] Migrate the AttributeHelpText page to Primer
…-package-name-for-column-titles-on-boards [OP-17691] Display full work package name for column titles on boards
…ctions-dropdown Brings in dev up to 2026-10-13, including CKEditor 49 and its new ESM bundle. The vendor bundle is taken from the base here and rebuilt with the Assistant plugin in the following commit.
Bundle built from commonmark-ckeditor-build master (CKEditor 49, esbuild) plus the Assistant plugin branch. Only ckeditor.js and its map change: the stylesheet keeps the refreshed theme that 43bf22d trimmed by hand, which the build repository's style script does not emit yet, and the translations stay as committed. The dropdown now sits on the toolbar element outside the grouped items, so it stays visible at every editor width, and uses the single sparkle icon of the Artificial Intelligence administration section. https://community.openproject.org/work_packages/77784
…ons-dropdown Brings in the CKEditor 49 integration of the core (no Watchdog, ESM bundle loader) that the base stack does not carry yet. The vendor bundle is taken from dev here and rebuilt with the Assistant plugin in the following commit.
Bundle built from commonmark-ckeditor-build master (CKEditor 49, esbuild) plus the Assistant plugin branch, on top of the core's CKEditor 49 integration from dev. Only ckeditor.js and its map change: the stylesheet keeps the refreshed theme that 43bf22d trimmed by hand, which the build repository's style script does not emit yet, and the translations stay as committed. https://community.openproject.org/work_packages/77784
…wn' into feature/ai-101-ai-actions-dropdown
|
Warning Flaky specs
🤖 Ask Copilot to investigateCopy the prompt below into a new comment on this PR to delegate the investigation to GitHub Copilot. It will look into the flakiness and open a separate pull request with you as reviewer. |
The menu at the right end of the toolbar was clipped by the work package pane. Bundle rebuilt from commonmark-ckeditor-build 773478c, which opens the panel towards the toolbar, mirrored for right-to-left languages. https://community.openproject.org/work_packages/77784
|
Warning Flaky specs
🤖 Ask Copilot to investigateCopy the prompt below into a new comment on this PR to delegate the investigation to GitHub Copilot. It will look into the flakiness and open a separate pull request with you as reviewer. |
The CKEditor split button asks the service which action to show. `defaultAction` returns the action that was run last in this browser, remembered in local storage at selection time, and falls back to the first offered action when none was run yet or the remembered one is not offered for this work package. The label is capped at 12em so an admin-defined name cannot push the button out of the toolbar. Rebuilt bundle from opf/commonmark-ckeditor-build 3c22c9f. https://community.openproject.org/wp/AI-101
Ticket
https://community.openproject.org/wp/AI-101
What are you trying to accomplish?
Stacked on #25734, the last PR of the AI-3 stack. First cut of the editor side of the description assistant: an "Assistant" split button in the work package description editor offers the actions the AI-134 endpoints answer with, and picking one runs it through the AI-136 endpoints and puts the result into the editor.
OPAiActionsfor the full editor (paired build-repo PR: [AI-101] Add the AI actions dropdown to the full editor toolbar commonmark-ckeditor-build#131, this PR carries the rebuilt bundle). The plugin only renders the list and reports the selection; it adds nothing while the list is empty and does nothing on cores without theaiActionsservice. The button is a split button at the right end of the toolbar, outside CKEditor's overflow grouping, so it stays visible at every editor width: the main part shows the sparkle Octicon of the Artificial Intelligence administration section next to the name of the action that was run last (the first action until then) and runs that action; the arrow opens the list of all actions.AiActionsServicein the core frontend: resolves the list for an existing work package (/work_packages/:id/ai_text_transform_actions) or, for a new one, through its project and type.defaultActionpicks the action the button shows: the one run last in this browser, kept in local storage, or the first offered one. Running an action creates a run, polls it with theaftercursor until a terminal status, and replaces the editor content with thecompletedtext through the editor model, so a single undo restores the previous text. The editor is read-only meanwhile; toasts report progress, success or the run's error message. Errors and cancellations never touch the text.Llm::TextTransformGatewayinmodules/llm, registered with the text transform port on boot. It resolves:description_assistantthroughLlm::Runtime, streams the completion with the action's prompt as instructions and the submitted text as the user message, and maps the module's errors onto the port's reasons. This covers AI-137 ahead of its own ticket.AI::TextTransforms::EchoGateway, enabled withOPENPROJECT_AI_TEXT_TRANSFORM_ECHO_GATEWAY=trueoutside production, streams the submitted text back so the whole flow can be exercised without a model.Screenshots
The branch also merges
devahead of the stack base, because the rebuilt bundle is a CKEditor 49 build and needs the core's CKEditor 49 integration (#25966); the stack's next forward-merge absorbs that. Onlyckeditor.jsand its map are rebuilt; the stylesheet keeps the refreshed theme trimmed in 43bf22d and the translations stay as committed.What approach did you choose and why?
The plugin is deliberately thin so that iterating on the editor behaviour needs no bundle rebuild; everything dynamic lives in the core service behind the plugin context. Availability stays server-side: an empty list leaves the toolbar untouched, the frontend carries no flag or setting logic. The dropdown is appended to the toolbar element itself and keeps itself behind the overflow menu, since CKEditor's grouping measures the toolbar's last child; a
maxWidthnudge makes the toolbar regroup when the dropdown appears and whenever the shown action, and with it the button width, changes. The label is capped at 12em so an admin-defined action name cannot push the button out of the toolbar.Execution follows the polling contract from AI-136: adaptive 400 to 1000 ms interval, in-flight guard through
await, stop on a terminal status, result built from thecompletedevent rather than concatenated deltas. A client-side deadline of 200 s requests cancellation of a run that never finishes.The result is applied with
model.insertContentover the root range instead ofeditor.setData(), which would drop the undo history. Persisting still happens only through the regular save flow.The port learns about the module's gateway through a factory block set by the module's engine, so core never references module constants and code reloading in development keeps resolving the current class. Without the module the port falls back to the null gateway.
Deliberately not in this first cut, all from the AI-101 spec: diff preview with a clean/diff toggle, accept and reject, a cancel control during the run, progressive rendering of deltas. Known follow-up for the AI-3 stack: RubyLLM sends the instructions as OpenAI's
developerrole becauseLlm::Sessiondoes not setopenai_use_system_role; self-hosted servers may reject that.Merge checklist
Behind the existing flag
ai_text_transform_actionsand settingai_text_transform_actions_enabled, plus the AI-3 flagllm_connectionand settingllm_features_enabledfor the real gateway.On PullPreview only the two flags are on. To see the dropdown there, switch on the AI text transform actions and the LLM features in the administration and connect an LLM server with a chat model on the LLM connection page.