Commit Graph

139 Commits

Author SHA1 Message Date
vvzvlad 77c64c4fd9 Merge pull request 'test(infra): coverage-gate + acceptInvitation atomicity + turn-end unit (#324)' (#335) from fix/324-coverage-gate into develop
Reviewed-on: #335
2026-07-04 17:45:46 +03:00
claude code agent 227 f13105333a feat(client): intraline diff highlighting in the suggestion before→after block (#331)
The suggestion block (#315) struck the whole `selection` red and showed the whole
`suggestedText` green, so a one-letter edit (заведем→заведём) highlighted the
entire line. Now only the CHANGED fragments are emphasized intraline, git-style.

Pure, render-only — nothing changes in the DB/backend/MCP/IComment/mutations/
Apply/Badge. New pure `computeSuggestionDiff(old, new) => { old: Segment[], new:
Segment[] }` (Segment = {text, changed}) in suggestion.ts: hybrid word+char —
`diffWordsWithSpace` for the word skeleton, then `diffChars` inside an adjacent
removed+added pair so only the differing letters (not the whole word) are
flagged; a lone insertion/deletion is wholly changed; equal parts are common on
both sides. Concatenating each side reproduces the input (lossless). Wrapped in
`useMemo` on [selection, suggestedText].

comment-list-item.tsx renders per-segment spans instead of two whole <Text>;
changed segments get `.suggestionChanged` (a stronger currentColor tint + bold,
NO text-decoration so the old block's inherited line-through survives on the
changed letters — the whole old line still reads removed, new as added).

`diff@8.0.3` (jsdiff, already in the root package.json) added to
apps/client/package.json (+ lockfile, additive) so the workspace resolves it;
it bundles its own types.

Tests: new suggestion.test.ts (one-letter ё/е; word replacement keeping the
shared word common with no per-letter noise; word insertion/deletion; identical)
— asserts segment text + changed flags, non-vacuous. Two pre-existing
comment-list-item.test assertions switched from getByText (a single text node)
to container.textContent (the new line is now multiple spans) — adapts to the
intended DOM change, not a weakening.

Verified: tsc --noEmit clean; client vitest 892 passed | 1 expected-fail.
Visual/pixel check of the tint at the 390px comment panel needs a human (no
screenshot tooling in-repo).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-04 15:17:07 +03:00
claude code agent 227 baa41d66ad test(infra): coverage-gate + acceptInvitation atomicity int-spec + turn-end unit (#324)
Tail of #244. Three items:

1. Coverage-gate (main). develop had no coverage tooling at all. Added
   @vitest/coverage-v8@4.1.6 (pinned to the vitest already in use) to the three
   vitest packages — git-sync, editor-ext (which also gains its missing direct
   `vitest` devDep), apps/client — and enabled v8 coverage with per-package
   thresholds (no root vitest config exists, so per-package is the only
   meaningful scope). v8 provider is chosen deliberately: istanbul broke on the
   ESM `@docmost/editor-ext` barrel; v8 collects native runtime coverage and
   never re-parses ESM. `enabled: true` wires the gate into the plain `test`
   script, so `pnpm -r test` (the CI entrypoint) enforces it without a manual
   `--coverage`. Thresholds set ~4-5 pts below measured current coverage so the
   gate PASSES today and FAILS on regression (verified: forcing lines=95 on
   editor-ext exits 1). `all: false` — coverage counts test-touched files;
   documented in the configs (with `all: true` the many untested type/barrel
   files would sink the % and make the gate meaningless).
   Measured→threshold (S/B/F/L): git-sync 91.78/79.16/76.76/92.46 → 88/75/72/88;
   editor-ext 58.58/48.1/64.96/58.91 → 54/44/60/54; client 59.93/58/48.47/59.39
   → 55/53/44/55. All exit 0.

2. acceptInvitation atomicity int-spec. New
   apps/server/test/integration/workspace-accept-invitation-atomicity.int-spec.ts
   (+ createDefaultGroup/createInvitation seeders in test/integration/db.ts per
   its convention). Wires the real WorkspaceInvitationService with real
   User/Group/GroupUser repos against the test Kysely, stubbing only the
   post-commit collaborators. Asserts the invariant protected by
   users_email_workspace_id_unique: (a) two CONCURRENT accepts → exactly one
   fulfilled, one BadRequestException('Invitation already accepted'), membership
   count == 1, invitation consumed; (b) repeated sequential accept → still one
   membership; (c) the survivor is in the workspace default group (whole-tx, no
   torn state). Ran against real Postgres+Redis: 3/3 pass.

3. turn-end decision unit test. `decideTurnEnd` does not exist as a symbol; the
   turn-end logic lives in chat-thread.tsx's onFinish handler. Added a focused
   block to the existing chat-thread.test.tsx (matching its hoisted-mock style):
   clean finish → flush queued (continue); abort/disconnect/error → queue
   preserved (end) with the correct notice; parent notified on every terminal
   outcome. 8 passed (3 existing + 5 new).

Verified: git-sync 712, editor-ext 247, client 888 (all with the gate, exit 0);
int-spec 3/3 (real Postgres); tsc --noEmit clean for client + server;
pnpm install --frozen-lockfile consistent (lockfile additive).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-04 12:37:28 +03:00
claude_code aad0a37cfd 0.94.1
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 19:33:57 +03:00
claude_code 378d8b676b 0.94.0
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 18:15:24 +03:00
claude_code 7093f184b2 fix(dictation): self-host Silero VAD / onnxruntime-web assets
Streaming dictation failed at runtime with "no available backend found /
'text/html' is not a valid JavaScript MIME type": @ricky0123/vad-web 0.0.30
defaults baseAssetPath/onnxWASMBasePath to "./" (relative to the page URL),
so the worklet, Silero model and ORT wasm/mjs were requested against the SPA
catch-all and came back as index.html.

Serve them from a fixed /vad/ instead:
- scripts/copy-vad-assets.mjs copies the 4 runtime assets (vad worklet,
  silero_vad_v5.onnx, ort-wasm-simd-threaded.jsep.{mjs,wasm}) from node_modules
  into apps/client/public/vad/ (gitignored — the ORT wasm is ~26 MB)
- client dev/build scripts run the copy first so the assets are always present
- useStreamingDictation points both path constants at "/vad/"

Verified: dev server serves all four under /vad/ with HTTP 200 and correct
Content-Type (js/wasm, never text/html); tsc clean. Prod (Docker) build runs
the copy step, so dist/vad/* ships in the image.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 17:19:11 +03:00
claude_code 4f0da42d88 feat(dictation): streaming STT via silence cut (Silero VAD)
Add a lightweight "streaming" dictation mode as a simpler alternative to the
realtime-websocket path: detect speech with Silero VAD (@ricky0123/vad-web),
cut each segment on a pause and POST it to the existing /ai-chat/transcribe
endpoint, so text appears progressively. No server changes.

- new useStreamingDictation hook (same API as useDictation), lazy-loads VAD,
  in-order seq emission, session-epoch guard against stop->start races
- new encodeWavPcm16 util (Float32 -> mono PCM16 WAV, accepted by the server)
- MicButton gains a `streaming` prop; enabled in the editor toolbar and chat
- VAD tuning: redemptionMs 640 / preSpeechPadMs 320 / minSpeechMs 96
- batch dictation kept as the fallback (streaming=false)
- deps: @ricky0123/vad-web@0.0.30, onnxruntime-web@1.27.0

Note: VAD assets load from the library CDN by default; for self-hosted/offline
set VAD_BASE_ASSET_PATH/VAD_ONNX_WASM_BASE_PATH and copy assets to public/vad/.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 16:52:05 +03:00
claude_code cf29a0fc11 0.93.0 2026-06-20 19:57:37 +03:00
vvzvlad c6b878c514 0.91.0
Bump root, client and server package versions 0.90.1 -> 0.91.0 to match the
v0.91.0 release tag. packages/mcp keeps its independent 1.0.0 version.
2026-06-18 18:07:54 +03:00
vvzvlad 44b340dc1a feat(ai-chat): agent write tools, provenance wiring, chat panel + provider settings UI" -m "Backend:
- Add reversible write tools to the per-user agent toolset (page create/update/
  move/soft-delete; comment reply + resolve), exposed under the user's JWT and
  enforced by Docmost CASL; no permanent/force delete (D3).
- Non-spoofable agent provenance: sign actor/aiChatId into the access and collab
  tokens (TokenService), propagate via jwt.strategy onto the request, and set
  pages.last_updated_source/last_updated_ai_chat_id on REST create/update/move and
  comments.created_source/resolved_source/ai_chat_id.
- packages/mcp: add an optional getCollabToken provider (content-edit provenance)
  and guard against empty tokens; service-account /mcp path unchanged.

Frontend:
- Admin 'AI / Models' settings section: provider/model/embedding/base URL, a
  write-only API key field, system prompt, and Test connection.
- AI chat panel (useChat + DefaultChatTransport): conversation list, streamed
  messages, tool-call action log and page citations; header entry point gated on
  settings.ai.chat.

Compile-verified (server nest build + client tsc/vite); not yet live-tested.
Known gaps: history 'AI agent' badge (C3), vector RAG (D), external MCP (E);
chat tool-card citation links pending a fix.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 02:39:26 +03:00
Philipinho b6760c63c4 fix: package updates 2026-05-28 16:39:47 +01:00
Philipinho 2b68879e72 0.90.1 2026-05-28 16:36:18 +01:00
Philipinho adb1f27767 v0.90.0 2026-05-20 16:55:23 +01:00
Philip Okugbe cea9be7926 feat: table enhancement (#2191) 2026-05-14 00:37:44 +01:00
Philip Okugbe 31ed0df3f7 feat(tree): replace sidebar tree (react-aborist) with custom tree implementation (#2199)
* feat(tree): replace react-arborist with custom tree implementation

* feat(tree): keyboard arrow navigation between rows

* feat(emoji-picker): focus search input on open

* refactor(emoji): switch to @slidoapp/emoji-mart fork for accessibility

* feat(tree): Home/End and typeahead keyboard navigation

* feat(tree): roving tabindex and * to expand sibling subtrees

* feat(tree): Space activation and ARIA refinements

* fix(tree): move treeitem role to focusable row + aria-current
2026-05-13 23:01:04 +01:00
Philip Okugbe bdc369fce0 feat(editor): fixed toolbar preference (#2185)
* feat(editor): fixed toolbar preference

* remove key

* cleanup translation strings

* update axios
2026-05-09 13:27:03 +01:00
Philip Okugbe de60aa7e61 feat: synced blocks (transclusion) (#2163)
* feat: synced blocks (transclusion)

* fix:remove name

* make placeholders smaller

* feat: enforce strict transclusion schema

* fix: scope synced blocks to workspace, gate unsync on edit permission

* fix collab module error
2026-05-08 13:23:16 +01:00
Philipinho 980521f957 v0.80.1 2026-04-27 16:06:32 +01:00
Philipinho 15b8908b1a update postcss 2026-04-27 15:23:47 +01:00
Philipinho 8e15b22d8c package updates 2026-04-27 15:22:02 +01:00
Philipinho a573acedd0 fix: local storage, and package overrides 2026-04-22 14:13:25 +01:00
Philipinho 271f855761 v0.80.0 2026-04-14 17:08:44 +01:00
Philip Okugbe 4056bd0104 feat: enhancements (#2107)
* refactor
* fix
* update packages
2026-04-13 23:34:40 +01:00
Philipinho 4966f9b152 fix(deps): package updates 2026-04-07 10:24:46 +01:00
Philip Okugbe 895c1817ae feat: bug fixes (#2084)
* handle enter in inline code

* fix: duplicate comment cache

* track link nodes (backlinks)

* fix en-US translation

* fix internal a-links

* overrides

* 0.71.1
2026-04-05 13:45:36 +01:00
Philipinho 147d028036 v0.71.0 2026-03-31 20:42:37 +01:00
Philip Okugbe 9aaa6c731c feat: add AI_EMBEDDING_SUPPORTS_MRL env var to decouple pgvector dimensions from model API (#2079)
Some embedding models don't accept a `dimensions` parameter. This adds
an optional env var that controls whether the dimension is sent to the
model API, while always using it for pgvector indexing. Preset models
have this handled automatically; the env var allows explicit override
for custom models.
2026-03-31 19:39:49 +01:00
Philip Okugbe fa4872e89e fix(deps): package updates (#2041)
* update
* overrides
* override
* fix page update mutation
* fix
* cleanup
* loader
* fix excalidraw package
* override
* fix regex
2026-03-25 10:07:01 +00:00
Philipinho cc5c800238 0.70.3 2026-03-17 14:29:09 +00:00
Philipinho 74eddb0638 v0.70.2 2026-03-16 13:49:50 +00:00
Philipinho 1980b94825 0.70.1 2026-03-04 11:57:31 +00:00
Philipinho 9331ac2df8 v0.70.0 2026-03-03 00:13:01 +00:00
Philip Okugbe 60848ea903 feat(ee): mcp (#1976)
* feat: MCP
* sync
* sync
2026-03-01 18:37:39 +00:00
Philip Okugbe 0aeaa43112 feat: replace sharp with client-side icon resize (#1951) 2026-02-16 19:48:19 +00:00
Philipinho 4d43f86c51 update deps 2026-02-11 17:43:13 -08:00
Philip Okugbe f170ede8da fix(deps): override packages (#1936)
* override packages
2026-02-11 16:48:26 -08:00
Philipinho 3a9bdfbb06 fix(deps): update vite and nx 2026-02-09 18:32:09 -08:00
Philipinho ab7999a946 v0.25.3 2026-02-09 18:27:55 -08:00
Philipinho fbb44df548 v0.25.2 2026-02-06 11:32:00 -08:00
Philipinho e0809e7104 v0.25.1 2026-02-04 07:10:13 -08:00
Philipinho 6a0bb8d4cb v0.25.0 2026-02-03 13:18:03 -08:00
Philipinho f32bb298e0 v0.25.0-beta.1 2026-01-30 23:09:01 +00:00
Philip Okugbe 657fdf8cb7 feat: Tiptap V3 migration (#1854)
* Tiptap3 migration - WIP

* fix collaboration

* remove unused code

* fix flicker

* disable duplicate extensions

* update tiptap version

* Switch to useEditorState
- Set shouldRerenderOnTransaction to false

* fix editable state

* add tippyoptions for reference

* merge main

* tiptap 3.6.1

* fix bubble menu

* fix converter

* fix menus

* fix collaboration caret css

* fix: Set `isInitialized` to force immediate react node view rendering

* feat: Migrate tippy.js menus to Floating UI

* feat: Update collaboration connection for HocusPocus v3

* fix: Connect/disconnect websocketProvider

* cleanup

* cleanup

* feat: Improved placeholder and upload handling for images

* feat: Improved placeholder and upload handling for videos

* refactor: Image node and view clean-up

* feat: Improved placeholder and upload handling for attachments

* fix: Video view styles

* fix: Transaction handling on asset upload

* fix: Use imageDimensionsFromStream

* feat: Multiple file upload, improved placeholders, local previews

* fix: Drag & drop, paste upload

* fix: Allow media as attachment

* * add skeleton pulse animation
* add translation strings
* fix attachment view responsiveness

* fix collab connection status display

* Tiptap v3.17.0

* fix suggestion menu exit bug

* fix search shortcut

* fix history editor css

* tiptap 3.17.1

---------

Co-authored-by: Arek Nawo <areknawo@areknawo.com>
2026-01-24 20:41:08 +00:00
Philip Okugbe 183787fa0c fix: update dependencies (#1843) 2026-01-14 16:36:47 +00:00
Philipinho 732951a322 v0.24.1 2025-12-14 13:24:09 +00:00
Philipinho 6af7956889 v0.24.0 2025-12-12 17:15:59 +00:00
Philip Okugbe 9fb16bc842 feat(EE): AI vector search (#1691)
* WIP

* AI module - init

* WIP

* sync

* WIP

* refactor naming

* new columns

* sync

* sync

* fix search bug

* stream response

* WIP

* feat embeddings sync

* refine

* Add workspaceId to page events

* refine

* WIP

* add translation string

* sync

* reset ai answer on query change

* hide AI search in cloud

* capture streaming error

* sync
2025-12-01 11:50:25 +00:00
Philip Okugbe 04a17c9b92 package security updates (#1744)
* package security updates

* package updates
2025-11-29 11:50:20 +00:00
Philip Okugbe 3164b6981c feat: api keys management (EE) (#1665)
* feat: api keys (EE)

* improvements

* fix table

* fix route

* remove token suffix

* api settings

* Fix

* fix

* fix

* fix
2025-10-07 21:05:13 +01:00
Philipinho 3c4cab0d2a v0.23.2 2025-09-18 18:00:28 +01:00