quberi/dsh-quberi

dsh-quberi

在 DeepSeek Harness 内通过 OAuth 检索你的 Quberi 知识库中的文档和图片,浏览空间和文档,保存笔记,并上传文件(每个文件都需你确认)。

未分類deepseek-harnessquberi

dsh-quberi

Query your Quberi knowledge base from DeepSeek Harness: search, browse, save notes and upload files.

The interesting part isn't the search — it's what search is allowed to return. Quberi enforces permissions per document, not per space: two people asking the same question in the same space can get different answers, because the retrieval filter runs inside the vector index and a denied document is never a candidate in the first place.

  • Per-document access rules with deny wins — a grant cannot override a

decision to hide one document.

  • Filtered at retrieval time, so you get a full result set, not a shorter

one with holes.

  • Revoked picture links die — a picture preview URL issued before access was

removed returns 404 on the next request.

  • Writes go only into spaces you can edit; uploads require your confirmation

each time.

Ask Harness a question about your documents. The first time, your browser opens by itself so you can approve access; after that the model can call quberi_search, which finds passages in the documents you can read in Quberi, in the one organization you pick (name a space to search only that one). It can also call quberi_save to add a note (a conclusion, decision or summary from the chat) to your knowledge base, and quberi_upload_file to add a file from your workspace. quberi_list_spaces and quberi_list_documents show what is there, and quberi_search_images finds pictures from a description and shows them in the chat. Saving is new in 0.3.0 and uploading in 0.4.0; each needs a fresh sign-in that includes it. Browsing and picture search need nothing beyond search. An upload only happens after you approve that file (see Uploading files).

Each scope is granted on its own: search needs knowledge:read, saving needs knowledge:write and uploading needs knowledge:upload. A document someone shared with you individually is found even if you cannot read its space, and a document hidden from you is not found even if you can read its space.

Install

In DeepSeek Harness open Plugins → Add plugin and enter:

dsh-quberi

Or from a terminal (replace desktop with your profile name):

dsh plugin --profile desktop add dsh-quberi

Then restart Harness. To upgrade, remove the old version first (dsh plugin --profile desktop remove dsh-quberi), then add it again.

You need a Quberi account at ai.quberi.com, or your own Quberi server (see Configuration).

A plugin runs on your machine with your permissions, so read the source first. It is small: src/oauth.ts (sign-in helpers), src/browser.ts (opens your browser), src/controller.ts (sign-in, token refresh, search, save, upload), src/upload.ts (which files may be uploaded, and the approval gate) and src/index.ts (the /quberi command and the tools). Its only runtime dependency is @deepseek-ai/schemastery.

From source

npm install
npm test
npm pack      # builds lib/ and writes dsh-quberi-<version>.tgz
dsh plugin --profile desktop add /path/to/dsh-quberi-<version>.tgz

Use

Command · What it does /quberi login · Opens your browser to sign in to Quberi (the link is also shown in case it does not open). Choose an organization and allow. You rarely need this: the first search does it for you. If you signed in with an older version, run it again to allow saving or uploading. /quberi status · Shows whether you are connected. Never prints a token. /quberi logout · Revokes the sign-in at Quberi and forgets it locally. /quberi mode [text\ · image\ · both] · Shows or sets where searches look: the documents' text, pictures, or both (the default). See Where a search looks.

The sign-in page says what Harness is asking to do (search, save notes, upload files) and what it cannot do, and lets you choose the organization (shown here in Chinese):

You can also disconnect any time in Quberi under Account → Connected tools.

When sign-in finishes, the browser shows a confirmation page and Harness is brought back to the front (macOS). Nothing needs to be copied or pasted.

On a machine with no screen (a remote shell), the browser is not opened; the plugin gives you the link to open on another device instead.

Before it works

The organization you choose must allow outside tools. It is off by default. An owner or admin turns it on under Admin console → Integrations → Outside tools; owners and admins also get a "Turn on" button on the approval page.

What leaves Quberi

