Commit Graph

174 Commits

Author SHA1 Message Date
claude code agent 227 dd186406b6 Merge remote-tracking branch 'gitea/develop' into HEAD
# Conflicts:
#	CHANGELOG.md
#	apps/server/src/integrations/environment/environment.service.spec.ts
#	apps/server/src/integrations/environment/environment.service.ts
2026-06-29 18:49:06 +03:00
claude_code 7ac7fcba2d chore(pwa): reconcile dual service worker after mobile-app-bootstrap merge
The mobile bootstrap shipped a hand-written public/sw.js plus a manual
navigator.serviceWorker.register('/sw.js') in main.tsx. The offline-sync
Workbox SW (vite-plugin-pwa, generateSW) functionally supersedes it
(NetworkOnly for /api,/collab,/socket.io, navigateFallback to the app shell,
runtime caching) and adds precache + prompt-based updates, so:

- Remove the hand-written apps/client/public/sw.js.
- Remove the manual SW registration block from main.tsx; registration is now
  owned by <PwaUpdatePrompt/> via useRegisterSW (skipped in Capacitor native).
- Regenerate pnpm-lock.yaml for the merged Capacitor + @nestjs/swagger deps.

Kept from mobile-app-bootstrap: the richer manifest.json (offline-sync uses
manifest:false), capacitor.config.ts, the apple-touch-icon, and all server
mobile-auth/CORS/Swagger changes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 15:15:50 +03:00
claude_code e05495ba4f feat(offline): PWA shell, Yjs-backed titles, and offline read cache (M0–M2)
Implements docs/offline-sync-plan.md milestones M0–M2.

M0 (PWA shell):
- Add vite-plugin-pwa (generateSW, registerType: 'prompt', manifest:false);
  NetworkOnly for /api,/collab,/socket.io, NetworkFirst for GET /api,
  navigateFallback to index.html.
- Register SW via useRegisterSW with a Mantine update prompt; skip
  registration inside Capacitor native WebView (is-capacitor guard).

M1 (harden CRDT body + title into Yjs):
- Lift the per-page Y.Doc/Hocuspocus providers into a shared hook+context so
  body and title editors share one doc.
- Move the page title into a dedicated 'title' Yjs fragment (CRDT, offline-
  tolerant); drop the REST title save. Server persists the title fragment to
  page.title and seeds it for legacy pages (empty-fragment guard); a collab
  rename emits a treeUpdate so other users' tree/breadcrumbs refresh.
- Persist the rebuilt ydoc on the content->ydoc path to neutralize the Yjs
  duplication trap. Add a 3-state sync indicator.

M2 (offline read/navigation):
- Persist React Query to IndexedDB (idb-keyval persister, version buster,
  selected roots only).
- "Make available offline" action warms page, space, tree (root+ancestors+
  children) and comments under exact hook keys, plus the page ydoc.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 15:15:49 +03:00
