@sparkelf/dsh-knowledge-base 0.1.4 → 0.1.20
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.
- package/README.md +129 -2
- package/SKILL.md +86 -18
- package/lib/client.js +13915 -8694
- package/lib/client.js.map +1 -1
- package/lib/index.js +8098 -256
- package/lib/types/api.d.ts +36 -1
- package/lib/types/client/KnowledgeCreateDialog.d.ts +25 -0
- package/lib/types/client/KnowledgeFileTree.d.ts +143 -0
- package/lib/types/client/KnowledgeHome.d.ts +58 -0
- package/lib/types/client/KnowledgeListing.d.ts +7 -0
- package/lib/types/client/KnowledgeNewDocumentDialog.d.ts +32 -0
- package/lib/types/client/KnowledgeProgressPopover.d.ts +69 -0
- package/lib/types/client/KnowledgeSettings.d.ts +4 -3
- package/lib/types/client/KnowledgeTemplates.d.ts +4 -0
- package/lib/types/client/VectorSettingsGroup.d.ts +17 -0
- package/lib/types/client/WorkflowMenuIcon.d.ts +22 -0
- package/lib/types/client/dropTargetPath.d.ts +33 -0
- package/lib/types/client/extractionHistory.d.ts +43 -0
- package/lib/types/client/index.d.ts +32 -14
- package/lib/types/client/listingFilter.d.ts +58 -0
- package/lib/types/client/locales.d.ts +126 -0
- package/lib/types/client/openInSidebar.d.ts +2 -2
- package/lib/types/client/progressRules.d.ts +198 -17
- package/lib/types/client/sanitizeExplorerTabs.d.ts +20 -0
- package/lib/types/client/settingsGate.d.ts +65 -0
- package/lib/types/client/uploadTransport.d.ts +65 -0
- package/lib/types/client/useTreeSort.d.ts +72 -0
- package/lib/types/client/workflows/WorkflowPlaza.d.ts +146 -0
- package/lib/types/client/workflows/cron.d.ts +125 -0
- package/lib/types/client/workflows/dedupe.d.ts +70 -0
- package/lib/types/client/workflows/deps.d.ts +101 -0
- package/lib/types/client/workflows/modelChoice.d.ts +106 -0
- package/lib/types/client/workflows/published.d.ts +43 -0
- package/lib/types/client/workflows/registry.d.ts +98 -0
- package/lib/types/client/workflows/subscribe.d.ts +179 -0
- package/lib/types/embeddings.d.ts +62 -0
- package/lib/types/externalChange.d.ts +25 -0
- package/lib/types/extract.d.ts +32 -0
- package/lib/types/extractionQueue.d.ts +23 -2
- package/lib/types/ftsIndex.d.ts +497 -0
- package/lib/types/index.d.ts +266 -8
- package/lib/types/initialize.d.ts +105 -0
- package/lib/types/knowledgeTools.d.ts +239 -0
- package/lib/types/localStoragePath.d.ts +6 -0
- package/lib/types/localStorageSettings.d.ts +33 -0
- package/lib/types/managementTools.d.ts +184 -0
- package/lib/types/outlineGuard.d.ts +119 -0
- package/lib/types/outlineText.d.ts +134 -0
- package/lib/types/protocol.d.ts +34 -0
- package/lib/types/scopeAliases.d.ts +20 -0
- package/lib/types/trash.d.ts +14 -0
- package/lib/types/vectorIndex.d.ts +113 -0
- package/lib/types/views.d.ts +33 -1
- package/lib/types/workflowPublish.d.ts +114 -0
- package/package.json +7 -7
- package/skills/kb-summarize/SKILL.md +158 -0
- package/skills/kb-summarize/i18n/zh.json +10 -0
- package/skills/kb-vectorize/SKILL.md +57 -0
- package//344/270/207/347/233/270AI/344/275/277/347/224/250/346/225/231/347/250/213.html +294 -0
- package/lib/types/client/KnowledgeProgressPanel.d.ts +0 -53
package/lib/types/api.d.ts
CHANGED
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
*
|
|
13
13
|
* @module @sparkelf/dsh-knowledge-base/api
|
|
14
14
|
*/
|
|
15
|
+
import type { VectorRetrievalConfig } from './embeddings.ts';
|
|
15
16
|
/** Prefix the Host registers and the browser calls. */
|
|
16
17
|
export declare const KB_API_PREFIX = "/knowledge-base/api";
|
|
17
18
|
/** Method names the Host dispatches on. */
|
|
@@ -45,10 +46,14 @@ export declare const KB_API: {
|
|
|
45
46
|
readonly list: "list";
|
|
46
47
|
/** Read one file for the preview, without needing a conversation session. */
|
|
47
48
|
readonly read: "read";
|
|
49
|
+
/** Resolve a kb://doc/<docId>/chunk/<chunkId> token to all page boxes. */
|
|
50
|
+
readonly chunk: "chunk";
|
|
48
51
|
/** Rebuild the caller's visible tree from what DataOps resolves for them. */
|
|
49
52
|
readonly viewsSync: "views.sync";
|
|
50
53
|
/** Rescan the mounted tree and report its shape. */
|
|
51
54
|
readonly index: "index";
|
|
55
|
+
/** Explicitly rebuild the whole optional vector index (requires confirmation). */
|
|
56
|
+
readonly vectorRebuild: "vector.rebuild";
|
|
52
57
|
/**
|
|
53
58
|
* Report the mounted tree's per-directory shape.
|
|
54
59
|
*
|
|
@@ -239,6 +244,8 @@ export interface KnowledgeConfigView {
|
|
|
239
244
|
host: string;
|
|
240
245
|
/** Absolute path of the authoritative tree on the storage host. */
|
|
241
246
|
actualRoot: string;
|
|
247
|
+
/** Local deployments: configured storage path (default `~/kb`). */
|
|
248
|
+
storageRoot?: string;
|
|
242
249
|
/** Absolute path of the caller's view tree on the storage host. */
|
|
243
250
|
viewRoot: string;
|
|
244
251
|
/** Path where the view tree is mounted inside the container. */
|
|
@@ -256,6 +263,10 @@ export interface KnowledgeConfigView {
|
|
|
256
263
|
storageProtocol?: 'nfs' | 'sshfs';
|
|
257
264
|
/** SSHFS transport, present so the panel can show and edit what it will mount. */
|
|
258
265
|
ssh?: KnowledgeSshView;
|
|
266
|
+
/** Optional hybrid retrieval configuration, safe to render (credential reference only). */
|
|
267
|
+
retrieval?: {
|
|
268
|
+
vector: VectorRetrievalConfig;
|
|
269
|
+
};
|
|
259
270
|
}
|
|
260
271
|
/** One transport field the panel may persist. */
|
|
261
272
|
export interface KnowledgeConfigWrite {
|
|
@@ -345,6 +356,28 @@ export interface KnowledgeStatusView {
|
|
|
345
356
|
* with that single name exactly as it did before hierarchy existed. Code that
|
|
346
357
|
* assumed the path was present would break against such a backend.
|
|
347
358
|
*/
|
|
359
|
+
/** Backend DSH permission keys for this caller; used only to hide dead-end menus. */
|
|
360
|
+
permissions?: readonly string[];
|
|
361
|
+
/** Optional vector index coverage/progress. */
|
|
362
|
+
vector?: {
|
|
363
|
+
enabled: boolean;
|
|
364
|
+
provider?: string;
|
|
365
|
+
model?: string;
|
|
366
|
+
embeddedChunks: number;
|
|
367
|
+
totalChunks: number;
|
|
368
|
+
embeddedDocs: number;
|
|
369
|
+
totalDocs: number;
|
|
370
|
+
failed: number;
|
|
371
|
+
canManageVector?: boolean;
|
|
372
|
+
indexing: {
|
|
373
|
+
running: boolean;
|
|
374
|
+
total?: number;
|
|
375
|
+
done?: number;
|
|
376
|
+
embedded?: number;
|
|
377
|
+
failed?: number;
|
|
378
|
+
error?: string;
|
|
379
|
+
};
|
|
380
|
+
};
|
|
348
381
|
caller?: {
|
|
349
382
|
userId: string;
|
|
350
383
|
label: string;
|
|
@@ -583,7 +616,7 @@ export interface KnowledgeTemplateSaveInput {
|
|
|
583
616
|
id?: string;
|
|
584
617
|
}
|
|
585
618
|
/** Where one extraction task is in its lifecycle, as the Host reports it. */
|
|
586
|
-
export type ExtractionStateView = 'pending' | 'running' | 'succeeded' | 'failed' | 'unsupported';
|
|
619
|
+
export type ExtractionStateView = 'pending' | 'running' | 'succeeded' | 'failed' | 'unsupported' | 'already-markdown';
|
|
587
620
|
/**
|
|
588
621
|
* One extraction task.
|
|
589
622
|
*
|
|
@@ -596,6 +629,8 @@ export interface ExtractionTaskView {
|
|
|
596
629
|
relPath: string;
|
|
597
630
|
/** Where the task is in its lifecycle. */
|
|
598
631
|
state: ExtractionStateView;
|
|
632
|
+
/** Current Agentic RAG stage (parse/chunk/index/done), when running. */
|
|
633
|
+
step?: 'parse' | 'chunk' | 'index' | 'done';
|
|
599
634
|
/** When the task was accepted, ISO-8601. */
|
|
600
635
|
queuedAt: string;
|
|
601
636
|
/** When the run started, ISO-8601. */
|
|
@@ -22,6 +22,8 @@
|
|
|
22
22
|
*
|
|
23
23
|
* @module @sparkelf/dsh-knowledge-base/client
|
|
24
24
|
*/
|
|
25
|
+
import type { TreeClipboard } from './KnowledgeContextMenu.tsx';
|
|
26
|
+
import type { FileTreeSort } from 'dsh-better-sidebar/src/client/file-tree-sort.ts';
|
|
25
27
|
/**
|
|
26
28
|
* Where a create or upload should land when the reader has not said otherwise.
|
|
27
29
|
*
|
|
@@ -118,6 +120,29 @@ export interface KnowledgeCreateDialogProps {
|
|
|
118
120
|
onClose: () => void;
|
|
119
121
|
/** The directory the dialog should start in, from {@link defaultDestination}. */
|
|
120
122
|
defaultPath: string;
|
|
123
|
+
/** Absolute mount root, for the upload tree (the same root the sidebar uses). */
|
|
124
|
+
root?: string;
|
|
125
|
+
/** Caller identity, so personal extraction rows can be addressed authoritatively. */
|
|
126
|
+
callerId?: string;
|
|
127
|
+
/** Real session key for the borrowed explorer; absent uses the KB placeholder. */
|
|
128
|
+
sessionId?: string;
|
|
129
|
+
/** Locale tag for tree dates and labels. */
|
|
130
|
+
locale?: string;
|
|
131
|
+
/** The same bucket labels the sidebar tree takes. */
|
|
132
|
+
bucketLabels?: Readonly<Record<string, string>>;
|
|
133
|
+
/** The same department code/name chain the sidebar tree takes. */
|
|
134
|
+
departmentPath?: {
|
|
135
|
+
codes: readonly string[];
|
|
136
|
+
names: readonly string[];
|
|
137
|
+
};
|
|
138
|
+
/** The same explorer ordering the sidebar tree takes. */
|
|
139
|
+
sort?: FileTreeSort;
|
|
140
|
+
isFavorite?: (relPath: string) => boolean;
|
|
141
|
+
onToggleFavorite?: (relPath: string, next: boolean) => void;
|
|
142
|
+
onShare?: (relPath: string, isDir: boolean) => void;
|
|
143
|
+
onClipboard?: (entry: TreeClipboard) => void;
|
|
144
|
+
hasClipboard?: boolean;
|
|
145
|
+
onPasteInto?: (directory: string) => void;
|
|
121
146
|
/** Locale-bound copy resolver. */
|
|
122
147
|
t: (key: string) => string;
|
|
123
148
|
/**
|
|
@@ -21,8 +21,36 @@
|
|
|
21
21
|
* a reader should rename. They are filtered with the `exclude` prop, which the host
|
|
22
22
|
* applies to the listing -- so they never arrive rather than being hidden after the fact.
|
|
23
23
|
*
|
|
24
|
+
* ## This bundle INLINES the explorer's source, which is why sort needs a sync step
|
|
25
|
+
*
|
|
26
|
+
* `FileTree` is imported as SOURCE (`dsh-better-sidebar/src/client/FileTree.tsx`), not as
|
|
27
|
+
* the package's built output, so its code is compiled into this plugin's bundle. Sorting
|
|
28
|
+
* lives in two places that this file depends on:
|
|
29
|
+
*
|
|
30
|
+
* - `file-tree-sort.ts` — the sort keys and comparators (a separate module, imported by
|
|
31
|
+
* `FileTree.tsx`);
|
|
32
|
+
* - `listing-filter.ts` — the name-matching rule set, shared by the explorer and this
|
|
33
|
+
* plugin's list view. It lives in the explorer package, not here, precisely so the two
|
|
34
|
+
* surfaces cannot drift apart: `KnowledgeListing` imports it from there too, and there
|
|
35
|
+
* is only ONE implementation of "substring, case-insensitive, keep the parent chain".
|
|
36
|
+
* It also has to be synced, or the tree's `nameFilter` prop arrives with nothing to run;
|
|
37
|
+
* - `fs-tree.ts` — the HOST side that puts `mtimeMs`/`size` on each row;
|
|
38
|
+
* - `sidebar.module.css` / `locales.ts` — the visible row for "no file matched" and its
|
|
39
|
+
* two strings.
|
|
40
|
+
*
|
|
41
|
+
* That means a change to those files reaches this bundle by COPYING THE SOURCE into the
|
|
42
|
+
* resolved package under `node_modules/.pnpm/@sparkelf+dsh-better-sidebar@.../` and
|
|
43
|
+
* rebuilding here. It does NOT arrive by reinstalling the dependency from npm, and the
|
|
44
|
+
* copy is LOST on a fresh `install` — at which point `sort` silently falls back to the
|
|
45
|
+
* published keys (no `mtime`, no `size`) and the menu's choices stop matching the data.
|
|
46
|
+
*
|
|
47
|
+
* The durable source of truth is the fork at `/root/projects/DSH-better-sidebar`,
|
|
48
|
+
* branch `sparkelf/kb-save-events`. Reinstalling the dependency therefore means: rebuild
|
|
49
|
+
* and publish from that branch, bump the dependency, and delete this note.
|
|
50
|
+
*
|
|
24
51
|
* @module @sparkelf/dsh-knowledge-base/client
|
|
25
52
|
*/
|
|
53
|
+
import type { FileTreeSort } from 'dsh-better-sidebar/src/client/file-tree-sort.ts';
|
|
26
54
|
import type { UploadItem } from 'dsh-better-sidebar/src/client/upload.ts';
|
|
27
55
|
import { type DepartmentPath } from './departmentFolders.ts';
|
|
28
56
|
export interface KnowledgeFileTreeProps {
|
|
@@ -46,12 +74,33 @@ export interface KnowledgeFileTreeProps {
|
|
|
46
74
|
busy: boolean;
|
|
47
75
|
/** Bump to reload the visible set after a change made elsewhere. */
|
|
48
76
|
refreshTick: number;
|
|
77
|
+
/**
|
|
78
|
+
* The caller's DataOps user id, when the page knows it.
|
|
79
|
+
*
|
|
80
|
+
* The tree renders the caller's VIEW, where `personal` hides the owner segment. The
|
|
81
|
+
* Host reads the AUTHORITATIVE tree, where that segment is required, so an extraction
|
|
82
|
+
* requested from a personal row must put the id back before it leaves the browser.
|
|
83
|
+
* Without it the Host answers `404 no such file` for a document the reader can see.
|
|
84
|
+
*/
|
|
85
|
+
callerId?: string;
|
|
49
86
|
/** Called after the explorer's own inline rename lands. */
|
|
50
87
|
onPathRenamed?: (oldPath: string, newPath: string) => void;
|
|
51
88
|
/** Called after the explorer's own delete lands. */
|
|
52
89
|
onPathDeleted?: (path: string, isDir: boolean) => void;
|
|
53
90
|
/** Whether the owning surface is on screen. */
|
|
54
91
|
visible?: boolean;
|
|
92
|
+
/**
|
|
93
|
+
* Hide the explorer's root row. A destination picker draws its own root row so
|
|
94
|
+
* selecting the mount root is a click, not an expansion.
|
|
95
|
+
*/
|
|
96
|
+
hideRoot?: boolean;
|
|
97
|
+
/**
|
|
98
|
+
* Tree-relative path to paint as selected. Used by the upload destination picker;
|
|
99
|
+
* `''` is the mount root (the picker draws that row itself).
|
|
100
|
+
*/
|
|
101
|
+
selectedPath?: string;
|
|
102
|
+
/** Locale tag for row dates; absent uses the document language. */
|
|
103
|
+
locale?: string;
|
|
55
104
|
/**
|
|
56
105
|
* Say the three buckets in the reader's language.
|
|
57
106
|
*
|
|
@@ -87,8 +136,102 @@ export interface KnowledgeFileTreeProps {
|
|
|
87
136
|
* caller has no favourites store, which keeps the wrapper from touching the DOM at all.
|
|
88
137
|
*/
|
|
89
138
|
isFavorite?: (relPath: string) => boolean;
|
|
139
|
+
/** Toggle the caller's favourite flag for one document. */
|
|
140
|
+
onToggleFavorite?: (relPath: string, next: boolean) => void;
|
|
90
141
|
/** The favourites star's accessible name. */
|
|
91
142
|
favoriteMarkLabel?: string;
|
|
143
|
+
/**
|
|
144
|
+
* Open the Share dialog for one row.
|
|
145
|
+
*
|
|
146
|
+
* The dialog itself lives on the page, not in this wrapper: it is a `Modal`, and the
|
|
147
|
+
* page already owns one for its own surfaces. This hook exists so the native menu can
|
|
148
|
+
* offer the entry without this component importing a dialog (which would mount a second
|
|
149
|
+
* one per tree instance and tie a page-level overlay to a widget's lifecycle).
|
|
150
|
+
*/
|
|
151
|
+
onShare?: (relPath: string, isDir: boolean) => void;
|
|
152
|
+
/**
|
|
153
|
+
* What the cut/copy entries put on the clipboard.
|
|
154
|
+
*
|
|
155
|
+
* The clipboard belongs to the page: a copy from this tree has to paste on the table,
|
|
156
|
+
* and vice versa. Passing it in keeps ONE clipboard rather than a per-surface copy that
|
|
157
|
+
* would disagree about what "paste" means.
|
|
158
|
+
*/
|
|
159
|
+
onClipboard?: (entry: {
|
|
160
|
+
entries: Array<{
|
|
161
|
+
relPath: string;
|
|
162
|
+
name: string;
|
|
163
|
+
}>;
|
|
164
|
+
cut: boolean;
|
|
165
|
+
}) => void;
|
|
166
|
+
/**
|
|
167
|
+
* Whether the clipboard currently holds anything.
|
|
168
|
+
*
|
|
169
|
+
* The Paste row is hidden rather than disabled while this is false: an entry that can
|
|
170
|
+
* never run in this state advertises an action the reader cannot take.
|
|
171
|
+
*/
|
|
172
|
+
hasClipboard?: boolean;
|
|
173
|
+
/**
|
|
174
|
+
* Paste the clipboard into one directory (tree-relative, `''` for the root).
|
|
175
|
+
*
|
|
176
|
+
* The page performs the move/copy and clears the clipboard on a cut; this wrapper only
|
|
177
|
+
* reports where the click landed.
|
|
178
|
+
*/
|
|
179
|
+
onPasteInto?: (directory: string) => void;
|
|
180
|
+
/**
|
|
181
|
+
* Called the moment an extraction is REQUESTED for one document, before it settles.
|
|
182
|
+
*
|
|
183
|
+
* Carries the path so the progress panel can show that document as queued straight away:
|
|
184
|
+
* a menu item that produces no visible change until a round trip finishes reads as a dead
|
|
185
|
+
* control. The panel treats this as a guess with a lifetime, and replaces it with the
|
|
186
|
+
* Host's own task as soon as one is reported.
|
|
187
|
+
*/
|
|
188
|
+
onExtractionQueued?: (relPath: string) => void;
|
|
189
|
+
/**
|
|
190
|
+
* Called when an extraction request was refused or never completed.
|
|
191
|
+
*
|
|
192
|
+
* Exists because the menu used to discard the response: a refusal was indistinguishable
|
|
193
|
+
* from a success, so the reader had nothing to act on.
|
|
194
|
+
*/
|
|
195
|
+
onExtractionFailed?: (relPath: string, reason: string) => void;
|
|
196
|
+
/**
|
|
197
|
+
* How to order the rows.
|
|
198
|
+
*
|
|
199
|
+
* Passed straight through to the explorer's own `sort` prop, so the ordering logic and
|
|
200
|
+
* its comparators stay in one place. Omitted keeps the explorer's default.
|
|
201
|
+
*/
|
|
202
|
+
sort?: FileTreeSort;
|
|
203
|
+
/**
|
|
204
|
+
* Narrow the visible rows to names containing this text.
|
|
205
|
+
*
|
|
206
|
+
* Passed straight to the explorer, which applies the same rule set the listing view
|
|
207
|
+
* uses (`listing-filter.ts`) to the levels it has already loaded: typing therefore costs
|
|
208
|
+
* no request, a hit inside a collapsed folder keeps its parent chain visible, and
|
|
209
|
+
* expansion state is untouched so clearing the term restores what was on screen.
|
|
210
|
+
*/
|
|
211
|
+
nameFilter?: string;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Add the knowledge actions to the explorer's native row menu.
|
|
215
|
+
*
|
|
216
|
+
* The installed explorer builds that menu internally and does not consume the
|
|
217
|
+
* `extraMenuItems` prop yet, so appending is done at the one place the menu is
|
|
218
|
+
* visible: after it opens. The clone keeps the menu's own row/typography classes;
|
|
219
|
+
* the handler closes the menu with Escape, exactly like choosing a native row.
|
|
220
|
+
*
|
|
221
|
+
* The contextmenu listener is a normal bubble-phase React handler that only records
|
|
222
|
+
* the row; it never prevents the explorer's own menu from opening.
|
|
223
|
+
*/
|
|
224
|
+
export interface KnowledgeTreeMenuAction {
|
|
225
|
+
id: string;
|
|
226
|
+
label: string;
|
|
227
|
+
when: (target: {
|
|
228
|
+
relPath: string;
|
|
229
|
+
isDir: boolean;
|
|
230
|
+
}) => boolean;
|
|
231
|
+
run: (target: {
|
|
232
|
+
relPath: string;
|
|
233
|
+
isDir: boolean;
|
|
234
|
+
}) => void;
|
|
92
235
|
}
|
|
93
236
|
/**
|
|
94
237
|
* The knowledge tree, rendered by the product's file explorer.
|
|
@@ -15,16 +15,35 @@
|
|
|
15
15
|
*
|
|
16
16
|
* @module @sparkelf/dsh-knowledge-base/client
|
|
17
17
|
*/
|
|
18
|
+
/** One document row, as the table renders it. */
|
|
19
|
+
interface HomeRow {
|
|
20
|
+
/** Path relative to the mount point. */
|
|
21
|
+
relPath: string;
|
|
22
|
+
/** File name alone. */
|
|
23
|
+
name: string;
|
|
24
|
+
/** Directory the file sits in, for the Location column. */
|
|
25
|
+
location: string;
|
|
26
|
+
/** Last-modified instant in Unix ms, which is the tree's only timestamp. */
|
|
27
|
+
mtimeMs?: number;
|
|
28
|
+
}
|
|
18
29
|
/** Props for the Home surface. */
|
|
19
30
|
export interface KnowledgeHomeProps {
|
|
20
31
|
/** Locale-bound copy resolver. */
|
|
21
32
|
t: (key: string) => string;
|
|
33
|
+
/** Real session key for the borrowed file explorer; absent uses its placeholder. */
|
|
34
|
+
sessionId?: string;
|
|
35
|
+
/** The same explorer ordering the sidebar tree takes. */
|
|
36
|
+
sort?: import('dsh-better-sidebar/src/client/file-tree-sort.ts').FileTreeSort;
|
|
22
37
|
/** Locale tag, so dates match the reader's language. */
|
|
23
38
|
locale?: string;
|
|
24
39
|
/** Disabled when the tree is not mounted, so the cards cannot promise a tree. */
|
|
25
40
|
mountPoint: string;
|
|
26
41
|
/** Open one document in the preview. */
|
|
27
42
|
onOpen: (path: string) => void;
|
|
43
|
+
/** The client context, used to open a Session from the new-document chooser. */
|
|
44
|
+
ctx?: unknown;
|
|
45
|
+
/** Authoritative storage root, used when a template is materialized for the agent. */
|
|
46
|
+
actualRoot?: string;
|
|
28
47
|
/**
|
|
29
48
|
* The caller's DataOps id, when the status route reported one.
|
|
30
49
|
*
|
|
@@ -37,6 +56,25 @@ export interface KnowledgeHomeProps {
|
|
|
37
56
|
departmentCode?: string;
|
|
38
57
|
/** The caller's own department name; the code stands in when this is absent. */
|
|
39
58
|
departmentName?: string;
|
|
59
|
+
/**
|
|
60
|
+
* Display names for the three buckets.
|
|
61
|
+
*
|
|
62
|
+
* The same map the file tree uses, so one vocabulary covers both surfaces: a folder
|
|
63
|
+
* called `personal` on disk reads as 「个人」 in the tree AND in this table's Location
|
|
64
|
+
* column. A second mapping table here is exactly the two-truths defect this reuses the
|
|
65
|
+
* tree's helper to avoid.
|
|
66
|
+
*/
|
|
67
|
+
bucketLabels?: Readonly<Record<string, string>>;
|
|
68
|
+
/**
|
|
69
|
+
* The caller's organization chain, codes first and names aligned.
|
|
70
|
+
*
|
|
71
|
+
* Passed the same way the tree takes it, so a nested department path reads as
|
|
72
|
+
* 「部门/数据平台」 here instead of `department/data-platform`.
|
|
73
|
+
*/
|
|
74
|
+
departmentPath?: {
|
|
75
|
+
codes: readonly string[];
|
|
76
|
+
names: readonly string[];
|
|
77
|
+
};
|
|
40
78
|
/**
|
|
41
79
|
* Whether the Host verified this caller may manage grants.
|
|
42
80
|
*
|
|
@@ -96,6 +134,25 @@ export interface KnowledgeHomeProps {
|
|
|
96
134
|
file: unknown;
|
|
97
135
|
relativePath: string;
|
|
98
136
|
}[]) => void;
|
|
137
|
+
/**
|
|
138
|
+
* Read the document rows for this mount.
|
|
139
|
+
*
|
|
140
|
+
* TEST SEAM, NOT AN EXTENSION POINT. It exists so a test can count how many times the
|
|
141
|
+
* table re-reads when `refreshTick` bumps -- the only way to tell "the table refreshed"
|
|
142
|
+
* apart from "a row happened to appear". It is optional and defaults to the real
|
|
143
|
+
* implementation below, so production behaviour is unchanged; do not use it as a hook
|
|
144
|
+
* for new features.
|
|
145
|
+
*/
|
|
146
|
+
readHomeRows?: (mountPoint: string) => Promise<HomeRow[]>;
|
|
147
|
+
/**
|
|
148
|
+
* Re-read trigger.
|
|
149
|
+
*
|
|
150
|
+
* A file uploaded from anywhere in the panel changes what this table should list, and
|
|
151
|
+
* the panel already bumps one counter for exactly that. Without this the tree refreshed
|
|
152
|
+
* and the table did not, so a reader who had just uploaded a file could not find it --
|
|
153
|
+
* indistinguishable from the upload having failed.
|
|
154
|
+
*/
|
|
155
|
+
refreshTick?: number;
|
|
99
156
|
/**
|
|
100
157
|
* Where a drop on this table lands, tree-relative.
|
|
101
158
|
*
|
|
@@ -111,3 +168,4 @@ export interface KnowledgeHomeProps {
|
|
|
111
168
|
* @returns The Home view.
|
|
112
169
|
*/
|
|
113
170
|
export declare function KnowledgeHome(props: KnowledgeHomeProps): import("react").JSX.Element;
|
|
171
|
+
export {};
|
|
@@ -125,6 +125,13 @@ export interface KnowledgeListingProps {
|
|
|
125
125
|
* are already visible.
|
|
126
126
|
*/
|
|
127
127
|
expandAll?: boolean;
|
|
128
|
+
/**
|
|
129
|
+
* Restrict the rows to these pinned paths and their ancestors.
|
|
130
|
+
*
|
|
131
|
+
* The pinned band is a list of pins, not a second copy of the whole tree: without
|
|
132
|
+
* this the band rendered every top-level entry and called all of them pinned.
|
|
133
|
+
*/
|
|
134
|
+
pinnedPaths?: readonly string[];
|
|
128
135
|
/**
|
|
129
136
|
* The action offered when the tree genuinely holds no documents.
|
|
130
137
|
*
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Home surface's "New" chooser.
|
|
3
|
+
*
|
|
4
|
+
* A new document is not a file-manager operation here: it starts a conversation
|
|
5
|
+
* that writes the document. The dialog therefore asks what kind of artefact the
|
|
6
|
+
* reader wants and hands the prompt to the conversation surface, instead of
|
|
7
|
+
* asking for a file name and a directory the reader has not opened yet.
|
|
8
|
+
*
|
|
9
|
+
* @module @sparkelf/dsh-knowledge-base/client
|
|
10
|
+
*/
|
|
11
|
+
import type { ReactNode } from 'react';
|
|
12
|
+
/** The document kinds the conversation can create. */
|
|
13
|
+
export type NewDocumentKind = 'document' | 'spreadsheet' | 'presentation';
|
|
14
|
+
/** Props for the chooser. */
|
|
15
|
+
export interface KnowledgeNewDocumentDialogProps {
|
|
16
|
+
/** Whether the dialog is showing. */
|
|
17
|
+
open: boolean;
|
|
18
|
+
/** Close without choosing a type. */
|
|
19
|
+
onClose: () => void;
|
|
20
|
+
/** Start a conversation with the chosen prompt, caret after "一份". */
|
|
21
|
+
onCreate: (prompt: string, caretOffset: number) => void;
|
|
22
|
+
/** Open the conventional folder form instead. */
|
|
23
|
+
onNewFolder: () => void;
|
|
24
|
+
/** Locale-bound copy resolver. */
|
|
25
|
+
t: (key: string) => string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Render the type chooser.
|
|
29
|
+
* @param props - open state and the two actions.
|
|
30
|
+
* @returns The dialog.
|
|
31
|
+
*/
|
|
32
|
+
export declare function KnowledgeNewDocumentDialog(props: KnowledgeNewDocumentDialogProps): ReactNode;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The progress notification button and its panel.
|
|
3
|
+
*
|
|
4
|
+
* Uploading a document and extracting its text are two waits a reader cannot see
|
|
5
|
+
* otherwise: a dropped file looks like nothing happened until the bytes land, and a
|
|
6
|
+
* scanned PDF looks uploaded while its `.md` sibling is still being produced.
|
|
7
|
+
*
|
|
8
|
+
* This is the notification form of that information: a bell in the panel header whose
|
|
9
|
+
* badge counts the work still in flight, opening a panel that names every task. It
|
|
10
|
+
* replaces an earlier strip pinned to the panel's foot, which was too narrow -- file
|
|
11
|
+
* names were cut to a few characters ("中电信桂【2025】150号…"), which is exactly the
|
|
12
|
+
* detail a reader needs to tell two uploads apart.
|
|
13
|
+
*
|
|
14
|
+
* Only the PRESENTATION lives here. The upload rows come from the panel's own upload
|
|
15
|
+
* code and the extraction rows from `extract.status`; this module reads and retries,
|
|
16
|
+
* it does not own either data path.
|
|
17
|
+
*
|
|
18
|
+
* @module @sparkelf/dsh-knowledge-base/client
|
|
19
|
+
*/
|
|
20
|
+
import type { FailedExtractionView, OptimisticExtraction } from './progressRules.ts';
|
|
21
|
+
import type { UploadTaskView } from './progressRules.ts';
|
|
22
|
+
/** Props for the notification button and panel. */
|
|
23
|
+
export interface KnowledgeProgressPopoverProps {
|
|
24
|
+
/** Locale-bound copy resolver. */
|
|
25
|
+
t: (key: string) => string;
|
|
26
|
+
/** The batch currently uploading, oldest first; empty when nothing is in flight. */
|
|
27
|
+
uploads: readonly UploadTaskView[];
|
|
28
|
+
/**
|
|
29
|
+
* Whether to read extraction progress at all.
|
|
30
|
+
*
|
|
31
|
+
* False on a surface that cannot extract (no mount): polling a route whose answer can
|
|
32
|
+
* never be acted on costs a request per reader and buys nothing.
|
|
33
|
+
*/
|
|
34
|
+
watchExtraction: boolean;
|
|
35
|
+
/** Called after a retry was accepted, so the caller can refresh its own views. */
|
|
36
|
+
onRetried?: (relPath: string) => void;
|
|
37
|
+
/**
|
|
38
|
+
* A counter the page bumps when extraction changed outside this panel's own polling.
|
|
39
|
+
*
|
|
40
|
+
* The panel polls only while it already knows about pending work, so an extraction
|
|
41
|
+
* queued from a context menu -- exactly the case where it knows about none -- would
|
|
42
|
+
* never appear. Watching a counter makes that one re-read reachable without adding a
|
|
43
|
+
* second timer.
|
|
44
|
+
*/
|
|
45
|
+
refreshSignal?: number;
|
|
46
|
+
/**
|
|
47
|
+
* Documents the reader asked to extract that the Host has not reported yet.
|
|
48
|
+
*
|
|
49
|
+
* Drawn as a "queued" row so the click has a visible answer before the round trip
|
|
50
|
+
* finishes. Each entry is replaced by the Host's own task the moment `extract.status`
|
|
51
|
+
* mentions it, and expires on its own when it is never confirmed.
|
|
52
|
+
*/
|
|
53
|
+
optimistic?: readonly OptimisticExtraction[];
|
|
54
|
+
/**
|
|
55
|
+
* Requests this page session saw refused before the Host created a task.
|
|
56
|
+
*
|
|
57
|
+
* `extract.retry` answers 404/403 before it enqueues anything, so the Host's snapshot
|
|
58
|
+
* never mentions those failures. Without these rows the panel would show an empty state
|
|
59
|
+
* right after the reader watched an extraction fail -- the exact silence this panel
|
|
60
|
+
* exists to remove. The page owns the store; this component only draws it.
|
|
61
|
+
*/
|
|
62
|
+
failures?: readonly FailedExtractionView[];
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* The notification button and its progress panel.
|
|
66
|
+
* @param props - the upload batch, whether to watch extraction, and the copy resolver.
|
|
67
|
+
* @returns The button, plus the panel while it is open.
|
|
68
|
+
*/
|
|
69
|
+
export declare function KnowledgeProgressPopover(props: KnowledgeProgressPopoverProps): import("react").JSX.Element;
|
|
@@ -22,9 +22,10 @@
|
|
|
22
22
|
/**
|
|
23
23
|
* The settings surface of the management page.
|
|
24
24
|
*
|
|
25
|
-
* This page
|
|
26
|
-
*
|
|
27
|
-
*
|
|
25
|
+
* This page carries the review switch and the shared vector-retrieval group: the
|
|
26
|
+
* switch is a DECISION about whether other people's contributions take effect
|
|
27
|
+
* immediately, so it needs write access; the vector group is the same component the
|
|
28
|
+
* DSH settings section renders, which keeps a profile without that slot usable. The queue that decision governs and the trail of what it settled both
|
|
28
29
|
* moved to the Audit page, which is the surface an operator opens to get through
|
|
29
30
|
* work; parking a worklist under a configuration switch made them scroll past the
|
|
30
31
|
* setting to reach today's arrivals, and left two duplicate entry points pointing
|
|
@@ -32,8 +32,12 @@ export interface KnowledgeTemplatesProps {
|
|
|
32
32
|
mountPoint?: string;
|
|
33
33
|
/** The caller's id, so the destination default prefers their own folder. */
|
|
34
34
|
callerId?: string;
|
|
35
|
+
/** Authoritative storage root, where a materialized template is readable by the agent. */
|
|
36
|
+
actualRoot?: string;
|
|
35
37
|
/** Open a document once it has been created from a template. */
|
|
36
38
|
onOpen?: (relPath: string) => void;
|
|
39
|
+
/** Start a conversation that references the materialized template file. */
|
|
40
|
+
onStartSession?: (prompt: string) => void;
|
|
37
41
|
}
|
|
38
42
|
/**
|
|
39
43
|
* Render the template library.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared "vector retrieval" settings group.
|
|
3
|
+
*
|
|
4
|
+
* One component owns the config/status reads, the save call and the rebuild poll so
|
|
5
|
+
* the DSH Settings section and the knowledge-base panel's own Settings page cannot
|
|
6
|
+
* drift. The group is deliberately self-loading: a profile that never mounts
|
|
7
|
+
* `settings.section` still gets the same controls because the panel renders this
|
|
8
|
+
* component directly.
|
|
9
|
+
*
|
|
10
|
+
* @module @sparkelf/dsh-knowledge-base/client
|
|
11
|
+
*/
|
|
12
|
+
/** Copy resolver; accepts both the DSH settings locale function and the panel one. */
|
|
13
|
+
export type VectorSettingsT = (key: any) => string;
|
|
14
|
+
/** One self-contained vector settings group. */
|
|
15
|
+
export declare function VectorSettingsGroup({ t }: {
|
|
16
|
+
t: VectorSettingsT;
|
|
17
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The glyph the left sidebar renders for the 「工作流广场」 entry.
|
|
3
|
+
*
|
|
4
|
+
* A calendar outline rather than the knowledge-base document glyph: two entries with
|
|
5
|
+
* the same artwork would be indistinguishable on the rail. Sized by the sidebar and
|
|
6
|
+
* coloured by `currentColor`, so it follows the selected/idle row state.
|
|
7
|
+
*
|
|
8
|
+
* @module @sparkelf/dsh-knowledge-base/client
|
|
9
|
+
*/
|
|
10
|
+
/** Props the sidebar list passes to one entry. */
|
|
11
|
+
export interface WorkflowMenuIconProps {
|
|
12
|
+
/** Glyph edge length in pixels, chosen by the sidebar for its current width. */
|
|
13
|
+
size?: number;
|
|
14
|
+
/** Whether this entry is the selected panel. */
|
|
15
|
+
active?: boolean;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Render the workflow-plaza glyph.
|
|
19
|
+
* @param props - sidebar-supplied glyph size.
|
|
20
|
+
* @returns The calendar outline sized for the sidebar rail.
|
|
21
|
+
*/
|
|
22
|
+
export declare function WorkflowMenuIcon(props: WorkflowMenuIconProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where a dropped file actually lands.
|
|
3
|
+
*
|
|
4
|
+
* The tree shows a reader a `personal` folder, but the authoritative tree stores every
|
|
5
|
+
* caller's documents under their own id (`personal/<owner>/<file>`) -- the owner segment
|
|
6
|
+
* is hidden from the view on purpose, because it is an implementation detail a reader
|
|
7
|
+
* never typed. The consequence is that a tree row labelled 「个人」 carries the path
|
|
8
|
+
* `personal`, and writing straight to it puts the file in `personal/` beside the owner
|
|
9
|
+
* directories, where no view will ever show it: the reader uploads, the progress row says
|
|
10
|
+
* "done", and the file is invisible.
|
|
11
|
+
*
|
|
12
|
+
* This module owns that translation so every drop entry point (the borrowed explorer, the
|
|
13
|
+
* plugin's own listing, the Home table) answers the same question the same way.
|
|
14
|
+
*
|
|
15
|
+
* @module @sparkelf/dsh-knowledge-base/client
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Resolve a view-relative directory into the authoritative path a write must use.
|
|
19
|
+
*
|
|
20
|
+
* A `personal` path gains the caller's id as its second segment, at whatever depth the
|
|
21
|
+
* drop names: the bucket row (`personal`), a folder inside it (`personal/specs`), or one
|
|
22
|
+
* nested deeper all resolve to the caller's own subtree. Everything else (`global`,
|
|
23
|
+
* `department/...`, `''` for the mount root) is already authoritative and passes through.
|
|
24
|
+
*
|
|
25
|
+
* A `personal` path with no caller id is REFUSED rather than passed through. Writing to
|
|
26
|
+
* `personal` without an owner is exactly the defect this function exists to prevent, so
|
|
27
|
+
* the refusal is explicit: `undefined` means "no safe destination", and the caller reports
|
|
28
|
+
* it instead of writing somewhere the reader cannot see.
|
|
29
|
+
* @param viewRelDir - the directory as the VIEW names it (what a tree row carries).
|
|
30
|
+
* @param callerId - the id the Host reports for the caller, when it is known.
|
|
31
|
+
* @returns The authoritative relative directory, or undefined when it cannot be resolved.
|
|
32
|
+
*/
|
|
33
|
+
export declare function resolveUploadDir(viewRelDir: string, callerId: string | undefined): string | undefined;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Failures this browser session saw that the Host has no task for.
|
|
3
|
+
*
|
|
4
|
+
* A refused extraction never reaches `extract.status`: the Host answers 404 before it
|
|
5
|
+
* creates a queue entry, so the progress panel -- which reads only the Host's snapshot --
|
|
6
|
+
* could not show the one failure the reader just hit. This store is the panel's own
|
|
7
|
+
* memory of those refusals.
|
|
8
|
+
*
|
|
9
|
+
* It lives at module scope rather than in component state for one reason: the knowledge
|
|
10
|
+
* panel unmounts when the reader visits another destination, and a failure that vanished
|
|
11
|
+
* on navigation would be indistinguishable from one the feature never recorded. The
|
|
12
|
+
* store is per page load, which is the "this session" the reader means -- a reload is a
|
|
13
|
+
* new session, and the filesystem (not this array) remains the authority on disk.
|
|
14
|
+
*
|
|
15
|
+
* @module @sparkelf/dsh-knowledge-base/client
|
|
16
|
+
*/
|
|
17
|
+
import type { FailedExtractionView } from './progressRules.ts';
|
|
18
|
+
/** Most failures kept; an unbounded array would grow for the life of the tab. */
|
|
19
|
+
export declare const SESSION_FAILURE_LIMIT = 50;
|
|
20
|
+
/**
|
|
21
|
+
* Record one refused extraction.
|
|
22
|
+
*
|
|
23
|
+
* Re-recording a path REPLACES its earlier reason and moves it to the end: a reader who
|
|
24
|
+
* retried and failed differently needs the newest reason, and the list reads newest-last.
|
|
25
|
+
* @param entry - the path, the raw reason, and when it was observed (defaults to now).
|
|
26
|
+
*/
|
|
27
|
+
export declare function rememberExtractionFailure(entry: {
|
|
28
|
+
relPath: string;
|
|
29
|
+
reason: string;
|
|
30
|
+
at?: number;
|
|
31
|
+
}): void;
|
|
32
|
+
/**
|
|
33
|
+
* Read the session's failures.
|
|
34
|
+
* @returns A copy, so a caller cannot mutate the store by accident.
|
|
35
|
+
*/
|
|
36
|
+
export declare function readExtractionFailures(): FailedExtractionView[];
|
|
37
|
+
/**
|
|
38
|
+
* Drop one path's recorded failure, e.g. after a retry was accepted.
|
|
39
|
+
* @param relPath - the document whose failure is no longer current.
|
|
40
|
+
*/
|
|
41
|
+
export declare function forgetExtractionFailure(relPath: string): void;
|
|
42
|
+
/** Clear every recorded failure. Exists for tests; no production path calls it. */
|
|
43
|
+
export declare function clearExtractionFailures(): void;
|