The passages the search returns go to Harness and to whichever AI model Harness uses. Quberi's "check before sending" step does not apply to this path. Every search is recorded in the organization's audit log (the tool's name and the documents returned, never the question or the text).

quberi_read_around sends more of a document than the search does: up to 3000 characters on either side of a passage, only when the model asks for it, and only from documents you can open in Quberi. Each call is recorded in the audit log (the document, the version and how many characters, never the text) and is rate limited. A page image is fetched by Harness from a short-lived link on your Quberi address; the link names one page for you and stops working when you sign out of the tool, lose access to the document or after about ten minutes. An organization owner can turn outside tools off, which ends all of this at once.

Saving notes

quberi_save takes a title, the note text (Markdown) and, optionally, the name of a space. With no space it saves into your personal space. The tool asks the model to offer to save and wait for you to agree, not to save silently, but that is an instruction to the model, not a guarantee: you decide by what you approve and by watching what the model does.

Here the person asked Harness to save the conversation to their personal space. The model calls quberi_save, then says where the note went and when it becomes searchable:

A saved note becomes a document in that space. Anyone who can read that space can find it, so name a shared space only on purpose. Saving is recorded in the audit log (the tool's name and the new document, not the text).

Where in the file a passage is

When your Quberi server records it, each passage comes with its place, so the answer can say where to look in the original: the page of a PDF (page 3, pages 3-4), the slide of a presentation, the sheet and row of a spreadsheet, the heading and paragraph of a Word file, or the lines of a text file. The version is shown when the file has more than one (version 1 (older, replaced by version 2)). A passage read from a scan, or a model's description of a picture, is marked as such, because it can contain mistakes. Nothing is shown for a passage the server gave no place for, and an older server leaves the results exactly as before.

Citing a passage

When your Quberi server sends it, each passage comes with a Cite as: line (for example handbook.pdf, page 3, version 2 (latest)), and the model is asked to end each point it takes from a passage with that line, copied as given, and never to state a page or version the line does not give. This is a request to the model, not something Harness can enforce. A passage with no recorded place is cited by its document alone.

Seeing the page, and reading around a passage

Two more things come with a search result, when your Quberi server supports them.

The page. A passage from a PDF (and text read out of a picture) comes with a link to an image of the page it was found on. The result gives the model a ready-made `` line and tells it to show the page only when you ask to see the original. Slides, spreadsheets and Word files have no page that can be drawn, so they carry no image; their place (slide, sheet and row, paragraph) is still named. Harness only passes on a link that is on your Quberi address and in the page path; any other link is dropped.

The text around it. quberi_read_around returns the text before and after a passage, from the same file and version, so the model can read it in context without you opening the file. The search result gives the model the exact values to pass (document_id, version, char_start, char_end), and the model is told to ask only when you want more context or a passage looks cut off. It does not work for text read from a scan or a picture, which has no text layer to read around, and it says so.

Where a search looks

A text search cannot see pictures, so by default quberi_search looks in both: it returns the matching passages and, beside them, a few pictures that might be what you asked for (for example, asking about "动物母狮" shows the lioness picture even though no document mentions it). The pictures are offered as possible matches, never as the answer, and only ones scoring above a floor are included. Without this, asking for a picture by its subject would have said "nothing found".

In this example the question is "VMC-850 的设备铭牌和开机前检查" (the nameplate of a machine and its pre-start checks). The model searches, then answers from the operating procedure and shows the nameplate picture it found next to the text. The text documents say nothing about the nameplate itself; the picture does.

  • Say "only the documents" or "only pictures" and the model sets kind to text or image.
  • /quberi mode text or /quberi mode image fixes it for you, and overrides the model;

/quberi mode both goes back to the default. In text mode the picture tool refuses. The choice lasts until Harness restarts; set the default with searchMode (below).

  • both needs a Quberi server that supports it. An older server only searches text, and

the plugin simply gets no pictures.

  • Looking for pictures runs Quberi's picture model, so it has its own rate limit. If that

is reached, or picture search is off, the text results still come back.

Finding pictures

quberi_search_images finds pictures from a description ("a red bracket with two holes") in the documents you can read, closest first, optionally in one named space. Harness cannot show a picture a tool returns, but it does show a Markdown image in the model's reply, so each result carries a link to a small preview (a JPEG of at most 320 px) and the model is asked to paste it into its answer exactly as given. Three things follow from that:

  • The link is short-lived (about ten minutes) and names one picture for you. It

works without a sign-in header, so anyone who has the link can open that one small preview until it expires. It stops working at once if you revoke this tool in Quberi, lose access to the space, or the picture is deleted or archived.

  • The model has to copy the link without changing it. That is a request, not a

guarantee: a model can drop or alter it, and then no preview appears. Ask again.

  • The plugin only passes on links that point at your Quberi address, so a reply

cannot send the chat window to some other site. The search runs the same space isolation as text search, and each use is recorded in the audit log (the pictures returned, never your description). It needs a Quberi server with picture search; an older one says so.

Browsing

quberi_list_spaces lists the spaces you can read: your personal space and the team spaces, how many documents each holds, and whether you can edit it (so whether saving or uploading there would work). quberi_list_documents lists the documents in one space you name, newest first: name, type, size, last update and whether it is searchable yet. It returns up to 50 at a time and hands the model a cursor for the next page. Pass type (image, pdf, word, spreadsheet, presentation, text or other) to list only that kind of file; this needs a Quberi server that supports it (an older one ignores the filter).

Asked "which spaces and documents do I have?", the model lists the spaces first and then each space's documents. Pictures are marked as searchable by picture, text files by content.

Both listing tools show file information only. They never return what is inside a document (that is what search is for) and they do not say who uploaded it. They use the same read permission as search and the same live access rules, so a space or document you cannot see in Quberi is not listed. Each use is recorded in the audit log (which kind of listing and how many items, never the names).

How it shows up in Harness

Harness lists a plugin's tool calls as plain rows ("Tool call · quberi_search" plus a summary of the arguments) and does not display custom cards from plugins. What you read is the model's own answer. The tools therefore return plain text, and ask the model to answer in your language, to show spaces as a list and documents as a table, to name the document each point comes from, and not to wrap any of it in a code block. That is a request to the model, not a guarantee, so the layout can vary between models. The upload approval prompt is different: Harness itself shows it, with the file, its size and the destination.

Uploading files

quberi_upload_file sends one file from your current workspace to your personal space, or to a named space you can edit. It exists so Harness can keep a PDF, a Word or Excel file, a slide deck, an image or a text file you point to, without you opening the Quberi web app.

Harness asks before each file leaves the workspace, showing the file, its size and the destination:

Afterwards the model lists what is in the space. Files that are still being indexed are marked as not yet searchable; the saved note is already searchable:

Because a model chooses the path, and a model can be steered by whatever text it read last, three separate checks stand between a path and the network:

  1. You approve every file. Harness shows the exact file, its size, a short

hash and the destination space, and the upload runs only if you allow it. The approval covers that one file once; there is no "always allow". With no approval prompt available (a headless run), or in the "full access, never ask" mode, the upload is refused rather than sent.

  1. Workspace only. The path must stay inside the workspace folder after links

are resolved. Folders such as .git, .ssh and .aws, and names that look like secrets (.env*, secrets.json, credentials.txt, id_rsa*), are refused outright. This filter is best effort, not a guarantee, which is why step 1 exists.

  1. The approved file is the file sent. The file is read again when it is

sent and must match what you approved; if it changed, nothing is uploaded.