@sparkelf/dsh-knowledge-base 0.1.5 → 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.
Files changed (58) hide show
  1. package/README.md +129 -2
  2. package/SKILL.md +86 -18
  3. package/lib/client.js +14766 -9663
  4. package/lib/client.js.map +1 -1
  5. package/lib/index.js +8082 -258
  6. package/lib/types/api.d.ts +36 -1
  7. package/lib/types/client/KnowledgeCreateDialog.d.ts +25 -0
  8. package/lib/types/client/KnowledgeFileTree.d.ts +143 -0
  9. package/lib/types/client/KnowledgeHome.d.ts +58 -0
  10. package/lib/types/client/KnowledgeListing.d.ts +7 -0
  11. package/lib/types/client/KnowledgeNewDocumentDialog.d.ts +32 -0
  12. package/lib/types/client/KnowledgeProgressPopover.d.ts +69 -0
  13. package/lib/types/client/KnowledgeSettings.d.ts +4 -3
  14. package/lib/types/client/KnowledgeTemplates.d.ts +4 -0
  15. package/lib/types/client/VectorSettingsGroup.d.ts +17 -0
  16. package/lib/types/client/WorkflowMenuIcon.d.ts +22 -0
  17. package/lib/types/client/extractionHistory.d.ts +43 -0
  18. package/lib/types/client/index.d.ts +32 -14
  19. package/lib/types/client/listingFilter.d.ts +58 -0
  20. package/lib/types/client/locales.d.ts +123 -0
  21. package/lib/types/client/openInSidebar.d.ts +2 -2
  22. package/lib/types/client/progressRules.d.ts +198 -17
  23. package/lib/types/client/sanitizeExplorerTabs.d.ts +20 -0
  24. package/lib/types/client/settingsGate.d.ts +65 -0
  25. package/lib/types/client/uploadTransport.d.ts +65 -0
  26. package/lib/types/client/useTreeSort.d.ts +72 -0
  27. package/lib/types/client/workflows/WorkflowPlaza.d.ts +146 -0
  28. package/lib/types/client/workflows/cron.d.ts +125 -0
  29. package/lib/types/client/workflows/dedupe.d.ts +70 -0
  30. package/lib/types/client/workflows/deps.d.ts +101 -0
  31. package/lib/types/client/workflows/modelChoice.d.ts +106 -0
  32. package/lib/types/client/workflows/published.d.ts +43 -0
  33. package/lib/types/client/workflows/registry.d.ts +98 -0
  34. package/lib/types/client/workflows/subscribe.d.ts +179 -0
  35. package/lib/types/embeddings.d.ts +62 -0
  36. package/lib/types/externalChange.d.ts +25 -0
  37. package/lib/types/extract.d.ts +32 -0
  38. package/lib/types/extractionQueue.d.ts +23 -2
  39. package/lib/types/ftsIndex.d.ts +497 -0
  40. package/lib/types/index.d.ts +266 -8
  41. package/lib/types/initialize.d.ts +105 -0
  42. package/lib/types/knowledgeTools.d.ts +239 -0
  43. package/lib/types/localStoragePath.d.ts +6 -0
  44. package/lib/types/localStorageSettings.d.ts +33 -0
  45. package/lib/types/managementTools.d.ts +184 -0
  46. package/lib/types/outlineGuard.d.ts +119 -0
  47. package/lib/types/outlineText.d.ts +134 -0
  48. package/lib/types/protocol.d.ts +34 -0
  49. package/lib/types/scopeAliases.d.ts +20 -0
  50. package/lib/types/vectorIndex.d.ts +113 -0
  51. package/lib/types/views.d.ts +33 -1
  52. package/lib/types/workflowPublish.d.ts +114 -0
  53. package/package.json +7 -7
  54. package/skills/kb-summarize/SKILL.md +158 -0
  55. package/skills/kb-summarize/i18n/zh.json +10 -0
  56. package/skills/kb-vectorize/SKILL.md +57 -0
  57. package//344/270/207/347/233/270AI/344/275/277/347/224/250/346/225/231/347/250/213.html +294 -0
  58. package/lib/types/client/KnowledgeProgressPanel.d.ts +0 -53
