feat(ai-smart-file-tagger-qa): add AI Smart File Tagger#490
Open
LukasHirt wants to merge 16 commits into
Open
Conversation
✅ Snyk checks have passed. No issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
Signed-off-by: Lukas Hirt <info@hirt.cz>
…mposables/useTagSuggestions.ts` (prompt construction, LLM fetch, JSON parse with confidence scores, plain-text fallback, WebDAV tag write via `useClientService`), `src/utils/file-support.ts` (content-extraction eligibility check, MIME helper), and wire `src/index.ts` to read `applicationConfig.llm`, build `llmConfig`, and register the `ActionExtension` on `app.files.quick-actions` (with fallback to `global.files.context-actions` if the extension point is absent). Verify the quick-actions extension point exists in `node_modules/@ownclouders/web-pkg` and confirm an unused dev-server port in the `97XX` range. Signed-off-by: Lukas Hirt <info@hirt.cz>
Signed-off-by: Lukas Hirt <info@hirt.cz>
Signed-off-by: Lukas Hirt <info@hirt.cz>
Signed-off-by: Lukas Hirt <info@hirt.cz>
…ts/TagSuggestionModal.vue`: loading spinner, selectable tag chips (OcTag or OcButton toggle fallback), confidence badges, error banner, confirm/dismiss buttons, and unconfigured-state info message. Wire the modal into the action handler via `useModals().dispatchModal`. Use only ODS components and ownCloud CSS custom properties; wrap all strings in `$pgettext`. Signed-off-by: Lukas Hirt <info@hirt.cz>
…/composables/useTagSuggestions.spec.ts` covering prompt construction (content mode vs name-only mode), structured JSON parse, plain-text fallback, tag application via mocked WebDAV, and error branches (401, 429, network failure). Write `tests/unit/components/TagSuggestionModal.spec.ts` covering loading state, chip rendering, chip toggle, confirm calls `applyTags`, dismiss closes, error banner, and unconfigured tooltip. Signed-off-by: Lukas Hirt <info@hirt.cz>
Signed-off-by: Lukas Hirt <info@hirt.cz>
Signed-off-by: Lukas Hirt <info@hirt.cz>
…on in `tests/e2e/acceptance.spec.ts` with a Playwright smoke test: upload a `.txt` file, click the sparkle quick-action, assert the `TagSuggestionModal` appears with at least one chip, toggle a chip off, confirm, and assert the modal closes. Signed-off-by: Lukas Hirt <info@hirt.cz>
Signed-off-by: Lukas Hirt <info@hirt.cz>
Signed-off-by: Lukas Hirt <info@hirt.cz>
Signed-off-by: Lukas Hirt <info@hirt.cz>
… state sync issues - Fix tag chips rendering as raw JSON/numbered-list text when the LLM ignores the requested response format - Fix selected/unselected chip colors having inverted contrast; tags now default to unselected (opt-in) instead of pre-selected - Replace the modal's custom Dismiss/Apply tags button row with the framework's own modal actions (confirmText + exposed onConfirm) - Add a hint above the chip list explaining the tags must be selected - Sync the resources store after applying tags so the file list/sidebar reflect the new tags without a page refresh - Fix a race in the e2e test that read the chip count before the async suggestion fetch resolved Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Signed-off-by: Lukas Hirt <info@hirt.cz>
Signed-off-by: Lukas Hirt <info@hirt.cz>
…I matrix, and oCIS apps config Signed-off-by: Lukas Hirt <info@hirt.cz>
8c0104a to
6d1c358
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Files accumulate without tags, making search and filter ineffective.
Manual tagging at scale doesn't happen — it requires opening every file individually.
Solution
A sparkle icon appears inline in each file row. Clicking it sends the file's
content (txt/md/pdf) or just its name and type (all others) to the configured
LLM, which returns 3–5 suggested tags shown in a lightweight confirmation
popover. The user accepts, deselects, or dismisses. With structured-output
models, tags include a confidence score; with basic text models, a flat list.
Without a configured LLM, the button shows a tooltip describing the required
admin setup.
Extension points
app.files.quick-actionsWhy ship this now
As oCIS deployments scale, findability suffers first. This is the lowest-friction
path to enriched metadata, meeting users exactly where they already are.
What was built
packages/web-app-ai-smart-file-tagger-qa adds an inline "suggest tags" action to the files app, sending a file's content or name/MIME type to a configured LLM and returning suggested tags for the user to accept or dismiss. Because
app.files.quick-actionsdoesn't exist in the installed@ownclouders/web-pkg(v12.3.2), the action is registered onglobal.files.context-actionsinstead — accessible from the file's context menu rather than as an inline row icon.src/index.tsreadsapplicationConfig.llm, builds the LLM config, and wires theActionExtensionregistration.The core logic lives in
src/composables/useTagSuggestions.ts, which pulls file content over WebDAV for.txt/.md/.pdf(PDF text extraction via pdfjs-dist with a fake worker) and falls back to filename + MIME type for everything else, gated bysrc/utils/file-support.ts. It calls the existinguseLLM.complete()composable with a structured JSON prompt and parses a{ tags: [{ name, confidence }] }response, with a plain-text comma/newline fallback for models that don't support structured output — matching the two-tier degradation already established byweb-app-ai-doc-summary. Accepted tags are applied viaclientService.graphAuthenticated.tags.assignTags().src/components/TagSuggestionModal.vuerenders the suggestion UI: a loading spinner, an unconfigured-LLM notice, toggleableOcTagchips with confidence badges (selection state is tracked via a CSS class since thisOcTagversion has no nativeselectedprop), an error banner, and its own Apply/Dismiss controls since the modal is launched withhideConfirmButton: true.Test coverage includes 36 unit tests across the composable (prompt construction, structured/plain-text parsing, confidence normalization, tag application, and 401/429/network error handling) and the modal component (state rendering, chip toggling, confirm/dismiss behavior), plus a Playwright acceptance spec that mocks the LLM proxy, uploads a test file, triggers the action from the context menu, and verifies the modal's chip rendering, toggle, and confirm-close flow. The acceptance spec and its page object live inside the package rather than shared
support/pages/, per the per-extension page-object convention. A known limitation, documented in the package README, is that tag suggestions surface from the file context menu rather than as an inline quick-action icon, since the originally spec'd extension point isn't available in this web-pkg version.Gate
Effort: S · 🤖 Generated by extctl