claude code agent 227 38a863e5f7 refactor(agent-roles-catalog): store catalog as YAML with block-scalar instructions (#229)
The agent-roles catalog content files move from JSON to YAML so each role's long
`instructions` system prompt is stored as a literal block scalar (`|-`): editing
one sentence now produces a line-by-line diff and the prompt is editable as plain
multi-line text instead of a single escaped JSON string.

Data:
- `index.json` -> `index.yaml`, `bundles/<id>/<lang>.json` -> `<lang>.yaml`
  (old `.json` deleted). Converted programmatically via the `yaml` library with
  `lineWidth: 0`; round-trip verified deepEqual against the old JSON, so the
  resolved role content is byte-for-byte identical (the only `version` bump is
  fact-checker v2->3, carried over from develop during the rebase; see below).

Server (`AiAgentRolesCatalogProvider`):
- parse with `yaml`'s safe default (JSON-compatible) schema instead of
  `JSON.parse` — `strict: true` (rejects duplicate keys) and `maxAliasCount: 100`
  (billion-laughs guard); no custom `!!` tags / no code execution. Fetched paths
  become `index.yaml` / `<lang>.yaml`. The streaming 1 MB size cap,
  `redirect: 'error'`, 10s timeout and `^[a-z0-9-]+$` path-traversal/SSRF guard
  are unchanged; the hand-written type guards are untouched (`instructions` is
  still a string after parsing).
- add `yaml` as a direct server dependency (already in the lockfile as a
  transitive dep).

Catalog tooling:
- `scripts/check.mjs` parses the catalog as YAML (lockfile stays JSON); pin
  `yaml` as a devDependency of the catalog package.

Tests:
- provider spec fixtures serialized with `yaml`; new tests for the block-scalar
  `instructions` round-trip (exact multi-line string), malformed YAML and
  strict duplicate-key rejection -> BadGateway; size-cap and path-traversal
  cases retargeted to the `.yaml` paths.

Docs: README, `.env.example`, `catalog-types.ts` comments and CHANGELOG updated
to the YAML layout. `AI_AGENT_ROLES_CATALOG_URL` base-URL contract unchanged.

Rebase onto develop + review (PR #231, comment 2509):
- semantic conflict: develop's 89edddc5 bumped fact-checker v2->3 (flags errors
  instead of confirming facts) in the now-deleted `.json`. Resolved the
  modify/delete by taking the deletion and porting develop's v3 `description` +
  `instructions` (en + ru) into the YAML and setting `version: 3` in index.yaml.
  Verified by `node scripts/check.mjs` going green against develop's unchanged
  content-hash lock (the ported YAML hashes byte-identically to the v3 JSON).
- doc fix: ai-agent-roles.service.ts catalog comment "untrusted JSON" -> YAML.
- doc fix: parseYaml docstring no longer claims `strict: true` rejects unknown
  custom tags (yaml@2.8.x warns + resolves to a plain scalar, then the type
  guard rejects it); the duplicate-key claim is kept.
- doc: note in check.mjs that `yaml` resolves from the repo-ROOT node_modules
  (via shamefully-hoist), not the catalog package's own pinned devDependency.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28 04:38:50 +03:00
claude code agent 227 f86b8b69a0 fix(mcp): structural-diff write-back so agent edits don't jump the cursor (#152)
mutatePageContent wrote agent edits back by DELETING the whole Yjs fragment and
re-applying a fresh Y.Doc. Yjs is a CRDT — the editor anchors its selection to
node ids — so wiping every id made an open editor's cursor lose its anchor and
snap to the end of the document on every agent write. It was most visible on
comment anchoring (issue #152): a comment changes no text, yet the cursor jumped.
(Before commit 4201f0a3 the anchoring silently no-op'd, so the destructive write
never ran for comments — hence the regression.)

Fix: write via `updateYFragment` (y-prosemirror) — the same routine the editor
uses to sync its own edits into Yjs. It structurally diffs the new doc against
the live fragment and touches only changed nodes, preserving the ids of unchanged
ones, so the cursor stays put. This improves ALL agent write tools (text edits,
node ops, comments, replace) — minimal diff instead of full replace: less collab
noise, stable block-ids, other users' cursors no longer disrupted.

- collaboration.ts: new `applyDocToFragment` (sanitize -> PMNode.fromJSON against
  a memoized docmost schema -> updateYFragment in one transact), keeping the
  `findUnstorableAttr` encode diagnostic; swap the destructive write-back for it.
- package.json: `y-prosemirror` promoted to a direct dependency (was transitive).
- test: comment-cursor-stability.test.mjs — a Yjs RelativePosition (the cursor
  anchor) survives both a sibling edit and a comment-mark anchoring (the old
  full-replace tombstoned it -> null). 292 package tests green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 05:56:32 +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
vvzvlad a4b7919753 fix(ai-chat): OpenAI Chat Completions for multi-turn + provider settings, stream UX & errors" -m "Live-stand fixes (OpenRouter / OpenAI-compatible):
- openai provider: use .chat() (Chat Completions) instead of the default callable
  (Responses API), which gateways reject on multi-turn -> 400.
- updateAiProviderSettings: assemble settings.ai.provider via jsonb_build_object
  with ::text-cast bound params + jsonb_typeof self-heal (postgres.js was
  double-encoding it into an array; the ::text cast avoids 'could not determine
  data type of parameter').
- chat agent: drop the hard maxOutputTokens cap (truncated complex tool calls);
  keep a tiny cap only on the test-connection ping.
- testConnection + chat stream: surface the real provider error (statusCode+message)
  to logs and the UI instead of generic masks; never log the API key.
- chat UI: typing indicator, incremental streaming render, tool 'running' status, Stop.

Also bundled (prior uncommitted ai-chat work):
- history 'AI agent' provenance badge; vector RAG (pgvector image + page_embeddings
  + AI_QUEUE indexer + space-scoped semanticSearch); external MCP servers backend
  (@ai-sdk/mcp client, SSRF IP-pinning, encrypted headers, admin CRUD/Test);
  yjs duplicate-instance fix via pnpm patch (single CJS instance server-side).
2026-06-17 04:28:29 +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
vvzvlad 1f5987d6b0 feat(mcp): serve embedded community MCP server at /mcp
Replace the removed enterprise EE MCP (private apps/server/src/ee submodule,
license-gated /mcp route) with our docmost-mcp, vendored as an isolated ESM
workspace package and served by the server over HTTP — no enterprise license.

Backend:
- Add packages/mcp (@docmost/mcp): vendored docmost-mcp refactored into a
  side-effect-free createDocmostMcpServer() factory (38 tools preserved),
  stdio entry kept in stdio.ts, Streamable-HTTP session manager in http.ts.
- Add apps/server McpModule: @Post/@Get/@Delete('mcp') (served at /mcp via the
  existing global-prefix exclude), @SkipTransform + reply.hijack to bridge raw
  Fastify req/res into the SDK transport. The module dynamically imports the
  ESM-only package from CommonJS via a Function-indirected import resolved with
  require.resolve + file:// URL. Gated by the workspace ai.mcp toggle, a
  service-account (MCP_DOCMOST_EMAIL/PASSWORD/API_URL) and optional MCP_TOKEN;
  per-session idle eviction (MCP_SESSION_IDLE_MS).
- Drop the enterprise license check on mcpEnabled in workspace.service.
- Dockerfile: copy packages/mcp into the production image.
- .env.example: document MCP_DOCMOST_*, MCP_TOKEN, MCP_SESSION_IDLE_MS.

Frontend:
- Recreate the community "AI & MCP" workspace-settings panel (mcp-settings.tsx):
  admin-only toggle on settings.ai.mcp with optimistic update, copyable
  ${APP_URL}/mcp URL; wired into workspace-settings page. Reuses existing i18n.

Fixes:
- Pin packages/mcp tiptap deps to 3.20.4 (matching the client) and inline
  getStyleProperty, preventing a duplicate @tiptap/core@3.26.1 from leaking into
  the client editor via pnpm shamefully-hoist (was breaking apps/client tsc).
2026-06-16 23:54:53 +03:00
Philipinho b6760c63c4 fix: package updates 2026-05-28 16:39:47 +01:00
Philipinho 13a7f1372f fix: update pdf-inspector package 2026-05-21 13:44:11 +01:00
Philip Okugbe 4295ea09f6 feat(storage): add Azure Blob Storage driver (#2222) 2026-05-21 12:18:58 +01:00
Philip Okugbe a5858bc470 fix: update packages (#2221) 2026-05-20 18:30:15 +01:00
Philipinho 3b983a27f6 sync 2026-05-14 03:01:55 +01:00
Philip Okugbe 299a9ca3c8 fix: bug fixes (#2201)
* fix(editor): hide transclusion borders and reset spacing in read-only mode

* feat(share): add full width toggle for shared pages

* feat(share): support resizing sidebar on shared pages

* fix: auto redirect if there is only one SSO provider.
- fix tighten sso redirect
- fix share tree margin

* sync

* package overrides
2026-05-14 02:54:00 +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
Philip Okugbe 73dc62bca3 update react-email (#2149) 2026-05-04 22:26:53 +01:00
Philipinho 3c74bb3dee update package 2026-05-04 22:09:19 +01:00
Philipinho 17f3158a3b update aws packages 2026-05-01 20:00:20 +01:00
Philip Okugbe c247d4c1e3 feat(ee): PDF import (#2142)
* feat: replace pdfjs-dist with firecrawl-pdf-inspector

* use modified firecrawl-pdf-inspector

* feat: pdf import

* increase single file upload size limit

* use npm package

* sync

* update package
2026-05-01 14:56:39 +01:00
Philip Okugbe 641ce142df feat(ee): SCIM (#1347)
* SCIM - init (EE)

* accept db transaction

* sync

* Content parser support for scim+json

* patch scimmy

* sync

* return early if userIds is empty

* sync

* SCIM db table

* fixes

* scim tokens

* backfill

* feat(audit): add scim token events

* rename scim migration

* fix

* fix translation

* cleanup
2026-05-01 14:53:30 +01:00
Philipinho 980521f957 v0.80.1 2026-04-27 16:06:32 +01:00
Philip Okugbe fad410ef23 chore: add undici for oidc proxy support (#2132) 2026-04-27 15:50:42 +01:00
Philipinho 8e15b22d8c package updates 2026-04-27 15:22:02 +01:00
Philipinho ec83fc82d5 fix: refactor sanitize 2026-04-27 15:16:26 +01:00
Philipinho a573acedd0 fix: local storage, and package overrides 2026-04-22 14:13:25 +01:00
Philipinho dba8e315ab override 2026-04-14 17:59:59 +01:00
Philip Okugbe 4056bd0104 feat: enhancements (#2107)
* refactor
* fix
* update packages
2026-04-13 23:34:40 +01:00
Philip Okugbe 57efb91bd3 feat(ee): ai chat (#2098)
* feat: ai chat

* feat: ai chat

* sync

* cleanup

* view space button
2026-04-10 19:23:47 +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 fd91b11c6c pin version 2026-03-31 16:06:44 +01:00
Philip Okugbe c180d0e487 feat: ratelimits (#2073)
* feat: rate limits

* ip
2026-03-30 15:38:44 +01:00
Philipinho bca85a49d6 pin marked version 2026-03-29 03:03:35 +01:00
Philipinho 17da762984 overrides 2026-03-28 19:28:22 +00:00
Philip Okugbe 7981ef462e feat(editor): audio and PDF nodes (#2064)
* use local resizable

* feat: aduio

* support audio imports

* feat: use confluence real file names

* cleanup

* error handling

* hide notice

* add audio

* fix pulse

* Fix import and export

* unify pulse

* hide in readonly mode

* keywords

* keyword

* translations

* better sort

* feat: PDF embed

* cleanup

* remove audio menu

* open active

* hide focus on readonly mode

* increase iframe default dimension
2026-03-28 17:33:29 +00:00
Philip Okugbe 803f1f0b81 feat: user session management (#2056)
* user session management

* WIP

* cleanup

* license

* cleanup

* don't cache index

* rename current device property

* fix
2026-03-26 20:00:04 +00:00
Philipinho 4e8f533b91 override 2026-03-26 16:48:33 +00:00
Philipinho 7b0d8fe140 override 2026-03-26 16:46:40 +00: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 7c83a9d4f0 update dompurify 2026-03-16 13:49:20 +00:00
Philip Okugbe 97c459be67 feat(cloud): add find-workspace and email verification endpoints (#2020)
* feat: add find-workspace and email verification endpoints
* sync
2026-03-14 13:36:30 +00:00
Philipinho c24ff44e09 fix(deps): update dependencies 2026-03-02 21:44:24 +00:00
Philip Okugbe 60848ea903 feat(ee): mcp (#1976)
* feat: MCP
* sync
* sync
2026-03-01 18:37:39 +00:00
Philip Okugbe 69d7532c6c feat(ee): audit logs (#1977)
feat: clickhouse driver
* sync
* updates
2026-03-01 01:29:03 +00:00
Philip Okugbe 59e945562d feat(ee): page-level access/permissions (#1971)
* Add page_hierarchy table

* feat(ee): page-level permissions

* pagination

* rename migration
fixes

* fix

* tabs

* fix theme

* cleanup

* sync

* page permissions notification
* other fixes

* sharing disbled

* fix column nodes

* toggle error handling
2026-02-26 19:49:10 +00:00
Philip Okugbe ef87210b3d feat: editor UI refresh and enhancements (#1968)
* feat: new image menu
* switch to resizable side handles
* use pixels

* refactor excalidraw and drawio menu

* support image resize undo

* video resize

* callout menu refresh

* refresh table menus

* fix color scheme

* fix: patch @tiptap/core ResizableNodeView to prevent resize sticking after mouseup

* feat: columns

* notes callout

* focus on first column

* capture tab key in column

* fix print

* hide columns menu when some nodes are focused

* fix print

* fix columns

* selective placeholder

* fix blockquote

* quote

* fix callout in columns
2026-02-24 15:22:37 +00:00