@@ -0,0 +1,134 @@
1
+ /**
2
+ * Deterministic document outline extraction for the knowledge-base index.
3
+ *
4
+ * The outline is navigation, never evidence. `summary-v1` copied the first sentence of each
5
+ * chapter, which made the INDEX.md read like a pile of raw paragraphs. `summary-v2` still
6
+ * uses no language model: it ranks whole source sentences by legal cues (obligation, ratio,
7
+ * amount, deadline, article opener), keeps 2–4 of them per chapter, and composes the
8
+ * document summary from those chapter summaries instead of from the first paragraph.
9
+ *
10
+ * Two readability-only normalizations are applied: docx/PDF extraction spaces inside a
11
+ * Chinese word are removed (`二分 之一` → `二分之一`), and the canonical `“以上”包括本数`
12
+ * wording is compacted to `“以上含本数”`. Every number, subject and exception still comes
13
+ * from a source sentence; key facts remain verbatim apart from the article-label prefix.
14
+ *
15
+ * `structure-v3` already keeps headings as hard chunk boundaries. This module reconstructs
16
+ * the heading tree from the leading heading lines of each chunk and turns the chunks under a
17
+ * node into an extractive summary plus the numeric/exception sentences (`key_facts`) an
18
+ * operator looks for first.
19
+ *
20
+ * @module @sparkelf/dsh-knowledge-base/outlineText
21
+ */
22
+ /** Version of the extraction rules; bump when the summary shape changes. */
23
+ export declare const SUMMARY_VERSION = "summary-v2";
24
+ /** How many summary sections a document outline keeps in its table of contents. */
25
+ export declare const OUTLINE_MAX_SECTIONS = 500;
26
+ /** One indexed chunk, already ordered by its zero-based ordinal. */
27
+ export interface OutlineChunk {
28
+ id: number;
29
+ /** Stable citation key when the index has one. */
30
+ chunkKey?: string;
31
+ ordinal: number;
32
+ /** First line of the chunk, as stored by the indexer. */
33
+ heading?: string;
34
+ content: string;
35
+ }
36
+ /** One verbatim sentence that carries a threshold, ratio, body or exception. */
37
+ export interface OutlineKeyFact {
38
+ /** Article heading or nearest heading label; never generated prose. */
39
+ fact: string;
40
+ /** The source sentence, verbatim (bounded). */
41
+ value: string;
42
+ chunkId: number;
43
+ }
44
+ /** One heading node and the chunks below it. */
45
+ export interface OutlineSection {
46
+ /** Document-scoped stable id (`s<docId>-<n>`). */
47
+ sectionId: string;
48
+ /** Full path: `第一章 总则 > 第一条 ...`. */
49
+ headingPath: string;
50
+ /** This node's own heading text. */
51
+ title: string;
52
+ /** 1-based depth; 1 is a chapter/top-level heading. */
53
+ level: number;
54
+ /** Extractive summary; 80–200 characters for a chapter when the source allows it. */
55
+ summary: string;
56
+ keyFacts: OutlineKeyFact[];
57
+ /** Chunks whose own heading is this node. */
58
+ chunkIds: number[];
59
+ /** Every chunk under this node, including descendants. */
60
+ sourceChunkIds: number[];
61
+ parentId?: string;
62
+ }
63
+ /** One table-of-contents row. `sections` carries the full heading path and summaries. */
64
+ export interface OutlineTocEntry {
65
+ sectionId: string;
66
+ title: string;
67
+ level: number;
68
+ /** Chunks whose own heading is this node. */
69
+ chunkIds: number[];
70
+ }
71
+ /** Everything one document outline produces. */
72
+ export interface BuiltOutline {
73
+ /** `#` title when the text has one, otherwise the filename. */
74
+ documentTitle: string;
75
+ /** Document-level summary, 200–300 characters when the source allows it. */
76
+ summary: string;
77
+ /** Chunks whose sentences were used by the document summary. */
78
+ sourceChunkIds: number[];
79
+ toc: OutlineTocEntry[];
80
+ sections: OutlineSection[];
81
+ }
82
+ /** Input for {@link buildDocumentOutline}. */
83
+ export interface BuildOutlineInput {
84
+ docId: number;
85
+ /** Filename (or stored title), used when the text has no `#` title. */
86
+ docTitle: string;
87
+ /** Original source path, shown in INDEX.md. */
88
+ sourcePath: string;
89
+ chunks: readonly OutlineChunk[];
90
+ }
91
+ interface HeadingLine {
92
+ title: string;
93
+ /** Heading depth before tree clamping. */
94
+ rawLevel: number;
95
+ kind: 'markdown' | 'chapter' | 'section' | 'article' | 'chinese';
96
+ }
97
+ interface Sentence {
98
+ text: string;
99
+ chunkId: number;
100
+ ordinal: number;
101
+ position: number;
102
+ /** Article label inherited across continuation chunks (`第六条` followed by a body-only chunk). */
103
+ article?: string;
104
+ }
105
+ /** Classify one trimmed line as a heading, or return undefined. */
106
+ export declare function headingLineOf(line: string): HeadingLine | undefined;
107
+ /** Collapse Markdown/table syntax into plain prose, keeping numbers and punctuation. */
108
+ export declare function plainOutlineText(value: string): string;
109
+ /** Split one chunk into non-heading, non-rule sentences. */
110
+ export declare function sentencesOfChunk(chunk: OutlineChunk): Sentence[];
111
+ /**
112
+ * Build one document's extractive outline.
113
+ *
114
+ * Every sentence comes from a chunk; the only generated text is structural framing
115
+ * ("共 N 章", "章节包括") and the legal-phrase compaction documented above. No number,
116
+ * responsible body or exception is invented.
117
+ */
118
+ export declare function buildDocumentOutline(input: BuildOutlineInput): BuiltOutline;
119
+ /** Input for {@link renderOutlineMarkdown}. */
120
+ export interface RenderOutlineInput {
121
+ docId: number;
122
+ docTitle: string;
123
+ sourcePath: string;
124
+ summaryVersion: string;
125
+ /** How the summary was produced; omitted for legacy callers means `extractive`. */
126
+ summaryKind?: 'none' | 'extractive' | 'llm';
127
+ summary: string;
128
+ summarySourceChunkIds: readonly number[];
129
+ toc: readonly OutlineTocEntry[];
130
+ sections: readonly OutlineSection[];
131
+ }
132
+ /** Render the human/agent-readable INDEX.md for one document. */
133
+ export declare function renderOutlineMarkdown(input: RenderOutlineInput): string;
134
+ export {};
@@ -44,6 +44,8 @@ export interface KnowledgeConfig {
44
44
  * This is the directory a container mounts.
45
45
  */
46
46
  viewRoot: string;
47
+ /** Local deployments: configured storage base (default `~/kb`). */
48
+ storageRoot?: string;
47
49
  /** Absolute path where the view tree is mounted inside the container. */
48
50
  mountPoint: string;
49
51
  /** NFS export host, when the deployment uses the NFS transport. */
@@ -114,6 +116,26 @@ export interface KnowledgeStatus {
114
116
  jobId?: string;
115
117
  progress?: number;
116
118
  };
119
+ /** Optional vector index coverage; reported only by hosts that have this feature. */
120
+ vector?: {
121
+ enabled: boolean;
122
+ provider?: string;
123
+ model?: string;
124
+ embeddedChunks: number;
125
+ totalChunks: number;
126
+ embeddedDocs: number;
127
+ totalDocs: number;
128
+ failed: number;
129
+ canManageVector?: boolean;
130
+ indexing: {
131
+ running: boolean;
132
+ total?: number;
133
+ done?: number;
134
+ embedded?: number;
135
+ failed?: number;
136
+ error?: string;
137
+ };
138
+ };
117
139
  }
