ocean-brain 0.13.0 → 0.13.2

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.
Files changed (48) hide show
  1. package/README.md +5 -3
  2. package/dist/index.js +12 -4
  3. package/package.json +10 -8
  4. package/server/client/dist/assets/{Calendar-CaeK7gTz.js → Calendar-DH3eSSRs.js} +1 -1
  5. package/server/client/dist/assets/{Note-CGI-Y1__.js → Note-CpzLtGVM.js} +1 -1
  6. package/server/client/dist/assets/{Search-DAYHxAml.js → Search-D9detGWk.js} +1 -1
  7. package/server/client/dist/assets/{Tag-CG8b0l1j.js → Tag-Bquqtx23.js} +1 -1
  8. package/server/client/dist/assets/{TagNotes-COyaVsdn.js → TagNotes-CbjfxqAN.js} +1 -1
  9. package/server/client/dist/assets/{Views-BPxlw3vk.js → Views-L4eC96Lx.js} +1 -1
  10. package/server/client/dist/assets/{app-BezcjTfd.js → app-BFM2V_Rx.js} +2 -2
  11. package/server/client/dist/assets/{index-CzZFedXj.js → index-CJPl3MJE.js} +1 -1
  12. package/server/client/dist/assets/{manage-image-detail-9hRTiAsR.js → manage-image-detail-BIDHUR5-.js} +1 -1
  13. package/server/client/dist/assets/mcp-D8footel.js +5 -0
  14. package/server/client/dist/assets/{note-core-DUTqUh5N.js → note-core-YhYEmI_R.js} +1 -1
  15. package/server/client/dist/assets/note-runtime-B3ats-dC.js +153 -0
  16. package/server/client/dist/assets/{note-ui-BaqzP-YU.js → note-ui-BtzPk8gA.js} +1 -1
  17. package/server/client/dist/assets/{placeholder-CZoqs4S3.js → placeholder-DKgxoe_f.js} +1 -1
  18. package/server/client/dist/assets/route-preload.js +2 -2
  19. package/server/client/dist/index.html +1 -1
  20. package/server/dist/app.js +91 -8
  21. package/server/dist/features/auth/http/api.js +9 -8
  22. package/server/dist/features/auth/http/pages.js +27 -28
  23. package/server/dist/features/auth/service.js +7 -27
  24. package/server/dist/features/cache/graphql/cache.type-defs.js +1 -1
  25. package/server/dist/features/image/http/upload.js +2 -2
  26. package/server/dist/features/mcp-admin/http/handlers.js +9 -9
  27. package/server/dist/features/note/http/mcp.js +17 -17
  28. package/server/dist/features/search/http/handlers.js +10 -10
  29. package/server/dist/features/search/search-manager.js +34 -6
  30. package/server/dist/features/tag/http/mcp.js +2 -2
  31. package/server/dist/modules/auth-guard.js +36 -53
  32. package/server/dist/modules/blocknote.js +16 -9
  33. package/server/dist/modules/error-handler.js +17 -20
  34. package/server/dist/modules/mcp-auth.js +50 -56
  35. package/server/dist/modules/rate-limit.js +23 -23
  36. package/server/dist/modules/server-events-handler.js +15 -13
  37. package/server/dist/modules/session-store.js +6 -8
  38. package/server/dist/paths.js +2 -1
  39. package/server/dist/routes/api.js +105 -71
  40. package/server/dist/routes/auth-pages.js +21 -11
  41. package/server/dist/routes/client.js +60 -72
  42. package/server/dist/routes/graphql.js +31 -26
  43. package/server/dist/routes/mcp.js +25 -35
  44. package/server/dist/server.js +14 -16
  45. package/server/client/dist/assets/mcp-ugdCKa6H.js +0 -4
  46. package/server/client/dist/assets/note-runtime-zN5ddTba.js +0 -168
  47. package/server/dist/modules/logger.js +0 -53
  48. package/server/dist/modules/use-async.js +0 -10