118
140
  /**
119
141
  * One grant to create.
@@ -207,6 +229,18 @@ export declare const ENDPOINTS: {
207
229
  * category yet.
208
230
  */
209
231
  readonly templates: "/api/resources/wiki/pages/templates";
232
+ /**
233
+ * The MinerU address the 「文档识别」 plugin's administrator shares with the deployment.
234
+ *
235
+ * Read-only here. The knowledge base keeps its own per-caller address field, and when that
236
+ * is empty this shared value is what the parser is called with. It is never written back:
237
+ * a copy in this plugin's settings file would stop following the administrator's later
238
+ * change and become a second source of truth.
239
+ *
240
+ * `AuthGuard`-only on the backend, so any signed-in member may read it: the address is not
241
+ * a secret, and being allowed to USE it is not being allowed to CHANGE it (`canEdit`).
242
+ */
243
+ readonly ocrConfig: "/api/ocr/config";
210
244
  };
211
245
  /**
212
246
  * Resource type the knowledge base records its paths under.
@@ -0,0 +1,20 @@
1
+ /** Virtual view aliases for the three canonical knowledge scopes. */
2
+ export type ScopeLocale = 'zh' | 'en';
3
+ export declare const CANONICAL_SCOPES: readonly ["global", "department", "personal"];
4
+ export type CanonicalScope = typeof CANONICAL_SCOPES[number];
5
+ /** Display label for one canonical scope. */
6
+ export declare function scopeAliasFor(scope: CanonicalScope, locale?: ScopeLocale): string;
7
+ /** All accepted spellings of one canonical scope. */
8
+ export declare function scopeSpellings(scope: CanonicalScope): string[];
9
+ /**
10
+ * Map a view path whose first segment is a localized scope alias back to canonical.
11
+ *
12
+ * The NFS tree and the index stay `global/department/personal`; aliases are only a
13
+ * virtual view coordinate accepted at every entry. Unknown first segments are left
14
+ * untouched (legacy/top-level paths).
15
+ */
16
+ export declare function resolveScopeAlias(relPath: string): string;
17
+ /** Turn a canonical path into its localized view spelling for display. */
18
+ export declare function localizedScopeForPath(relPath: string, locale?: ScopeLocale): string;
19
+ /** Canonical scope from a path or alias, or undefined for a non-bucket path. */
20
+ export declare function scopeFromAlias(segment: string): CanonicalScope | undefined;
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Optional SQLite vector sidecar for hybrid retrieval.
3
+ *
4
+ * Vectors are stored as raw Float32 blobs in the same SQLite file as the FTS index.
5
+ * No sqlite-vec extension is required: candidate rows are read into the process and
6
+ * cosine similarity is computed here. The table is keyed by the current chunk id, so
7
+ * a re-chunk simply makes an old row unreachable until it is pruned.
8
+ *
9
+ * @module @sparkelf/dsh-knowledge-base/vectorIndex
10
+ */
11
+ import { DatabaseSync } from 'node:sqlite';
12
+ /** One stored embedding row. */
13
+ export interface VectorEmbeddingRow {
14
+ chunkId: number;
15
+ docId: number;
16
+ path: string;
17
+ model: string;
18
+ dim: number;
19
+ vector: Float32Array;
20
+ norm: number;
21
+ contentHash: string;
22
+ }
23
+ /** One chunk that needs an embedding. */
24
+ export interface VectorChunk {
25
+ id: number;
26
+ docId: number;
27
+ path: string;
28
+ content: string;
29
+ }
30
+ /** Counts for the settings page. */
31
+ export interface VectorIndexStats {
32
+ totalChunks: number;
33
+ embeddedChunks: number;
34
+ totalDocs: number;
35
+ embeddedDocs: number;
36
+ failed: number;
37
+ model: string;
38
+ }
39
+ /** Create the vector tables in an existing index database. */
40
+ export declare function ensureVectorSchema(db: DatabaseSync): void;
41
+ /** Stable content key used to decide whether an embedding is stale. */
42
+ export declare function embeddingContentHash(content: string): string;
43
+ /** L2 norm of a vector; zero vectors cannot be normalized and are never stored. */
44
+ export declare function vectorNorm(vector: ArrayLike<number>): number;
45
+ /** Serialize a vector as little-endian Float32 bytes. */
46
+ export declare function packVector(vector: ArrayLike<number>): Buffer;
47
+ /** Deserialize a Float32 blob without copying the bytes. */
48
+ export declare function unpackVector(blob: Uint8Array): Float32Array;
49
+ /** Cosine similarity; both norms are precomputed for stored rows. */
50
+ export declare function cosineSimilarity(left: ArrayLike<number>, right: ArrayLike<number>, leftNorm: number, rightNorm: number): number;
51
+ /** Upsert one embedding and clear its previous failure. */
52
+ export declare function putEmbedding(db: DatabaseSync, row: {
53
+ chunkId: number;
54
+ docId: number;
55
+ path: string;
56
+ model: string;
57
+ vector: readonly number[];
58
+ contentHash: string;
59
+ updatedAt: string;
60
+ }): void;
61
+ /** Record a per-chunk failure without pretending a vector exists. */
62
+ export declare function recordVectorFailure(db: DatabaseSync, row: {
63
+ chunkId: number;
64
+ docId: number;
65
+ path: string;
66
+ model: string;
67
+ error: string;
68
+ updatedAt: string;
69
+ }): void;
70
+ /** Read chunks for a set of documents. */
71
+ export declare function chunksForDocuments(db: DatabaseSync, docIds: readonly number[]): VectorChunk[];
72
+ /** Current embedding state for chunks, keyed by chunk id. */
73
+ export declare function embeddingStates(db: DatabaseSync, model: string, chunkIds: readonly number[]): Map<number, {
74
+ contentHash: string;
75
+ model: string;
76
+ }>;
77
+ /** Stats for the settings page, optionally for one model. */
78
+ export declare function vectorIndexStats(db: DatabaseSync, model: string): VectorIndexStats;
79
+ /** One vector candidate row before fuse. */
80
+ export interface VectorCandidate {
81
+ chunkId: number;
82
+ docId: number;
83
+ path: string;
84
+ score: number;
85
+ }
86
+ /**
87
+ * Read every current embedding for a model and rank it by cosine similarity.
88
+ *
89
+ * Scope filtering is applied in SQL before similarity ordering, exactly as the FTS
90
+ * side does. A caller-supplied `canRead` check still runs on the resulting paths.
91
+ */
92
+ export declare function vectorCandidates(db: DatabaseSync, options: {
93
+ model: string;
94
+ query: readonly number[];
95
+ clauses: readonly string[];
96
+ params: readonly (string | number)[];
97
+ scopeClause: string;
98
+ scopeParams: readonly (string | number)[];
99
+ candidateK: number;
100
+ }): VectorCandidate[];
101
+ /** One document target for an explicit vectorization run. */
102
+ export interface VectorDocument {
103
+ id: number;
104
+ path: string;
105
+ scope: string;
106
+ }
107
+ /** Resolve explicit targets by id or path prefix, optionally narrowed by scope. */
108
+ export declare function vectorDocuments(db: DatabaseSync, target: {
109
+ docId?: number;
110
+ path?: string;
111
+ scope?: string;
112
+ all?: boolean;
113
+ }): VectorDocument[];
@@ -17,6 +17,7 @@
17
17
  *
18
18
  * @module @sparkelf/dsh-knowledge-base/views
19
19
  */
20
+ import { type VectorRetrievalConfig } from './embeddings.ts';
20
21
  /** One path a user may read, as DataOps resolved it. */
21
22
  export interface ResolvedPath {
22
23
  /** Path relative to the authoritative root. */
@@ -488,6 +489,10 @@ export interface KnowledgeStorageSettings {
488
489
  sshMountOptions?: string;
489
490
  /** SSHFS: credential reference holding the private key -- a name, never the key. */
490
491
  sshKeyRef?: string;
492
+ /** Optional vector retrieval settings, stored deployment-wide. */
493
+ retrieval?: {
494
+ vector: VectorRetrievalConfig;
495
+ };
491
496
  }
492
497
  /** Whether a write must be reviewed before it counts as published. */
493
498
  export interface KnowledgeSettings extends KnowledgeStorageSettings {
@@ -540,6 +545,22 @@ export declare function storageSettingsOf(raw: Record<string, unknown>): Knowled
540
545
  * @returns The stored settings, or the defaults.
541
546
  */
542
547
  export declare function readSettings(viewDir: string): Promise<KnowledgeSettings>;
548
+ /**
549
+ * Whether this caller's settings file holds a MinerU address that was refused as invalid.
550
+ *
551
+ * {@link readSettings} normalises a hand-edited or foreign value down to `''`, which makes
552
+ * "never configured" and "configured with something unusable" indistinguishable. The
553
+ * settings page has to tell them apart: the second case must not leave the reader thinking
554
+ * their own address is in use when it was dropped and a fallback answered instead.
555
+ *
556
+ * Read separately rather than threaded through {@link readSettings} because only the page
557
+ * needs it -- the extractor either has a usable address or it does not, and the reason it
558
+ * does not is a message for a human.
559
+ *
560
+ * @param viewDir - the user's view directory.
561
+ * @returns true when the file holds a non-empty value that the normaliser rejected.
562
+ */
563
+ export declare function storedMineruInvalid(viewDir: string): Promise<boolean>;
543
564
  /**
544
565
  * Replace this knowledge base's settings.
545
566
  *
@@ -807,12 +828,23 @@ export interface KnowledgeAuditEntry {
807
828
  * here" and "who changed it last". A save through the host's own file editor
808
829
  * reports here through a side channel (see the `audit.appended` route), which is
809
830
  * what keeps the host's write path untouched.
831
+ *
832
+ * `delete` is a caller-scoped tombstone (the bytes stay on disk); `external-change`
833
+ * is written by the filesystem watcher when a process outside these tools (usually
834
+ * a shell command) modifies the authoritative tree.
810
835
  */
811
- action: 'create' | 'upload' | 'move' | 'approve' | 'reject' | 'edit';
836
+ action: 'create' | 'upload' | 'move' | 'approve' | 'reject' | 'edit' | 'delete' | 'external-change';
812
837
  /** The path the action concerned, relative to the knowledge root. */
813
838
  relPath: string;
814
839
  /** For a move, the destination path. */
815
840
  toRelPath?: string;
841
+ /**
842
+ * Extra detail for actions that have more than one flavour.
843
+ *
844
+ * Only `external-change` currently uses it (`updated` / `renamed` / `deleted`).
845
+ * Optional so older lines remain readable.
846
+ */
847
+ detail?: 'updated' | 'renamed' | 'deleted';
816
848
  /**
817
849
  * What became of it.
818
850
  *
@@ -0,0 +1,114 @@
1
+ /**
2
+ * The workflow-plaza publish store.
3
+ *
4
+ * A workflow authored in a conversation is not public when it is written: the record
5
+ * lands as `pending`, an administrator reviews the actual prompt, and only `approved`
6
+ * records enter the plaza. The store lives beside the DSH profile rather than inside the
7
+ * knowledge tree because it is product metadata, not a document: it has no per-user view,
8
+ * no trash, and no DataOps grant semantics.
9
+ *
10
+ * Writes are read-modify-write over one JSON file, serialized per path and committed by
11
+ * atomic rename, so two model calls cannot overwrite each other and a restart never sees
12
+ * a half-written store.
13
+ *
14
+ * @module @sparkelf/dsh-knowledge-base/workflowPublish
15
+ */
16
+ /** Where a published workflow currently is. */
17
+ export type PublishedWorkflowVisibility = 'global' | 'department' | 'private';
18
+ export type PublishedWorkflowStatus = 'pending' | 'approved' | 'rejected' | 'unpublished';
19
+ /** What the model may publish. */
20
+ export interface WorkflowPublishInput {
21
+ readonly title: string;
22
+ readonly description: string;
23
+ readonly instruction: string;
24
+ readonly cronHint?: string;
25
+ readonly category?: string;
26
+ readonly visibility?: PublishedWorkflowVisibility;
27
+ readonly departmentCode?: string;
28
+ }
29
+ /** One authored workflow as stored. */
30
+ export interface PublishedWorkflow {
31
+ readonly id: string;
32
+ readonly title: string;
33
+ readonly description: string;
34
+ readonly instruction: string;
35
+ readonly cronHint: string;
36
+ readonly category: string;
37
+ readonly visibility: PublishedWorkflowVisibility;
38
+ readonly departmentCode?: string;
39
+ readonly authorId: string;
40
+ readonly authorName: string;
41
+ readonly createdAt: string;
42
+ readonly updatedAt: string;
43
+ readonly status: PublishedWorkflowStatus;
44
+ readonly unpublishedAt?: string;
45
+ readonly sourceSessionId?: string;
46
+ readonly reviewedAt?: string;
47
+ readonly reviewedById?: string;
48
+ readonly reviewedByName?: string;
49
+ readonly reviewNote?: string;
50
+ readonly audit: readonly WorkflowAuditEntry[];
51
+ }
52
+ /** One durable review/publish event. */
53
+ export interface WorkflowAuditEntry {
54
+ readonly at: string;
55
+ readonly actorId: string;
56
+ readonly actorName: string;
57
+ readonly action: 'published' | 'approved' | 'rejected';
58
+ readonly note?: string;
59
+ }
60
+ /** The whole file. */
61
+ export interface WorkflowPublishStore {
62
+ readonly version: 1;
63
+ readonly workflows: readonly PublishedWorkflow[];
64
+ }
65
+ /** Structured store failure; the HTTP route and the tool both map these. */
66
+ export declare class WorkflowPublishError extends Error {
67
+ readonly code: 'invalid' | 'not-found' | 'already-reviewed' | 'forbidden' | 'io';
68
+ readonly name = "WorkflowPublishError";
69
+ constructor(code: 'invalid' | 'not-found' | 'already-reviewed' | 'forbidden' | 'io', message: string);
70
+ }
71
+ /** The profile-local directory the store lives in. */
72
+ export declare function defaultPublishDir(env?: NodeJS.ProcessEnv): string;
73
+ /** Resolve the configured directory, falling back to the profile-local default. */
74
+ export declare function publishDirOf(configured: string | undefined): string;
75
+ /** The one file in that directory. */
76
+ export declare function publishStorePath(directory: string): string;
77
+ /** Validate and normalize one publish request. */
78
+ export declare function normalizePublishInput(input: WorkflowPublishInput): Required<WorkflowPublishInput>;
79
+ /** Parse a store file, treating absence as empty and quarantining corrupt JSON. */
80
+ export declare function readWorkflowStore(path: string): Promise<WorkflowPublishStore>;
81
+ /** Commit the store atomically (write beside it, then rename). */
82
+ export declare function writeWorkflowStore(path: string, store: WorkflowPublishStore): Promise<void>;
83
+ /** The caller who authors/reviews a record. */
84
+ export interface WorkflowActor {
85
+ readonly id: string;
86
+ readonly name: string;
87
+ }
88
+ /** Result of a publish attempt; `duplicate` means the pending record already existed. */
89
+ export interface PublishResult {
90
+ readonly record: PublishedWorkflow;
91
+ readonly duplicate: boolean;
92
+ }
93
+ /**
94
+ * Publish one workflow as pending.
95
+ *
96
+ * Deduplication is deliberately scoped to `(normalized title, author, pending)`: a
97
+ * second model call in the same conversation must not create a second review card, while
98
+ * a rejected workflow may be resubmitted after edits.
99
+ */
100
+ export declare function publishWorkflow(path: string, input: WorkflowPublishInput, actor: WorkflowActor, sourceSessionId?: string, now?: () => Date): Promise<PublishResult>;
101
+ /** Update one local record's mutable copy, stamping updatedAt and an audit entry. */
102
+ export declare function updatePublishedWorkflow(path: string, id: string, patch: Partial<Pick<PublishedWorkflow, 'title' | 'description' | 'instruction' | 'cronHint' | 'category' | 'visibility' | 'departmentCode'>>, actor: WorkflowActor, now?: () => Date): Promise<PublishedWorkflow>;
103
+ /** Mark one local workflow unpublished (retained for the owner's history). */
104
+ export declare function unpublishPublishedWorkflow(path: string, id: string, actor: WorkflowActor, now?: () => Date): Promise<PublishedWorkflow>;
105
+ /** Every record authored by one person, newest update first (the mine tab source). */
106
+ export declare function listWorkflowsForAuthor(path: string, authorId: string): Promise<readonly PublishedWorkflow[]>;
107
+ /** Put one rejected/unpublished workflow back into the pending review queue. */
108
+ export declare function resubmitPublishedWorkflow(path: string, id: string, actor: WorkflowActor, now?: () => Date): Promise<PublishedWorkflow>;
109
+ /** Approved workflows, newest first. */
110
+ export declare function listApprovedWorkflows(path: string): Promise<readonly PublishedWorkflow[]>;
111
+ /** Pending workflows for the review tab, oldest first so the queue reads in arrival order. */
112
+ export declare function listPendingWorkflows(path: string): Promise<readonly PublishedWorkflow[]>;
113
+ /** Approve or reject one pending workflow. Rejected records stay in the store. */
114
+ export declare function reviewWorkflow(path: string, id: string, decision: 'approve' | 'reject', actor: WorkflowActor, note?: string, now?: () => Date): Promise<PublishedWorkflow>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sparkelf/dsh-knowledge-base",
3
- "version": "0.1.5",
3
+ "version": "0.1.20",
4
4
  "description": "DataOps-backed knowledge base for DeepSeek Harness: a left-sidebar destination, Settings configuration, and index tooling over a mounted NAS view.",
5
5
  "type": "module",
6
6
  "main": "./lib/index.js",
@@ -43,15 +43,11 @@
43
43
  "README.md",
44
44
  "LICENSE",
45
45
  "SKILL.md",
46
+ "万相AI使用教程.html",
46
47
  "i18n/*.json",
47
48
  "skills/**/SKILL.md",
48
49
  "skills/**/i18n/*.json"
49
50
  ],
50
- "scripts": {
51
- "build": "rm -rf lib && tsc -p tsconfig.build.json && tsdown",
52
- "bundle": "tsdown",
53
- "prepack": "pnpm run build"
54
- },
55
51
  "engines": {
56
52
  "node": "^22.19.0 || >=24.0.0"
57
53
  },
@@ -107,5 +103,9 @@
107
103
  "dsh-better-sidebar": {
108
104
  "optional": true
109
105
  }
106
+ },
107
+ "scripts": {
108
+ "build": "rm -rf lib && tsc -p tsconfig.build.json && tsdown",
109
+ "bundle": "tsdown"
110
110
  }
111
- }
111
+ }