@@ -1,4 +1,3 @@
1
- import { Router } from "express";
2
1
  import {
3
2
  createMcpAppendNoteMarkdownHandler,
4
3
  createMcpCreateNoteHandler,
@@ -10,40 +9,31 @@ import {
10
9
  } from "../features/note/http/mcp.js";
11
10
  import { createMcpCreateTagHandler } from "../features/tag/http/mcp.js";
12
11
  import { createMcpAuthMiddleware } from "../modules/mcp-auth.js";
13
- import useAsync from "../modules/use-async.js";
14
- const createMcpRouter = (authConfig, mcpAdminService) => Router().post(
15
- "/notes/create",
16
- createMcpAuthMiddleware(authConfig, mcpAdminService),
17
- useAsync(createMcpCreateNoteHandler())
18
- ).post(
19
- "/notes/baseline",
20
- createMcpAuthMiddleware(authConfig, mcpAdminService),
21
- useAsync(createMcpNoteWriteBaselineHandler())
22
- ).post(
23
- "/notes/patch-markdown",
24
- createMcpAuthMiddleware(authConfig, mcpAdminService),
25
- useAsync(createMcpPatchNoteMarkdownHandler())
26
- ).post(
27
- "/notes/append-markdown",
28
- createMcpAuthMiddleware(authConfig, mcpAdminService),
29
- useAsync(createMcpAppendNoteMarkdownHandler())
30
- ).post(
31
- "/notes/metadata",
32
- createMcpAuthMiddleware(authConfig, mcpAdminService),
33
- useAsync(createMcpUpdateNoteMetadataHandler())
34
- ).post(
35
- "/notes/replace-markdown",
36
- createMcpAuthMiddleware(authConfig, mcpAdminService),
37
- useAsync(createMcpReplaceNoteMarkdownHandler())
38
- ).post(
39
- "/notes/delete",
40
- createMcpAuthMiddleware(authConfig, mcpAdminService),
41
- useAsync(createMcpDeleteNoteHandler())
42
- ).post(
43
- "/tags/create",
44
- createMcpAuthMiddleware(authConfig, mcpAdminService),
45
- useAsync(createMcpCreateTagHandler())
46
- );
12
+ const createMcpRouter = (authConfig, mcpAdminService) => {
13
+ return async (app) => {
14
+ const requireMcpAuth = createMcpAuthMiddleware(authConfig, mcpAdminService);
15
+ app.post("/notes/create", { preHandler: requireMcpAuth }, createMcpCreateNoteHandler());
16
+ app.post("/notes/baseline", { preHandler: requireMcpAuth }, createMcpNoteWriteBaselineHandler());
17
+ app.post(
18
+ "/notes/patch-markdown",
19
+ { preHandler: requireMcpAuth },
20
+ createMcpPatchNoteMarkdownHandler()
21
+ );
22
+ app.post(
23
+ "/notes/append-markdown",
24
+ { preHandler: requireMcpAuth },
25
+ createMcpAppendNoteMarkdownHandler()
26
+ );
27
+ app.post("/notes/metadata", { preHandler: requireMcpAuth }, createMcpUpdateNoteMetadataHandler());
28
+ app.post(
29
+ "/notes/replace-markdown",
30
+ { preHandler: requireMcpAuth },
31
+ createMcpReplaceNoteMarkdownHandler()
32
+ );
33
+ app.post("/notes/delete", { preHandler: requireMcpAuth }, createMcpDeleteNoteHandler());
34
+ app.post("/tags/create", { preHandler: requireMcpAuth }, createMcpCreateTagHandler());
35
+ };
36
+ };
47
37
  export {
48
38
  createMcpRouter
49
39
  };
@@ -1,4 +1,3 @@
1
- import { createServer as createNodeHttpServer } from "node:http";
2
1
  import { createApp } from "./app.js";
3
2
  import { ensureNoteReferenceIndex } from "./features/note/services/note-reference-index.js";
4
3
  import { getDefaultSemanticSearchManager } from "./features/search/search-manager.js";
@@ -9,31 +8,30 @@ const startServer = async (options = {}) => {
9
8
  const host = process.env.HOST || "0.0.0.0";
10
9
  const authConfig = resolveAuthConfig(process.env);
11
10
  logAuthConfig(authConfig);
12
- const httpServer = options.serverFactory ? await options.serverFactory(authConfig) : createNodeHttpServer(createApp(authConfig));
11
+ const app = options.serverFactory ? await options.serverFactory(authConfig) : createApp(authConfig);
13
12
  getDefaultSemanticSearchManager();
14
13
  const rebuiltReferenceCount = await ensureNoteReferenceIndex();
15
14
  if (rebuiltReferenceCount > 0) {
16
15
  process.stdout.write(`[maintenance] Rebuilt ${rebuiltReferenceCount} note reference rows
17
16
  `);
18
17
  }
19
- httpServer.listen(port, host, () => {
20
- process.stdout.write(`http server listen on ${host}:${port} (auth: ${authConfig.mode})
18
+ const address = await app.listen({ port, host });
19
+ process.stdout.write(`http server listen on ${address} (auth: ${authConfig.mode})
21
20
  `);
22
- startDataMaintenanceScheduler({
23
- onResults: (results) => {
24
- for (const result of results) {
25
- process.stdout.write(`[maintenance] Reconciled ${result.processedCount} rows for ${result.key}
26
- `);
27
- }
28
- },
29
- onError: (error) => {
30
- const message = error instanceof Error ? error.message : "Unknown data maintenance error";
31
- process.stderr.write(`[maintenance] Background run failed: ${message}
21
+ startDataMaintenanceScheduler({
22
+ onResults: (results) => {
23
+ for (const result of results) {
24
+ process.stdout.write(`[maintenance] Reconciled ${result.processedCount} rows for ${result.key}
32
25
  `);
33
26
  }
34
- });
27
+ },
28
+ onError: (error) => {
29
+ const message = error instanceof Error ? error.message : "Unknown data maintenance error";
30
+ process.stderr.write(`[maintenance] Background run failed: ${message}
31
+ `);
32
+ }
35
33
  });
36
- return httpServer;
34
+ return app;
37
35
  };
38
36
  export {
39
37
  startServer
@@ -1,4 +0,0 @@
1
- import{r as u,j as e}from"./floating-ui.react-dom-BWTnA00G.js";import{u as Z,a as W,b as k}from"./useNoteMutate-BjvZUmtX.js";import{u as X,P as Y,T as o,a as ee,b as j,L as p,B as x,d as $,s as te,I as O,S as ne,e as ae}from"./time-PxWila4-.js";import{f as se,s as oe,r as ie,a as ce}from"./mcp-admin-adapter-D0R8p9az.js";import{s as E}from"./Copy.es-fMv0ETir.js";import"./url-DKUMNVCI.js";const h=["mcp-admin","status"],f=t=>/^[A-Za-z0-9_./:@$-]+$/.test(t)?t:`'${t.replace(/'/g,"'\\''")}'`,L="$HOME/.config/ocean-brain/mcp-token",R=(t,n)=>{const s=f(t);return[`mkdir -p "$(dirname ${s})"`,`printf '%s' ${f(n)} > ${s}`,`chmod 600 ${s}`].join(`
2
- `)},A=(t,n)=>`npx -y ocean-brain mcp --server ${f(t)} --token-file ${f(n)}`,re=(t,n)=>`codex mcp add ocean-brain -- ${A(t,n)}`,le=(t,n)=>`claude mcp add --transport stdio ocean-brain -- ${A(t,n)}`,de=(t,n)=>JSON.stringify({mcpServers:{"ocean-brain":{command:"npx",args:["-y","ocean-brain","mcp","--server",t,"--token-file",n]}}},null,2),me=(t,n,s,c)=>{const d=t==="codex"?re(n,s):t==="claude"?le(n,s):de(n,s);return t==="json"?["# 1. Create the token file",R(s,c),"","# 2. Add this MCP JSON",d].join(`
3
- `):["# 1. Create the token file",R(s,c),"",`# 2. Add Ocean Brain to ${t}`,d].join(`
4
- `)},ue=t=>!t||t==="unknown"?"MCP compatibility":`MCP compatibility ${t}`,pe={codex:"Codex",claude:"Claude",json:"JSON"},je=()=>{const t=Z(),n=ae(),s=X(),[c,d]=u.useState(()=>window.location.origin),[r,C]=u.useState(""),[v,F]=u.useState(L),[i,J]=u.useState("codex"),{data:y,isLoading:z}=W({queryKey:h,queryFn:se}),w=k({mutationFn:oe,onSuccess:a=>{s.setQueryData(h,a),n(a.enabled?"MCP access enabled.":"MCP access disabled.")}}),N=k({mutationFn:ie,onSuccess:async({token:a})=>{C(a),n("New MCP token issued. Previous token is no longer valid."),await s.invalidateQueries({queryKey:h})}}),T=k({mutationFn:ce,onSuccess:a=>{C(""),s.setQueryData(h,a),n("MCP token revoked. Existing client configs will stop working.")}}),b=y?.enabled??!1,l=y?.hasActiveToken??!1,Q=!z&&!w.isPending,B=v.trim()||L,q=ue(y?.server.mcpVersionRequirement),I=l?"1 active token":"No active token",K=i==="json"?"Token file and MCP JSON":`${pe[i]} setup`,M=me(i,c,B,r||"PASTE_TOKEN_HERE"),_="Copy setup",P="text-fg-tertiary",m="font-medium text-fg-tertiary",g="surface-base px-4 py-3.5",S="space-y-2",H="max-w-full overflow-x-auto whitespace-pre font-mono text-xs leading-5 text-fg-secondary",V=async()=>{try{await navigator.clipboard.writeText(r),n("Copied token.")}catch{n("Failed to copy token.")}},G=async()=>{try{await navigator.clipboard.writeText(M),n(i==="json"?"Copied MCP JSON.":"Copied MCP command.")}catch{n(`Could not copy. Select the ${i==="json"?"JSON":"command"} and copy it manually.`)}},D=async()=>{l&&!await t("Rotate the MCP token? Existing MCP clients will stop working until they use the new token.")||N.mutate(void 0)},U=async()=>{await t("Revoke the MCP token? Existing MCP clients will stop working immediately.")&&T.mutate()};return e.jsx(Y,{title:"MCP",variant:"default",description:"Connect this Ocean Brain instance to MCP clients.",headerRight:e.jsxs("div",{className:"inline-flex items-center gap-3 rounded-[14px] border border-border-subtle bg-muted px-3 py-2",children:[e.jsxs(o,{as:"span",variant:"meta",weight:"medium",tone:"secondary",children:["MCP access ",b?"on":"off"]}),e.jsx(ne,{"aria-label":"MCP access",checked:b,disabled:!Q,onCheckedChange:()=>{w.mutate(!b)}})]}),children:e.jsxs("div",{className:"flex flex-col gap-4",children:[e.jsxs("section",{className:"flex flex-col gap-3","aria-labelledby":"mcp-connect-heading",children:[e.jsxs("div",{className:"flex flex-wrap items-start justify-between gap-3",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx(o,{id:"mcp-connect-heading",as:"h2",variant:"label",weight:"medium",className:P,children:"Connect a client"}),e.jsx(o,{as:"p",variant:"meta",tone:"secondary",children:"Save your token in a local file, then copy the command for your client."})]}),e.jsx(o,{as:"span",variant:"meta",weight:"medium",tone:"tertiary",className:"rounded-full border border-border-subtle bg-hover-subtle px-2.5 py-1",children:q})]}),e.jsxs("div",{className:`${g} flex flex-col gap-3`,children:[e.jsx("div",{className:"flex flex-wrap items-center gap-3",children:e.jsxs(ee,{type:"single",variant:"quiet",size:"sm",value:i,onValueChange:a=>{(a==="codex"||a==="claude"||a==="json")&&J(a)},children:[e.jsx(j,{value:"codex",children:"Codex"}),e.jsx(j,{value:"claude",children:"Claude"}),e.jsx(j,{value:"json",children:"JSON"})]})}),e.jsxs("div",{className:"min-w-0 space-y-2",children:[e.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-3",children:[e.jsx(p,{htmlFor:"mcp-connection-output",className:m,children:K}),e.jsxs(x,{type:"button",variant:"subtle",size:"sm",onClick:G,children:[e.jsx(E,{className:"h-4 w-4"}),_]})]}),e.jsx($,{id:"mcp-connection-output",readOnly:!0,rows:i==="json"?13:9,wrap:"off",value:M,className:H}),e.jsx(o,{as:"p",variant:"meta",tone:"tertiary",children:r?"The new token is already included in the token file step.":"Replace PASTE_TOKEN_HERE before running. The MCP client reads the token from that file."})]}),e.jsxs("details",{className:"group rounded-[12px] border border-border-subtle bg-muted",children:[e.jsxs("summary",{className:"flex cursor-pointer list-none items-center justify-between gap-3 px-3 py-2.5 marker:hidden",children:[e.jsx(o,{as:"span",variant:"meta",weight:"medium",tone:"secondary",children:"Connection options"}),e.jsx(te,{className:"h-4 w-4 shrink-0 text-fg-tertiary transition-transform group-open:rotate-180","aria-hidden":"true"})]}),e.jsxs("div",{className:"space-y-3 border-t border-border-subtle px-3 py-3",children:[e.jsxs("div",{className:S,children:[e.jsx(p,{htmlFor:"mcp-server-url",className:m,children:"Ocean Brain URL"}),e.jsx(O,{id:"mcp-server-url",value:c,onChange:a=>d(a.target.value)})]}),e.jsxs("div",{className:S,children:[e.jsx(p,{htmlFor:"mcp-token-file-path",className:m,children:"Token file path"}),e.jsx(O,{id:"mcp-token-file-path",placeholder:"/absolute/path/to/ocean-brain-mcp-token.txt",value:v,onChange:a=>F(a.target.value)})]})]})]})]})]}),e.jsxs("section",{className:"flex flex-col gap-3","aria-labelledby":"mcp-token-heading",children:[e.jsxs("div",{className:`${g} flex flex-wrap items-center justify-between gap-3`,children:[e.jsxs("div",{className:"min-w-0 space-y-1",children:[e.jsx(o,{id:"mcp-token-heading",as:"h2",variant:"label",weight:"medium",className:P,children:"Token"}),e.jsxs(o,{as:"p",variant:"meta",tone:"tertiary",children:[I,". New tokens are shown once."]})]}),e.jsxs("div",{className:"flex flex-wrap gap-2",children:[e.jsx(x,{type:"button",size:"sm",variant:l?"subtle":"primary",onClick:D,isLoading:N.isPending,children:l?"Rotate token":"Issue token"}),e.jsx(x,{type:"button",size:"sm",variant:"soft-danger",onClick:U,isLoading:T.isPending,disabled:!l,children:"Revoke token"})]})]}),r&&e.jsxs("div",{className:`${g} border-dashed`,children:[e.jsxs("div",{className:"mb-3 flex flex-wrap items-start justify-between gap-3",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx(p,{htmlFor:"issued-mcp-token",className:m,children:"New token"}),e.jsx(o,{as:"p",variant:"meta",tone:"secondary",children:"Copy this token now and save it in your token file."})]}),e.jsxs(x,{type:"button",variant:"subtle",size:"sm",onClick:V,children:[e.jsx(E,{className:"h-4 w-4"}),"Copy token"]})]}),e.jsx($,{id:"issued-mcp-token",rows:3,readOnly:!0,value:r})]})]})]})})};export{je as default};