@objectstack/knowledge-ragflow 17.1.0 → 17.3.0

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/CHANGELOG.md CHANGED
@@ -1,5 +1,400 @@
1
1
  # @objectstack/knowledge-ragflow
2
2
 
3
+ ## 17.3.0
4
+
5
+ ### Patch Changes
6
+
7
+ - ad54eb3: feat(tooling): onboard all 14 `packages/plugins/**` packages into `check:test-typecheck` (#14062)
8
+
9
+ Every plugin package now has a `tsconfig.test.json` compiled by the shared
10
+ `check:test-typecheck` gate, and its `typecheck` script names it. Before this,
11
+ the shrink-only `test-typecheck-debt.json` ratchet said **nothing** about a
12
+ third of the repo's runtime surface: 14 packages, 1 `tsconfig.test.json`
13
+ (`plugin-security`, wired directly to `tsc` rather than to the instrument), and
14
+ 0 `check:test-typecheck` scripts.
15
+
16
+ Onboarded as a family by the director ruling of 2026-09-01 on #14062
17
+ (maintainer verbatim: 「同意」), which also carries the #5286 maintainer
18
+ authority the starting ledgers need. The smaller branch triage recommended —
19
+ declare the instrument's scope and re-site the two compile-time pins — was
20
+ recorded as considered and not taken: an instrument silent over a third of the
21
+ runtime surface is a hole readers generalise across, and that costs more than
22
+ fourteen tsconfigs.
23
+
24
+ **Measured, not assumed** (at `e80889095`, workspace closure built first). Four
25
+ packages carry residue and therefore a starting ledger — plugin-approvals 324
26
+ over 8 files, plugin-auth 94 over 10, plugin-sharing 3 over 2,
27
+ knowledge-ragflow 3 over 1. The other ten measure **zero** and deliberately get
28
+ no ledger file at all: the gate reads a missing ledger as `{ entries: {} }`, so
29
+ any error there is red immediately with no entry to be added to — strictly
30
+ stronger than a ledger holding nothing, and the call `plugin-security` had
31
+ already recorded for itself.
32
+
33
+ ⛔ **This does not repair 345 type errors.** Per ruling item 3 it makes the
34
+ ratchet able to *see* them; paydown follows the ratchet's own shrink-only
35
+ discipline on its own cards. No test file is edited here.
36
+
37
+ Two corrections to the finding's own prose, both measured: the exclusion is
38
+ narrower than "no plugin package compiles its tests" — 9 of the 14 already
39
+ compiled their tests inside the `typecheck`-invoked build config, at zero
40
+ errors — and `exec-context-annotation.pin.ts` is a `.pin.ts`, which
41
+ `**/*.test.ts` never excluded, so its directives were already live. The pin
42
+ this change genuinely makes real is
43
+ `plugin-approvals/src/manager-org-screen-parity.contract.test.ts`, which no tsc
44
+ program had ever read.
45
+ - Updated dependencies [809d417]
46
+ - Updated dependencies [387e231]
47
+ - Updated dependencies [f794e4e]
48
+ - Updated dependencies [cae2169]
49
+ - Updated dependencies [b812a54]
50
+ - Updated dependencies [2d4fa75]
51
+ - Updated dependencies [0e4e51b]
52
+ - Updated dependencies [e84bbf6]
53
+ - Updated dependencies [effae80]
54
+ - Updated dependencies [efb3513]
55
+ - Updated dependencies [d62f990]
56
+ - Updated dependencies [c45d8e6]
57
+ - Updated dependencies [2e3e8c7]
58
+ - Updated dependencies [e621291]
59
+ - Updated dependencies [655b106]
60
+ - Updated dependencies [40a93b5]
61
+ - Updated dependencies [d5b330d]
62
+ - Updated dependencies [dda969c]
63
+ - Updated dependencies [1f45690]
64
+ - Updated dependencies [277948f]
65
+ - Updated dependencies [8bdd955]
66
+ - Updated dependencies [f3bbbef]
67
+ - Updated dependencies [4f24e9d]
68
+ - Updated dependencies [e27583e]
69
+ - Updated dependencies [4bd6faa]
70
+ - Updated dependencies [86cbe37]
71
+ - Updated dependencies [6a180e4]
72
+ - Updated dependencies [474242f]
73
+ - Updated dependencies [63cd487]
74
+ - Updated dependencies [bd4aa4e]
75
+ - Updated dependencies [803eaab]
76
+ - Updated dependencies [f8e8f03]
77
+ - Updated dependencies [983edf1]
78
+ - Updated dependencies [eae824e]
79
+ - Updated dependencies [f6fa22c]
80
+ - Updated dependencies [8a483b3]
81
+ - Updated dependencies [97bcd99]
82
+ - Updated dependencies [df59de0]
83
+ - Updated dependencies [96e25a8]
84
+ - Updated dependencies [f75a38a]
85
+ - Updated dependencies [7a25e7d]
86
+ - Updated dependencies [1fa05a6]
87
+ - Updated dependencies [c85a265]
88
+ - Updated dependencies [dcb10a5]
89
+ - Updated dependencies [773a999]
90
+ - Updated dependencies [35dffea]
91
+ - Updated dependencies [d8024f0]
92
+ - Updated dependencies [8120808]
93
+ - Updated dependencies [776a098]
94
+ - Updated dependencies [5060877]
95
+ - Updated dependencies [4f6325d]
96
+ - Updated dependencies [52954c0]
97
+ - Updated dependencies [2aa8456]
98
+ - Updated dependencies [93809a3]
99
+ - Updated dependencies [7c0d0c3]
100
+ - Updated dependencies [daae7aa]
101
+ - Updated dependencies [8dc22d6]
102
+ - Updated dependencies [279431e]
103
+ - Updated dependencies [948dd6b]
104
+ - Updated dependencies [3b4c56c]
105
+ - Updated dependencies [ae8edd2]
106
+ - Updated dependencies [e25403c]
107
+ - Updated dependencies [64baa68]
108
+ - Updated dependencies [9fa70d7]
109
+ - Updated dependencies [09db64a]
110
+ - Updated dependencies [92916e7]
111
+ - Updated dependencies [a84f3ea]
112
+ - Updated dependencies [f2eaae8]
113
+ - Updated dependencies [c09451b]
114
+ - Updated dependencies [ba64877]
115
+ - Updated dependencies [e7191ce]
116
+ - Updated dependencies [7345308]
117
+ - Updated dependencies [79b6a22]
118
+ - Updated dependencies [30d96ab]
119
+ - Updated dependencies [f658793]
120
+ - Updated dependencies [c95ad19]
121
+ - Updated dependencies [e58ea8b]
122
+ - Updated dependencies [4a17645]
123
+ - Updated dependencies [3795c5f]
124
+ - Updated dependencies [8ab926b]
125
+ - Updated dependencies [7317cf2]
126
+ - Updated dependencies [e25e839]
127
+ - Updated dependencies [5997207]
128
+ - Updated dependencies [8b13cc8]
129
+ - Updated dependencies [4a4a35d]
130
+ - Updated dependencies [86e765a]
131
+ - Updated dependencies [1d7e76a]
132
+ - Updated dependencies [53dc739]
133
+ - Updated dependencies [fd289be]
134
+ - Updated dependencies [03bf7b1]
135
+ - Updated dependencies [f90e820]
136
+ - Updated dependencies [18d816a]
137
+ - Updated dependencies [e8bd715]
138
+ - Updated dependencies [b91c351]
139
+ - Updated dependencies [a28a3c0]
140
+ - Updated dependencies [daeaaf9]
141
+ - Updated dependencies [c459da6]
142
+ - Updated dependencies [e914733]
143
+ - Updated dependencies [f887e52]
144
+ - Updated dependencies [881f8d8]
145
+ - Updated dependencies [3bfa1e6]
146
+ - Updated dependencies [0a8ebf3]
147
+ - Updated dependencies [901355c]
148
+ - Updated dependencies [34ce8e7]
149
+ - Updated dependencies [33681ea]
150
+ - Updated dependencies [4635f3e]
151
+ - Updated dependencies [fd289be]
152
+ - Updated dependencies [ee3595c]
153
+ - Updated dependencies [b2eab95]
154
+ - Updated dependencies [93940d4]
155
+ - Updated dependencies [3a04b01]
156
+ - Updated dependencies [45b9051]
157
+ - Updated dependencies [b9e9227]
158
+ - Updated dependencies [d395692]
159
+ - Updated dependencies [5894d30]
160
+ - Updated dependencies [a3765f6]
161
+ - Updated dependencies [2d5cee3]
162
+ - Updated dependencies [e22158f]
163
+ - Updated dependencies [7404925]
164
+ - Updated dependencies [0c2334f]
165
+ - Updated dependencies [778c59f]
166
+ - Updated dependencies [d2619fd]
167
+ - Updated dependencies [af56546]
168
+ - Updated dependencies [6acb11a]
169
+ - Updated dependencies [33c5fd3]
170
+ - Updated dependencies [20b0fdb]
171
+ - Updated dependencies [905019b]
172
+ - Updated dependencies [a286411]
173
+ - Updated dependencies [98c0d33]
174
+ - Updated dependencies [368a82e]
175
+ - Updated dependencies [a3d5724]
176
+ - Updated dependencies [93ea19b]
177
+ - Updated dependencies [9ee2dcf]
178
+ - Updated dependencies [8cb96ec]
179
+ - Updated dependencies [8f10a79]
180
+ - Updated dependencies [6269a55]
181
+ - Updated dependencies [a17da05]
182
+ - Updated dependencies [a8c00e2]
183
+ - Updated dependencies [0fb8760]
184
+ - Updated dependencies [e5ce2ed]
185
+ - Updated dependencies [be21955]
186
+ - Updated dependencies [bc56e18]
187
+ - Updated dependencies [be21955]
188
+ - Updated dependencies [a9ee989]
189
+ - Updated dependencies [4d0d944]
190
+ - Updated dependencies [15d58db]
191
+ - Updated dependencies [d63b014]
192
+ - Updated dependencies [9abe4e4]
193
+ - Updated dependencies [2cc7122]
194
+ - Updated dependencies [50d6c92]
195
+ - Updated dependencies [9e0ba21]
196
+ - Updated dependencies [311433f]
197
+ - Updated dependencies [3e5ad08]
198
+ - Updated dependencies [9abe4e4]
199
+ - Updated dependencies [b7131f3]
200
+ - Updated dependencies [e5812fa]
201
+ - Updated dependencies [7085f90]
202
+ - Updated dependencies [dee4dd4]
203
+ - Updated dependencies [ce7e497]
204
+ - Updated dependencies [51ecb2f]
205
+ - Updated dependencies [9086761]
206
+ - Updated dependencies [42a117b]
207
+ - Updated dependencies [1401ae7]
208
+ - Updated dependencies [4297fe7]
209
+ - Updated dependencies [e398863]
210
+ - Updated dependencies [d16df74]
211
+ - Updated dependencies [f11fc61]
212
+ - Updated dependencies [e808890]
213
+ - Updated dependencies [8f79379]
214
+ - Updated dependencies [e6ca40e]
215
+ - Updated dependencies [0c77ea4]
216
+ - Updated dependencies [52954c0]
217
+ - Updated dependencies [89eb997]
218
+ - Updated dependencies [7131f12]
219
+ - Updated dependencies [aa5994e]
220
+ - Updated dependencies [be93457]
221
+ - Updated dependencies [a65db76]
222
+ - Updated dependencies [15eb2c9]
223
+ - Updated dependencies [5691b07]
224
+ - Updated dependencies [2a6122b]
225
+ - Updated dependencies [225e769]
226
+ - Updated dependencies [8af88dd]
227
+ - Updated dependencies [fb5fbb8]
228
+ - Updated dependencies [d7b3963]
229
+ - Updated dependencies [33184fd]
230
+ - Updated dependencies [7c41693]
231
+ - Updated dependencies [b72db01]
232
+ - Updated dependencies [dce5cd4]
233
+ - Updated dependencies [9688f58]
234
+ - Updated dependencies [556ebc1]
235
+ - Updated dependencies [177ebdc]
236
+ - Updated dependencies [8d237b4]
237
+ - Updated dependencies [2d2e6f0]
238
+ - Updated dependencies [2d8dd8d]
239
+ - Updated dependencies [22d573e]
240
+ - Updated dependencies [b5a2398]
241
+ - Updated dependencies [348860c]
242
+ - Updated dependencies [5383fa6]
243
+ - Updated dependencies [5b3ff63]
244
+ - Updated dependencies [1a6a19c]
245
+ - Updated dependencies [527e050]
246
+ - Updated dependencies [dd33bf9]
247
+ - Updated dependencies [4cb2a90]
248
+ - Updated dependencies [74a7804]
249
+ - Updated dependencies [53d3689]
250
+ - Updated dependencies [b3a63d3]
251
+ - Updated dependencies [49f0dcf]
252
+ - Updated dependencies [033a34c]
253
+ - Updated dependencies [4d25d22]
254
+ - Updated dependencies [1ffee51]
255
+ - Updated dependencies [5ae4303]
256
+ - Updated dependencies [ece4dad]
257
+ - Updated dependencies [e9b377e]
258
+ - Updated dependencies [146f448]
259
+ - Updated dependencies [735f5c7]
260
+ - Updated dependencies [a7e18de]
261
+ - Updated dependencies [366f895]
262
+ - Updated dependencies [dc75ba8]
263
+ - Updated dependencies [cce0aa9]
264
+ - Updated dependencies [e764507]
265
+ - Updated dependencies [cff17af]
266
+ - Updated dependencies [39404f3]
267
+ - Updated dependencies [ca1965f]
268
+ - Updated dependencies [8619f95]
269
+ - Updated dependencies [b706af9]
270
+ - Updated dependencies [8422acd]
271
+ - Updated dependencies [add4360]
272
+ - Updated dependencies [fc9ba76]
273
+ - Updated dependencies [0f94cc7]
274
+ - Updated dependencies [a11c1a5]
275
+ - Updated dependencies [71f9cd1]
276
+ - Updated dependencies [ee17d86]
277
+ - Updated dependencies [cdbd920]
278
+ - Updated dependencies [18c432e]
279
+ - Updated dependencies [3c418c4]
280
+ - Updated dependencies [fa8715a]
281
+ - Updated dependencies [a933ed7]
282
+ - Updated dependencies [b3ca463]
283
+ - Updated dependencies [a933ed7]
284
+ - Updated dependencies [0d4a6a8]
285
+ - Updated dependencies [518d5e5]
286
+ - Updated dependencies [6643ba1]
287
+ - Updated dependencies [eeba2ef]
288
+ - Updated dependencies [ec4c4d2]
289
+ - Updated dependencies [424f73c]
290
+ - Updated dependencies [cccbe51]
291
+ - Updated dependencies [a8d6b1d]
292
+ - Updated dependencies [e4a7695]
293
+ - Updated dependencies [87075b1]
294
+ - Updated dependencies [fc58a99]
295
+ - Updated dependencies [14cfc00]
296
+ - Updated dependencies [1c6f7b4]
297
+ - Updated dependencies [e854a53]
298
+ - Updated dependencies [dfebfc8]
299
+ - Updated dependencies [d028b37]
300
+ - Updated dependencies [f7b25c5]
301
+ - Updated dependencies [122ef38]
302
+ - Updated dependencies [4a37870]
303
+ - Updated dependencies [428f9b2]
304
+ - Updated dependencies [aa7ff56]
305
+ - Updated dependencies [c41b42e]
306
+ - Updated dependencies [c4db311]
307
+ - Updated dependencies [750fff5]
308
+ - Updated dependencies [c19035e]
309
+ - Updated dependencies [ececf7a]
310
+ - Updated dependencies [d173125]
311
+ - Updated dependencies [8eeca27]
312
+ - Updated dependencies [8425c17]
313
+ - Updated dependencies [a5ef1d8]
314
+ - Updated dependencies [772d5de]
315
+ - Updated dependencies [ce80ec2]
316
+ - Updated dependencies [b372318]
317
+ - Updated dependencies [97a2263]
318
+ - Updated dependencies [29d0676]
319
+ - Updated dependencies [0169d49]
320
+ - Updated dependencies [6bd3231]
321
+ - Updated dependencies [d2b5ba8]
322
+ - Updated dependencies [b799ac5]
323
+ - Updated dependencies [8f74307]
324
+ - Updated dependencies [d23dc08]
325
+ - Updated dependencies [644ad50]
326
+ - Updated dependencies [0da7cd2]
327
+ - Updated dependencies [28a5c3e]
328
+ - Updated dependencies [4bc18e5]
329
+ - @objectstack/spec@17.3.0
330
+ - @objectstack/core@17.3.0
331
+ - @objectstack/service-knowledge@17.3.0
332
+
333
+ ## 17.2.0
334
+
335
+ ### Patch Changes
336
+
337
+ - 7bf3fb7: Point every documentation link in these packages' published READMEs — and in
338
+ the project `create-objectstack` scaffolds — at the canonical docs origin
339
+ `https://objectstack.ai`, replacing the `docs.objectstack.ai` spelling.
340
+
341
+ Both spellings reach the same pages (the alias redirects to the apex,
342
+ path-preserving), so no link was broken. The reason it needs a release rather
343
+ than an in-repo fix alone: a README ships inside the npm tarball, so the
344
+ version already on npm keeps showing the old host to every reader of the
345
+ package page until a new one is published.
346
+ - Updated dependencies [6936d07]
347
+ - Updated dependencies [59eb04d]
348
+ - Updated dependencies [9f05b7d]
349
+ - Updated dependencies [3b2af5e]
350
+ - Updated dependencies [7d2d112]
351
+ - Updated dependencies [5fa0d72]
352
+ - Updated dependencies [7bf3fb7]
353
+ - Updated dependencies [02b3b07]
354
+ - Updated dependencies [914c413]
355
+ - Updated dependencies [55809a0]
356
+ - Updated dependencies [ee2ff45]
357
+ - Updated dependencies [47cd3ec]
358
+ - Updated dependencies [52db1d1]
359
+ - Updated dependencies [5649efb]
360
+ - Updated dependencies [9d7d2de]
361
+ - Updated dependencies [c815c50]
362
+ - Updated dependencies [795ea05]
363
+ - Updated dependencies [2306a76]
364
+ - Updated dependencies [e5ea701]
365
+ - Updated dependencies [a40dcc1]
366
+ - Updated dependencies [def0d3e]
367
+ - Updated dependencies [8d0bb79]
368
+ - Updated dependencies [5acb58d]
369
+ - Updated dependencies [e222a53]
370
+ - Updated dependencies [2e3cf95]
371
+ - Updated dependencies [4c93387]
372
+ - Updated dependencies [504c8d5]
373
+ - Updated dependencies [a037f7c]
374
+ - Updated dependencies [6d5c4fa]
375
+ - Updated dependencies [3ee8ddf]
376
+ - Updated dependencies [16cef97]
377
+ - Updated dependencies [a79bd35]
378
+ - Updated dependencies [6ceaa4b]
379
+ - Updated dependencies [15ea214]
380
+ - Updated dependencies [de19489]
381
+ - Updated dependencies [c684d00]
382
+ - Updated dependencies [923c424]
383
+ - Updated dependencies [1ec36b7]
384
+ - Updated dependencies [5f2e54c]
385
+ - Updated dependencies [189373b]
386
+ - Updated dependencies [35ad101]
387
+ - Updated dependencies [ceb33a9]
388
+ - Updated dependencies [73d9795]
389
+ - Updated dependencies [8012960]
390
+ - Updated dependencies [f34f56b]
391
+ - Updated dependencies [f399618]
392
+ - Updated dependencies [75e9301]
393
+ - Updated dependencies [2810695]
394
+ - @objectstack/spec@17.2.0
395
+ - @objectstack/core@17.2.0
396
+ - @objectstack/service-knowledge@17.2.0
397
+
3
398
  ## 17.1.0
4
399
 
5
400
  ### Patch Changes
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [RAGFlow](https://github.com/infiniflow/ragflow) `IKnowledgeAdapter` for ObjectStack.
4
4
 
5
- Bridges the [Knowledge Protocol](https://docs.objectstack.ai/docs/protocol/knowledge) to a RAGFlow deployment via its HTTP API. RAGFlow handles chunking (DeepDoc), embedding, hybrid retrieval, and reranking; ObjectStack handles metadata-native sources and permission-aware filtering on top of the returned hits.
5
+ Bridges the [Knowledge Protocol](https://objectstack.ai/docs/protocol/knowledge) to a RAGFlow deployment via its HTTP API. RAGFlow handles chunking (DeepDoc), embedding, hybrid retrieval, and reranking; ObjectStack handles metadata-native sources and permission-aware filtering on top of the returned hits.
6
6
 
7
7
  ## Why RAGFlow?
8
8
 
package/dist/index.d.mts CHANGED
@@ -58,7 +58,7 @@ interface KnowledgeRagflowPluginOptions extends KnowledgeRagflowAdapterOptions {
58
58
  declare class KnowledgeRagflowPlugin implements Plugin {
59
59
  name: string;
60
60
  version: string;
61
- type: string;
61
+ type: "standard";
62
62
  private readonly adapter;
63
63
  constructor(opts: KnowledgeRagflowPluginOptions);
64
64
  init(_ctx: PluginContext): Promise<void>;
package/dist/index.d.ts CHANGED
@@ -58,7 +58,7 @@ interface KnowledgeRagflowPluginOptions extends KnowledgeRagflowAdapterOptions {
58
58
  declare class KnowledgeRagflowPlugin implements Plugin {
59
59
  name: string;
60
60
  version: string;
61
- type: string;
61
+ type: "standard";
62
62
  private readonly adapter;
63
63
  constructor(opts: KnowledgeRagflowPluginOptions);
64
64
  init(_ctx: PluginContext): Promise<void>;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { Plugin, PluginContext } from '@objectstack/core';\nimport type {\n IKnowledgeAdapter,\n IKnowledgeService,\n AdapterContext,\n AdapterSearchOptions,\n} from '@objectstack/spec/contracts';\nimport type {\n KnowledgeDocument,\n KnowledgeHit,\n KnowledgeSource,\n} from '@objectstack/spec/ai';\nimport { KNOWLEDGE_SERVICE } from '@objectstack/spec/contracts';\n\n/**\n * Subset of `fetch` used by the adapter. Inject in tests; defaults to\n * the global `fetch`.\n */\nexport type FetchLike = (\n input: string,\n init?: {\n method?: string;\n headers?: Record<string, string>;\n body?: string;\n signal?: AbortSignal;\n },\n) => Promise<{\n ok: boolean;\n status: number;\n statusText: string;\n text(): Promise<string>;\n json(): Promise<unknown>;\n}>;\n\nexport interface KnowledgeRagflowAdapterOptions {\n /** RAGFlow endpoint, e.g. `http://localhost:9380`. */\n endpoint: string;\n /** RAGFlow API key (Bearer token). */\n apiKey: string;\n /** Adapter id. @default 'ragflow' */\n id?: string;\n /** Override `fetch` for tests. */\n fetch?: FetchLike;\n /** Request timeout in milliseconds. @default 30000 */\n timeoutMs?: number;\n}\n\ninterface RagflowSourceOptions {\n datasetId: string;\n /** Optional rerank model id (overrides dataset default). */\n rerankModel?: string;\n /** Optional similarity threshold passed through to RAGFlow. */\n similarityThreshold?: number;\n /** Optional vector vs keyword weight in [0,1]. */\n vectorSimilarityWeight?: number;\n}\n\nfunction extractRagflowOptions(source: KnowledgeSource): RagflowSourceOptions {\n const opts = ((source as unknown as { options?: Record<string, unknown> }).options ?? {}) as\n Record<string, unknown>;\n const datasetId = opts.datasetId;\n if (typeof datasetId !== 'string' || !datasetId) {\n throw new Error(\n `RAGFlow adapter requires source.options.datasetId on source '${source.id}'`,\n );\n }\n return {\n datasetId,\n rerankModel: typeof opts.rerankModel === 'string' ? opts.rerankModel : undefined,\n similarityThreshold:\n typeof opts.similarityThreshold === 'number' ? opts.similarityThreshold : undefined,\n vectorSimilarityWeight:\n typeof opts.vectorSimilarityWeight === 'number'\n ? opts.vectorSimilarityWeight\n : undefined,\n };\n}\n\n/**\n * RAGFlow adapter. Maps {@link KnowledgeDocument} upserts to the\n * dataset's chunk API, delegates retrieval to `/api/v1/retrieval`, and\n * returns {@link KnowledgeHit}s with `sourceRecordId` preserved so the\n * orchestrator can run a permission re-check.\n */\nexport class KnowledgeRagflowAdapter implements IKnowledgeAdapter {\n readonly id: string;\n private readonly endpoint: string;\n private readonly apiKey: string;\n private readonly fetchImpl: FetchLike;\n private readonly timeoutMs: number;\n\n constructor(opts: KnowledgeRagflowAdapterOptions) {\n if (!opts.endpoint) throw new Error('RAGFlow adapter: endpoint required');\n if (!opts.apiKey) throw new Error('RAGFlow adapter: apiKey required');\n this.id = opts.id ?? 'ragflow';\n this.endpoint = opts.endpoint.replace(/\\/+$/, '');\n this.apiKey = opts.apiKey;\n this.fetchImpl = opts.fetch ?? ((globalThis as { fetch?: FetchLike }).fetch as FetchLike);\n this.timeoutMs = opts.timeoutMs ?? 30000;\n if (!this.fetchImpl) {\n throw new Error('RAGFlow adapter: no fetch available; pass options.fetch');\n }\n }\n\n async upsert(docs: KnowledgeDocument[], ctx: AdapterContext): Promise<void> {\n const { datasetId } = extractRagflowOptions(ctx.source);\n // RAGFlow models documents in two layers: documents (file-like) and\n // chunks (text blocks). We treat each KnowledgeDocument as a single\n // chunk-set: delete existing chunks with the same external id, then\n // upload as `content` chunks tagged with our document id.\n for (const doc of docs) {\n await this.deleteChunksByDocumentId(datasetId, doc.id);\n await this.request(`/api/v1/datasets/${datasetId}/chunks`, {\n method: 'POST',\n body: JSON.stringify({\n content: doc.content,\n // RAGFlow accepts arbitrary metadata used for filtering at\n // retrieval time. We always stamp `objectstack_doc_id` so\n // delete() can find these chunks again.\n important_keywords: doc.title ? [doc.title] : undefined,\n metadata: {\n ...(doc.metadata ?? {}),\n objectstack_doc_id: doc.id,\n objectstack_source_id: doc.sourceId,\n objectstack_record_id: doc.sourceRecordId,\n title: doc.title,\n },\n }),\n });\n }\n }\n\n async delete(documentIds: string[], ctx: AdapterContext): Promise<void> {\n const { datasetId } = extractRagflowOptions(ctx.source);\n for (const id of documentIds) {\n await this.deleteChunksByDocumentId(datasetId, id);\n }\n }\n\n async search(query: string, opts: AdapterSearchOptions): Promise<KnowledgeHit[]> {\n const { datasetId, rerankModel, similarityThreshold, vectorSimilarityWeight } =\n extractRagflowOptions(opts.source);\n const body: Record<string, unknown> = {\n question: query,\n dataset_ids: [datasetId],\n top_k: opts.topK,\n keyword: true,\n };\n if (rerankModel) body.rerank_id = rerankModel;\n if (typeof similarityThreshold === 'number') body.similarity_threshold = similarityThreshold;\n if (typeof vectorSimilarityWeight === 'number')\n body.vector_similarity_weight = vectorSimilarityWeight;\n if (opts.filter) body.metadata_condition = { ...opts.filter };\n\n const res = await this.request('/api/v1/retrieval', {\n method: 'POST',\n body: JSON.stringify(body),\n });\n const data = (res?.data ?? {}) as { chunks?: RagflowChunkHit[] };\n const chunks = data.chunks ?? [];\n return chunks.slice(0, opts.topK).map<KnowledgeHit>((c) => {\n const md = (c.metadata ?? {}) as Record<string, unknown>;\n const docId =\n (md.objectstack_doc_id as string | undefined) ??\n c.document_id ??\n c.doc_id ??\n c.id;\n const recordId = md.objectstack_record_id as string | undefined;\n return {\n chunkId: c.id ?? `${docId}#${c.position ?? 0}`,\n documentId: docId ?? c.id ?? 'unknown',\n sourceId: opts.source.id,\n sourceRecordId: recordId,\n score: c.similarity ?? c.score ?? 0,\n snippet: c.content ?? c.content_with_weight ?? '',\n title: (md.title as string | undefined) ?? c.document_name,\n metadata: md,\n };\n });\n }\n\n async healthCheck(): Promise<{ ok: boolean; message?: string }> {\n try {\n await this.request('/api/v1/datasets?page=1&page_size=1', { method: 'GET' });\n return { ok: true };\n } catch (err) {\n return { ok: false, message: err instanceof Error ? err.message : String(err) };\n }\n }\n\n private async deleteChunksByDocumentId(datasetId: string, docId: string): Promise<void> {\n // Find chunks with our stamped metadata, then delete by chunk id.\n const found = (await this.request(`/api/v1/retrieval`, {\n method: 'POST',\n body: JSON.stringify({\n question: docId,\n dataset_ids: [datasetId],\n top_k: 256,\n keyword: false,\n metadata_condition: { objectstack_doc_id: docId },\n }),\n })) as { data?: { chunks?: Array<{ id?: string }> } };\n const ids = (found.data?.chunks ?? [])\n .map((c) => c.id)\n .filter((x): x is string => typeof x === 'string');\n if (ids.length === 0) return;\n await this.request(`/api/v1/datasets/${datasetId}/chunks`, {\n method: 'DELETE',\n body: JSON.stringify({ chunk_ids: ids }),\n });\n }\n\n private async request(\n path: string,\n init: { method: string; body?: string },\n ): Promise<{ data?: unknown; code?: number; message?: string }> {\n const controller = new AbortController();\n const t = setTimeout(() => controller.abort(), this.timeoutMs);\n try {\n const res = await this.fetchImpl(`${this.endpoint}${path}`, {\n method: init.method,\n headers: {\n 'content-type': 'application/json',\n authorization: `Bearer ${this.apiKey}`,\n },\n body: init.body,\n signal: controller.signal,\n });\n const raw = await res.text();\n let parsed: { data?: unknown; code?: number; message?: string } = {};\n if (raw) {\n try {\n parsed = JSON.parse(raw) as typeof parsed;\n } catch {\n if (!res.ok) {\n throw new Error(\n `RAGFlow ${init.method} ${path} → ${res.status} ${res.statusText}: ${raw.slice(0, 200)}`,\n );\n }\n }\n }\n if (!res.ok || (typeof parsed.code === 'number' && parsed.code !== 0 && parsed.code !== 200)) {\n throw new Error(\n `RAGFlow ${init.method} ${path} → ${res.status} ${res.statusText}${\n parsed.message ? ` (${parsed.message})` : ''\n }`,\n );\n }\n return parsed;\n } finally {\n clearTimeout(t);\n }\n }\n}\n\ninterface RagflowChunkHit {\n id?: string;\n document_id?: string;\n doc_id?: string;\n document_name?: string;\n content?: string;\n content_with_weight?: string;\n similarity?: number;\n score?: number;\n position?: number;\n metadata?: Record<string, unknown>;\n}\n\n/* ---------------------------------------------------------------- */\n/* Kernel plugin glue */\n/* ---------------------------------------------------------------- */\n\nexport interface KnowledgeRagflowPluginOptions extends KnowledgeRagflowAdapterOptions {}\n\nexport class KnowledgeRagflowPlugin implements Plugin {\n name = 'com.objectstack.plugin.knowledge-ragflow';\n version = '0.1.0';\n type = 'standard';\n\n private readonly adapter: KnowledgeRagflowAdapter;\n\n constructor(opts: KnowledgeRagflowPluginOptions) {\n this.adapter = new KnowledgeRagflowAdapter(opts);\n }\n\n async init(_ctx: PluginContext): Promise<void> {\n // No-op: actual registration happens in start() once service is available.\n }\n\n async start(ctx: PluginContext): Promise<void> {\n let svc: IKnowledgeService | undefined;\n try {\n svc = ctx.getService<IKnowledgeService>(KNOWLEDGE_SERVICE);\n } catch {\n ctx.logger.warn?.(\n 'KnowledgeRagflowPlugin: IKnowledgeService not registered — install KnowledgeServicePlugin first.',\n );\n return;\n }\n svc.registerAdapter(this.adapter.id, this.adapter);\n ctx.logger.info?.(\n `KnowledgeRagflowPlugin: adapter '${this.adapter.id}' registered (endpoint=${(this.adapter as unknown as { endpoint: string }).endpoint}).`,\n );\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAcA,uBAAkC;AA6ClC,SAAS,sBAAsB,QAA+C;AAC5E,QAAM,OAAS,OAA4D,WAAW,CAAC;AAEvF,QAAM,YAAY,KAAK;AACvB,MAAI,OAAO,cAAc,YAAY,CAAC,WAAW;AAC/C,UAAM,IAAI;AAAA,MACR,gEAAgE,OAAO,EAAE;AAAA,IAC3E;AAAA,EACF;AACA,SAAO;AAAA,IACL;AAAA,IACA,aAAa,OAAO,KAAK,gBAAgB,WAAW,KAAK,cAAc;AAAA,IACvE,qBACE,OAAO,KAAK,wBAAwB,WAAW,KAAK,sBAAsB;AAAA,IAC5E,wBACE,OAAO,KAAK,2BAA2B,WACnC,KAAK,yBACL;AAAA,EACR;AACF;AAQO,IAAM,0BAAN,MAA2D;AAAA,EAOhE,YAAY,MAAsC;AAChD,QAAI,CAAC,KAAK,SAAU,OAAM,IAAI,MAAM,oCAAoC;AACxE,QAAI,CAAC,KAAK,OAAQ,OAAM,IAAI,MAAM,kCAAkC;AACpE,SAAK,KAAK,KAAK,MAAM;AACrB,SAAK,WAAW,KAAK,SAAS,QAAQ,QAAQ,EAAE;AAChD,SAAK,SAAS,KAAK;AACnB,SAAK,YAAY,KAAK,SAAW,WAAqC;AACtE,SAAK,YAAY,KAAK,aAAa;AACnC,QAAI,CAAC,KAAK,WAAW;AACnB,YAAM,IAAI,MAAM,yDAAyD;AAAA,IAC3E;AAAA,EACF;AAAA,EAEA,MAAM,OAAO,MAA2B,KAAoC;AAC1E,UAAM,EAAE,UAAU,IAAI,sBAAsB,IAAI,MAAM;AAKtD,eAAW,OAAO,MAAM;AACtB,YAAM,KAAK,yBAAyB,WAAW,IAAI,EAAE;AACrD,YAAM,KAAK,QAAQ,oBAAoB,SAAS,WAAW;AAAA,QACzD,QAAQ;AAAA,QACR,MAAM,KAAK,UAAU;AAAA,UACnB,SAAS,IAAI;AAAA;AAAA;AAAA;AAAA,UAIb,oBAAoB,IAAI,QAAQ,CAAC,IAAI,KAAK,IAAI;AAAA,UAC9C,UAAU;AAAA,YACR,GAAI,IAAI,YAAY,CAAC;AAAA,YACrB,oBAAoB,IAAI;AAAA,YACxB,uBAAuB,IAAI;AAAA,YAC3B,uBAAuB,IAAI;AAAA,YAC3B,OAAO,IAAI;AAAA,UACb;AAAA,QACF,CAAC;AAAA,MACH,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEA,MAAM,OAAO,aAAuB,KAAoC;AACtE,UAAM,EAAE,UAAU,IAAI,sBAAsB,IAAI,MAAM;AACtD,eAAW,MAAM,aAAa;AAC5B,YAAM,KAAK,yBAAyB,WAAW,EAAE;AAAA,IACnD;AAAA,EACF;AAAA,EAEA,MAAM,OAAO,OAAe,MAAqD;AAC/E,UAAM,EAAE,WAAW,aAAa,qBAAqB,uBAAuB,IAC1E,sBAAsB,KAAK,MAAM;AACnC,UAAM,OAAgC;AAAA,MACpC,UAAU;AAAA,MACV,aAAa,CAAC,SAAS;AAAA,MACvB,OAAO,KAAK;AAAA,MACZ,SAAS;AAAA,IACX;AACA,QAAI,YAAa,MAAK,YAAY;AAClC,QAAI,OAAO,wBAAwB,SAAU,MAAK,uBAAuB;AACzE,QAAI,OAAO,2BAA2B;AACpC,WAAK,2BAA2B;AAClC,QAAI,KAAK,OAAQ,MAAK,qBAAqB,EAAE,GAAG,KAAK,OAAO;AAE5D,UAAM,MAAM,MAAM,KAAK,QAAQ,qBAAqB;AAAA,MAClD,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU,IAAI;AAAA,IAC3B,CAAC;AACD,UAAM,OAAQ,KAAK,QAAQ,CAAC;AAC5B,UAAM,SAAS,KAAK,UAAU,CAAC;AAC/B,WAAO,OAAO,MAAM,GAAG,KAAK,IAAI,EAAE,IAAkB,CAAC,MAAM;AACzD,YAAM,KAAM,EAAE,YAAY,CAAC;AAC3B,YAAM,QACH,GAAG,sBACJ,EAAE,eACF,EAAE,UACF,EAAE;AACJ,YAAM,WAAW,GAAG;AACpB,aAAO;AAAA,QACL,SAAS,EAAE,MAAM,GAAG,KAAK,IAAI,EAAE,YAAY,CAAC;AAAA,QAC5C,YAAY,SAAS,EAAE,MAAM;AAAA,QAC7B,UAAU,KAAK,OAAO;AAAA,QACtB,gBAAgB;AAAA,QAChB,OAAO,EAAE,cAAc,EAAE,SAAS;AAAA,QAClC,SAAS,EAAE,WAAW,EAAE,uBAAuB;AAAA,QAC/C,OAAQ,GAAG,SAAgC,EAAE;AAAA,QAC7C,UAAU;AAAA,MACZ;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,cAA0D;AAC9D,QAAI;AACF,YAAM,KAAK,QAAQ,uCAAuC,EAAE,QAAQ,MAAM,CAAC;AAC3E,aAAO,EAAE,IAAI,KAAK;AAAA,IACpB,SAAS,KAAK;AACZ,aAAO,EAAE,IAAI,OAAO,SAAS,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,EAAE;AAAA,IAChF;AAAA,EACF;AAAA,EAEA,MAAc,yBAAyB,WAAmB,OAA8B;AAEtF,UAAM,QAAS,MAAM,KAAK,QAAQ,qBAAqB;AAAA,MACrD,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU;AAAA,QACnB,UAAU;AAAA,QACV,aAAa,CAAC,SAAS;AAAA,QACvB,OAAO;AAAA,QACP,SAAS;AAAA,QACT,oBAAoB,EAAE,oBAAoB,MAAM;AAAA,MAClD,CAAC;AAAA,IACH,CAAC;AACD,UAAM,OAAO,MAAM,MAAM,UAAU,CAAC,GACjC,IAAI,CAAC,MAAM,EAAE,EAAE,EACf,OAAO,CAAC,MAAmB,OAAO,MAAM,QAAQ;AACnD,QAAI,IAAI,WAAW,EAAG;AACtB,UAAM,KAAK,QAAQ,oBAAoB,SAAS,WAAW;AAAA,MACzD,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU,EAAE,WAAW,IAAI,CAAC;AAAA,IACzC,CAAC;AAAA,EACH;AAAA,EAEA,MAAc,QACZ,MACA,MAC8D;AAC9D,UAAM,aAAa,IAAI,gBAAgB;AACvC,UAAM,IAAI,WAAW,MAAM,WAAW,MAAM,GAAG,KAAK,SAAS;AAC7D,QAAI;AACF,YAAM,MAAM,MAAM,KAAK,UAAU,GAAG,KAAK,QAAQ,GAAG,IAAI,IAAI;AAAA,QAC1D,QAAQ,KAAK;AAAA,QACb,SAAS;AAAA,UACP,gBAAgB;AAAA,UAChB,eAAe,UAAU,KAAK,MAAM;AAAA,QACtC;AAAA,QACA,MAAM,KAAK;AAAA,QACX,QAAQ,WAAW;AAAA,MACrB,CAAC;AACD,YAAM,MAAM,MAAM,IAAI,KAAK;AAC3B,UAAI,SAA8D,CAAC;AACnE,UAAI,KAAK;AACP,YAAI;AACF,mBAAS,KAAK,MAAM,GAAG;AAAA,QACzB,QAAQ;AACN,cAAI,CAAC,IAAI,IAAI;AACX,kBAAM,IAAI;AAAA,cACR,WAAW,KAAK,MAAM,IAAI,IAAI,WAAM,IAAI,MAAM,IAAI,IAAI,UAAU,KAAK,IAAI,MAAM,GAAG,GAAG,CAAC;AAAA,YACxF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AACA,UAAI,CAAC,IAAI,MAAO,OAAO,OAAO,SAAS,YAAY,OAAO,SAAS,KAAK,OAAO,SAAS,KAAM;AAC5F,cAAM,IAAI;AAAA,UACR,WAAW,KAAK,MAAM,IAAI,IAAI,WAAM,IAAI,MAAM,IAAI,IAAI,UAAU,GAC9D,OAAO,UAAU,KAAK,OAAO,OAAO,MAAM,EAC5C;AAAA,QACF;AAAA,MACF;AACA,aAAO;AAAA,IACT,UAAE;AACA,mBAAa,CAAC;AAAA,IAChB;AAAA,EACF;AACF;AAqBO,IAAM,yBAAN,MAA+C;AAAA,EAOpD,YAAY,MAAqC;AANjD,gBAAO;AACP,mBAAU;AACV,gBAAO;AAKL,SAAK,UAAU,IAAI,wBAAwB,IAAI;AAAA,EACjD;AAAA,EAEA,MAAM,KAAK,MAAoC;AAAA,EAE/C;AAAA,EAEA,MAAM,MAAM,KAAmC;AAC7C,QAAI;AACJ,QAAI;AACF,YAAM,IAAI,WAA8B,kCAAiB;AAAA,IAC3D,QAAQ;AACN,UAAI,OAAO;AAAA,QACT;AAAA,MACF;AACA;AAAA,IACF;AACA,QAAI,gBAAgB,KAAK,QAAQ,IAAI,KAAK,OAAO;AACjD,QAAI,OAAO;AAAA,MACT,oCAAoC,KAAK,QAAQ,EAAE,0BAA2B,KAAK,QAA4C,QAAQ;AAAA,IACzI;AAAA,EACF;AACF;","names":[]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { Plugin, PluginContext } from '@objectstack/core';\nimport type {\n IKnowledgeAdapter,\n IKnowledgeService,\n AdapterContext,\n AdapterSearchOptions,\n} from '@objectstack/spec/contracts';\nimport type {\n KnowledgeDocument,\n KnowledgeHit,\n KnowledgeSource,\n} from '@objectstack/spec/ai';\nimport { KNOWLEDGE_SERVICE } from '@objectstack/spec/contracts';\n\n/**\n * Subset of `fetch` used by the adapter. Inject in tests; defaults to\n * the global `fetch`.\n */\nexport type FetchLike = (\n input: string,\n init?: {\n method?: string;\n headers?: Record<string, string>;\n body?: string;\n signal?: AbortSignal;\n },\n) => Promise<{\n ok: boolean;\n status: number;\n statusText: string;\n text(): Promise<string>;\n json(): Promise<unknown>;\n}>;\n\nexport interface KnowledgeRagflowAdapterOptions {\n /** RAGFlow endpoint, e.g. `http://localhost:9380`. */\n endpoint: string;\n /** RAGFlow API key (Bearer token). */\n apiKey: string;\n /** Adapter id. @default 'ragflow' */\n id?: string;\n /** Override `fetch` for tests. */\n fetch?: FetchLike;\n /** Request timeout in milliseconds. @default 30000 */\n timeoutMs?: number;\n}\n\ninterface RagflowSourceOptions {\n datasetId: string;\n /** Optional rerank model id (overrides dataset default). */\n rerankModel?: string;\n /** Optional similarity threshold passed through to RAGFlow. */\n similarityThreshold?: number;\n /** Optional vector vs keyword weight in [0,1]. */\n vectorSimilarityWeight?: number;\n}\n\nfunction extractRagflowOptions(source: KnowledgeSource): RagflowSourceOptions {\n const opts = ((source as unknown as { options?: Record<string, unknown> }).options ?? {}) as\n Record<string, unknown>;\n const datasetId = opts.datasetId;\n if (typeof datasetId !== 'string' || !datasetId) {\n throw new Error(\n `RAGFlow adapter requires source.options.datasetId on source '${source.id}'`,\n );\n }\n return {\n datasetId,\n rerankModel: typeof opts.rerankModel === 'string' ? opts.rerankModel : undefined,\n similarityThreshold:\n typeof opts.similarityThreshold === 'number' ? opts.similarityThreshold : undefined,\n vectorSimilarityWeight:\n typeof opts.vectorSimilarityWeight === 'number'\n ? opts.vectorSimilarityWeight\n : undefined,\n };\n}\n\n/**\n * RAGFlow adapter. Maps {@link KnowledgeDocument} upserts to the\n * dataset's chunk API, delegates retrieval to `/api/v1/retrieval`, and\n * returns {@link KnowledgeHit}s with `sourceRecordId` preserved so the\n * orchestrator can run a permission re-check.\n */\nexport class KnowledgeRagflowAdapter implements IKnowledgeAdapter {\n readonly id: string;\n private readonly endpoint: string;\n private readonly apiKey: string;\n private readonly fetchImpl: FetchLike;\n private readonly timeoutMs: number;\n\n constructor(opts: KnowledgeRagflowAdapterOptions) {\n if (!opts.endpoint) throw new Error('RAGFlow adapter: endpoint required');\n if (!opts.apiKey) throw new Error('RAGFlow adapter: apiKey required');\n this.id = opts.id ?? 'ragflow';\n this.endpoint = opts.endpoint.replace(/\\/+$/, '');\n this.apiKey = opts.apiKey;\n this.fetchImpl = opts.fetch ?? ((globalThis as { fetch?: FetchLike }).fetch as FetchLike);\n this.timeoutMs = opts.timeoutMs ?? 30000;\n if (!this.fetchImpl) {\n throw new Error('RAGFlow adapter: no fetch available; pass options.fetch');\n }\n }\n\n async upsert(docs: KnowledgeDocument[], ctx: AdapterContext): Promise<void> {\n const { datasetId } = extractRagflowOptions(ctx.source);\n // RAGFlow models documents in two layers: documents (file-like) and\n // chunks (text blocks). We treat each KnowledgeDocument as a single\n // chunk-set: delete existing chunks with the same external id, then\n // upload as `content` chunks tagged with our document id.\n for (const doc of docs) {\n await this.deleteChunksByDocumentId(datasetId, doc.id);\n await this.request(`/api/v1/datasets/${datasetId}/chunks`, {\n method: 'POST',\n body: JSON.stringify({\n content: doc.content,\n // RAGFlow accepts arbitrary metadata used for filtering at\n // retrieval time. We always stamp `objectstack_doc_id` so\n // delete() can find these chunks again.\n important_keywords: doc.title ? [doc.title] : undefined,\n metadata: {\n ...(doc.metadata ?? {}),\n objectstack_doc_id: doc.id,\n objectstack_source_id: doc.sourceId,\n objectstack_record_id: doc.sourceRecordId,\n title: doc.title,\n },\n }),\n });\n }\n }\n\n async delete(documentIds: string[], ctx: AdapterContext): Promise<void> {\n const { datasetId } = extractRagflowOptions(ctx.source);\n for (const id of documentIds) {\n await this.deleteChunksByDocumentId(datasetId, id);\n }\n }\n\n async search(query: string, opts: AdapterSearchOptions): Promise<KnowledgeHit[]> {\n const { datasetId, rerankModel, similarityThreshold, vectorSimilarityWeight } =\n extractRagflowOptions(opts.source);\n const body: Record<string, unknown> = {\n question: query,\n dataset_ids: [datasetId],\n top_k: opts.topK,\n keyword: true,\n };\n if (rerankModel) body.rerank_id = rerankModel;\n if (typeof similarityThreshold === 'number') body.similarity_threshold = similarityThreshold;\n if (typeof vectorSimilarityWeight === 'number')\n body.vector_similarity_weight = vectorSimilarityWeight;\n if (opts.filter) body.metadata_condition = { ...opts.filter };\n\n const res = await this.request('/api/v1/retrieval', {\n method: 'POST',\n body: JSON.stringify(body),\n });\n const data = (res?.data ?? {}) as { chunks?: RagflowChunkHit[] };\n const chunks = data.chunks ?? [];\n return chunks.slice(0, opts.topK).map<KnowledgeHit>((c) => {\n const md = (c.metadata ?? {}) as Record<string, unknown>;\n const docId =\n (md.objectstack_doc_id as string | undefined) ??\n c.document_id ??\n c.doc_id ??\n c.id;\n const recordId = md.objectstack_record_id as string | undefined;\n return {\n chunkId: c.id ?? `${docId}#${c.position ?? 0}`,\n documentId: docId ?? c.id ?? 'unknown',\n sourceId: opts.source.id,\n sourceRecordId: recordId,\n score: c.similarity ?? c.score ?? 0,\n snippet: c.content ?? c.content_with_weight ?? '',\n title: (md.title as string | undefined) ?? c.document_name,\n metadata: md,\n };\n });\n }\n\n async healthCheck(): Promise<{ ok: boolean; message?: string }> {\n try {\n await this.request('/api/v1/datasets?page=1&page_size=1', { method: 'GET' });\n return { ok: true };\n } catch (err) {\n return { ok: false, message: err instanceof Error ? err.message : String(err) };\n }\n }\n\n private async deleteChunksByDocumentId(datasetId: string, docId: string): Promise<void> {\n // Find chunks with our stamped metadata, then delete by chunk id.\n const found = (await this.request(`/api/v1/retrieval`, {\n method: 'POST',\n body: JSON.stringify({\n question: docId,\n dataset_ids: [datasetId],\n top_k: 256,\n keyword: false,\n metadata_condition: { objectstack_doc_id: docId },\n }),\n })) as { data?: { chunks?: Array<{ id?: string }> } };\n const ids = (found.data?.chunks ?? [])\n .map((c) => c.id)\n .filter((x): x is string => typeof x === 'string');\n if (ids.length === 0) return;\n await this.request(`/api/v1/datasets/${datasetId}/chunks`, {\n method: 'DELETE',\n body: JSON.stringify({ chunk_ids: ids }),\n });\n }\n\n private async request(\n path: string,\n init: { method: string; body?: string },\n ): Promise<{ data?: unknown; code?: number; message?: string }> {\n const controller = new AbortController();\n const t = setTimeout(() => controller.abort(), this.timeoutMs);\n try {\n const res = await this.fetchImpl(`${this.endpoint}${path}`, {\n method: init.method,\n headers: {\n 'content-type': 'application/json',\n authorization: `Bearer ${this.apiKey}`,\n },\n body: init.body,\n signal: controller.signal,\n });\n const raw = await res.text();\n let parsed: { data?: unknown; code?: number; message?: string } = {};\n if (raw) {\n try {\n parsed = JSON.parse(raw) as typeof parsed;\n } catch {\n if (!res.ok) {\n throw new Error(\n `RAGFlow ${init.method} ${path} → ${res.status} ${res.statusText}: ${raw.slice(0, 200)}`,\n );\n }\n }\n }\n if (!res.ok || (typeof parsed.code === 'number' && parsed.code !== 0 && parsed.code !== 200)) {\n throw new Error(\n `RAGFlow ${init.method} ${path} → ${res.status} ${res.statusText}${\n parsed.message ? ` (${parsed.message})` : ''\n }`,\n );\n }\n return parsed;\n } finally {\n clearTimeout(t);\n }\n }\n}\n\ninterface RagflowChunkHit {\n id?: string;\n document_id?: string;\n doc_id?: string;\n document_name?: string;\n content?: string;\n content_with_weight?: string;\n similarity?: number;\n score?: number;\n position?: number;\n metadata?: Record<string, unknown>;\n}\n\n/* ---------------------------------------------------------------- */\n/* Kernel plugin glue */\n/* ---------------------------------------------------------------- */\n\nexport interface KnowledgeRagflowPluginOptions extends KnowledgeRagflowAdapterOptions {}\n\nexport class KnowledgeRagflowPlugin implements Plugin {\n name = 'com.objectstack.plugin.knowledge-ragflow';\n version = '0.1.0';\n type = 'standard' as const;\n\n private readonly adapter: KnowledgeRagflowAdapter;\n\n constructor(opts: KnowledgeRagflowPluginOptions) {\n this.adapter = new KnowledgeRagflowAdapter(opts);\n }\n\n async init(_ctx: PluginContext): Promise<void> {\n // No-op: actual registration happens in start() once service is available.\n }\n\n async start(ctx: PluginContext): Promise<void> {\n let svc: IKnowledgeService | undefined;\n try {\n svc = ctx.getService<IKnowledgeService>(KNOWLEDGE_SERVICE);\n } catch {\n ctx.logger.warn?.(\n 'KnowledgeRagflowPlugin: IKnowledgeService not registered — install KnowledgeServicePlugin first.',\n );\n return;\n }\n svc.registerAdapter(this.adapter.id, this.adapter);\n ctx.logger.info?.(\n `KnowledgeRagflowPlugin: adapter '${this.adapter.id}' registered (endpoint=${(this.adapter as unknown as { endpoint: string }).endpoint}).`,\n );\n }\n}\n"],"mappings":"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","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { Plugin, PluginContext } from '@objectstack/core';\nimport type {\n IKnowledgeAdapter,\n IKnowledgeService,\n AdapterContext,\n AdapterSearchOptions,\n} from '@objectstack/spec/contracts';\nimport type {\n KnowledgeDocument,\n KnowledgeHit,\n KnowledgeSource,\n} from '@objectstack/spec/ai';\nimport { KNOWLEDGE_SERVICE } from '@objectstack/spec/contracts';\n\n/**\n * Subset of `fetch` used by the adapter. Inject in tests; defaults to\n * the global `fetch`.\n */\nexport type FetchLike = (\n input: string,\n init?: {\n method?: string;\n headers?: Record<string, string>;\n body?: string;\n signal?: AbortSignal;\n },\n) => Promise<{\n ok: boolean;\n status: number;\n statusText: string;\n text(): Promise<string>;\n json(): Promise<unknown>;\n}>;\n\nexport interface KnowledgeRagflowAdapterOptions {\n /** RAGFlow endpoint, e.g. `http://localhost:9380`. */\n endpoint: string;\n /** RAGFlow API key (Bearer token). */\n apiKey: string;\n /** Adapter id. @default 'ragflow' */\n id?: string;\n /** Override `fetch` for tests. */\n fetch?: FetchLike;\n /** Request timeout in milliseconds. @default 30000 */\n timeoutMs?: number;\n}\n\ninterface RagflowSourceOptions {\n datasetId: string;\n /** Optional rerank model id (overrides dataset default). */\n rerankModel?: string;\n /** Optional similarity threshold passed through to RAGFlow. */\n similarityThreshold?: number;\n /** Optional vector vs keyword weight in [0,1]. */\n vectorSimilarityWeight?: number;\n}\n\nfunction extractRagflowOptions(source: KnowledgeSource): RagflowSourceOptions {\n const opts = ((source as unknown as { options?: Record<string, unknown> }).options ?? {}) as\n Record<string, unknown>;\n const datasetId = opts.datasetId;\n if (typeof datasetId !== 'string' || !datasetId) {\n throw new Error(\n `RAGFlow adapter requires source.options.datasetId on source '${source.id}'`,\n );\n }\n return {\n datasetId,\n rerankModel: typeof opts.rerankModel === 'string' ? opts.rerankModel : undefined,\n similarityThreshold:\n typeof opts.similarityThreshold === 'number' ? opts.similarityThreshold : undefined,\n vectorSimilarityWeight:\n typeof opts.vectorSimilarityWeight === 'number'\n ? opts.vectorSimilarityWeight\n : undefined,\n };\n}\n\n/**\n * RAGFlow adapter. Maps {@link KnowledgeDocument} upserts to the\n * dataset's chunk API, delegates retrieval to `/api/v1/retrieval`, and\n * returns {@link KnowledgeHit}s with `sourceRecordId` preserved so the\n * orchestrator can run a permission re-check.\n */\nexport class KnowledgeRagflowAdapter implements IKnowledgeAdapter {\n readonly id: string;\n private readonly endpoint: string;\n private readonly apiKey: string;\n private readonly fetchImpl: FetchLike;\n private readonly timeoutMs: number;\n\n constructor(opts: KnowledgeRagflowAdapterOptions) {\n if (!opts.endpoint) throw new Error('RAGFlow adapter: endpoint required');\n if (!opts.apiKey) throw new Error('RAGFlow adapter: apiKey required');\n this.id = opts.id ?? 'ragflow';\n this.endpoint = opts.endpoint.replace(/\\/+$/, '');\n this.apiKey = opts.apiKey;\n this.fetchImpl = opts.fetch ?? ((globalThis as { fetch?: FetchLike }).fetch as FetchLike);\n this.timeoutMs = opts.timeoutMs ?? 30000;\n if (!this.fetchImpl) {\n throw new Error('RAGFlow adapter: no fetch available; pass options.fetch');\n }\n }\n\n async upsert(docs: KnowledgeDocument[], ctx: AdapterContext): Promise<void> {\n const { datasetId } = extractRagflowOptions(ctx.source);\n // RAGFlow models documents in two layers: documents (file-like) and\n // chunks (text blocks). We treat each KnowledgeDocument as a single\n // chunk-set: delete existing chunks with the same external id, then\n // upload as `content` chunks tagged with our document id.\n for (const doc of docs) {\n await this.deleteChunksByDocumentId(datasetId, doc.id);\n await this.request(`/api/v1/datasets/${datasetId}/chunks`, {\n method: 'POST',\n body: JSON.stringify({\n content: doc.content,\n // RAGFlow accepts arbitrary metadata used for filtering at\n // retrieval time. We always stamp `objectstack_doc_id` so\n // delete() can find these chunks again.\n important_keywords: doc.title ? [doc.title] : undefined,\n metadata: {\n ...(doc.metadata ?? {}),\n objectstack_doc_id: doc.id,\n objectstack_source_id: doc.sourceId,\n objectstack_record_id: doc.sourceRecordId,\n title: doc.title,\n },\n }),\n });\n }\n }\n\n async delete(documentIds: string[], ctx: AdapterContext): Promise<void> {\n const { datasetId } = extractRagflowOptions(ctx.source);\n for (const id of documentIds) {\n await this.deleteChunksByDocumentId(datasetId, id);\n }\n }\n\n async search(query: string, opts: AdapterSearchOptions): Promise<KnowledgeHit[]> {\n const { datasetId, rerankModel, similarityThreshold, vectorSimilarityWeight } =\n extractRagflowOptions(opts.source);\n const body: Record<string, unknown> = {\n question: query,\n dataset_ids: [datasetId],\n top_k: opts.topK,\n keyword: true,\n };\n if (rerankModel) body.rerank_id = rerankModel;\n if (typeof similarityThreshold === 'number') body.similarity_threshold = similarityThreshold;\n if (typeof vectorSimilarityWeight === 'number')\n body.vector_similarity_weight = vectorSimilarityWeight;\n if (opts.filter) body.metadata_condition = { ...opts.filter };\n\n const res = await this.request('/api/v1/retrieval', {\n method: 'POST',\n body: JSON.stringify(body),\n });\n const data = (res?.data ?? {}) as { chunks?: RagflowChunkHit[] };\n const chunks = data.chunks ?? [];\n return chunks.slice(0, opts.topK).map<KnowledgeHit>((c) => {\n const md = (c.metadata ?? {}) as Record<string, unknown>;\n const docId =\n (md.objectstack_doc_id as string | undefined) ??\n c.document_id ??\n c.doc_id ??\n c.id;\n const recordId = md.objectstack_record_id as string | undefined;\n return {\n chunkId: c.id ?? `${docId}#${c.position ?? 0}`,\n documentId: docId ?? c.id ?? 'unknown',\n sourceId: opts.source.id,\n sourceRecordId: recordId,\n score: c.similarity ?? c.score ?? 0,\n snippet: c.content ?? c.content_with_weight ?? '',\n title: (md.title as string | undefined) ?? c.document_name,\n metadata: md,\n };\n });\n }\n\n async healthCheck(): Promise<{ ok: boolean; message?: string }> {\n try {\n await this.request('/api/v1/datasets?page=1&page_size=1', { method: 'GET' });\n return { ok: true };\n } catch (err) {\n return { ok: false, message: err instanceof Error ? err.message : String(err) };\n }\n }\n\n private async deleteChunksByDocumentId(datasetId: string, docId: string): Promise<void> {\n // Find chunks with our stamped metadata, then delete by chunk id.\n const found = (await this.request(`/api/v1/retrieval`, {\n method: 'POST',\n body: JSON.stringify({\n question: docId,\n dataset_ids: [datasetId],\n top_k: 256,\n keyword: false,\n metadata_condition: { objectstack_doc_id: docId },\n }),\n })) as { data?: { chunks?: Array<{ id?: string }> } };\n const ids = (found.data?.chunks ?? [])\n .map((c) => c.id)\n .filter((x): x is string => typeof x === 'string');\n if (ids.length === 0) return;\n await this.request(`/api/v1/datasets/${datasetId}/chunks`, {\n method: 'DELETE',\n body: JSON.stringify({ chunk_ids: ids }),\n });\n }\n\n private async request(\n path: string,\n init: { method: string; body?: string },\n ): Promise<{ data?: unknown; code?: number; message?: string }> {\n const controller = new AbortController();\n const t = setTimeout(() => controller.abort(), this.timeoutMs);\n try {\n const res = await this.fetchImpl(`${this.endpoint}${path}`, {\n method: init.method,\n headers: {\n 'content-type': 'application/json',\n authorization: `Bearer ${this.apiKey}`,\n },\n body: init.body,\n signal: controller.signal,\n });\n const raw = await res.text();\n let parsed: { data?: unknown; code?: number; message?: string } = {};\n if (raw) {\n try {\n parsed = JSON.parse(raw) as typeof parsed;\n } catch {\n if (!res.ok) {\n throw new Error(\n `RAGFlow ${init.method} ${path} → ${res.status} ${res.statusText}: ${raw.slice(0, 200)}`,\n );\n }\n }\n }\n if (!res.ok || (typeof parsed.code === 'number' && parsed.code !== 0 && parsed.code !== 200)) {\n throw new Error(\n `RAGFlow ${init.method} ${path} → ${res.status} ${res.statusText}${\n parsed.message ? ` (${parsed.message})` : ''\n }`,\n );\n }\n return parsed;\n } finally {\n clearTimeout(t);\n }\n }\n}\n\ninterface RagflowChunkHit {\n id?: string;\n document_id?: string;\n doc_id?: string;\n document_name?: string;\n content?: string;\n content_with_weight?: string;\n similarity?: number;\n score?: number;\n position?: number;\n metadata?: Record<string, unknown>;\n}\n\n/* ---------------------------------------------------------------- */\n/* Kernel plugin glue */\n/* ---------------------------------------------------------------- */\n\nexport interface KnowledgeRagflowPluginOptions extends KnowledgeRagflowAdapterOptions {}\n\nexport class KnowledgeRagflowPlugin implements Plugin {\n name = 'com.objectstack.plugin.knowledge-ragflow';\n version = '0.1.0';\n type = 'standard';\n\n private readonly adapter: KnowledgeRagflowAdapter;\n\n constructor(opts: KnowledgeRagflowPluginOptions) {\n this.adapter = new KnowledgeRagflowAdapter(opts);\n }\n\n async init(_ctx: PluginContext): Promise<void> {\n // No-op: actual registration happens in start() once service is available.\n }\n\n async start(ctx: PluginContext): Promise<void> {\n let svc: IKnowledgeService | undefined;\n try {\n svc = ctx.getService<IKnowledgeService>(KNOWLEDGE_SERVICE);\n } catch {\n ctx.logger.warn?.(\n 'KnowledgeRagflowPlugin: IKnowledgeService not registered — install KnowledgeServicePlugin first.',\n );\n return;\n }\n svc.registerAdapter(this.adapter.id, this.adapter);\n ctx.logger.info?.(\n `KnowledgeRagflowPlugin: adapter '${this.adapter.id}' registered (endpoint=${(this.adapter as unknown as { endpoint: string }).endpoint}).`,\n );\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { Plugin, PluginContext } from '@objectstack/core';\nimport type {\n IKnowledgeAdapter,\n IKnowledgeService,\n AdapterContext,\n AdapterSearchOptions,\n} from '@objectstack/spec/contracts';\nimport type {\n KnowledgeDocument,\n KnowledgeHit,\n KnowledgeSource,\n} from '@objectstack/spec/ai';\nimport { KNOWLEDGE_SERVICE } from '@objectstack/spec/contracts';\n\n/**\n * Subset of `fetch` used by the adapter. Inject in tests; defaults to\n * the global `fetch`.\n */\nexport type FetchLike = (\n input: string,\n init?: {\n method?: string;\n headers?: Record<string, string>;\n body?: string;\n signal?: AbortSignal;\n },\n) => Promise<{\n ok: boolean;\n status: number;\n statusText: string;\n text(): Promise<string>;\n json(): Promise<unknown>;\n}>;\n\nexport interface KnowledgeRagflowAdapterOptions {\n /** RAGFlow endpoint, e.g. `http://localhost:9380`. */\n endpoint: string;\n /** RAGFlow API key (Bearer token). */\n apiKey: string;\n /** Adapter id. @default 'ragflow' */\n id?: string;\n /** Override `fetch` for tests. */\n fetch?: FetchLike;\n /** Request timeout in milliseconds. @default 30000 */\n timeoutMs?: number;\n}\n\ninterface RagflowSourceOptions {\n datasetId: string;\n /** Optional rerank model id (overrides dataset default). */\n rerankModel?: string;\n /** Optional similarity threshold passed through to RAGFlow. */\n similarityThreshold?: number;\n /** Optional vector vs keyword weight in [0,1]. */\n vectorSimilarityWeight?: number;\n}\n\nfunction extractRagflowOptions(source: KnowledgeSource): RagflowSourceOptions {\n const opts = ((source as unknown as { options?: Record<string, unknown> }).options ?? {}) as\n Record<string, unknown>;\n const datasetId = opts.datasetId;\n if (typeof datasetId !== 'string' || !datasetId) {\n throw new Error(\n `RAGFlow adapter requires source.options.datasetId on source '${source.id}'`,\n );\n }\n return {\n datasetId,\n rerankModel: typeof opts.rerankModel === 'string' ? opts.rerankModel : undefined,\n similarityThreshold:\n typeof opts.similarityThreshold === 'number' ? opts.similarityThreshold : undefined,\n vectorSimilarityWeight:\n typeof opts.vectorSimilarityWeight === 'number'\n ? opts.vectorSimilarityWeight\n : undefined,\n };\n}\n\n/**\n * RAGFlow adapter. Maps {@link KnowledgeDocument} upserts to the\n * dataset's chunk API, delegates retrieval to `/api/v1/retrieval`, and\n * returns {@link KnowledgeHit}s with `sourceRecordId` preserved so the\n * orchestrator can run a permission re-check.\n */\nexport class KnowledgeRagflowAdapter implements IKnowledgeAdapter {\n readonly id: string;\n private readonly endpoint: string;\n private readonly apiKey: string;\n private readonly fetchImpl: FetchLike;\n private readonly timeoutMs: number;\n\n constructor(opts: KnowledgeRagflowAdapterOptions) {\n if (!opts.endpoint) throw new Error('RAGFlow adapter: endpoint required');\n if (!opts.apiKey) throw new Error('RAGFlow adapter: apiKey required');\n this.id = opts.id ?? 'ragflow';\n this.endpoint = opts.endpoint.replace(/\\/+$/, '');\n this.apiKey = opts.apiKey;\n this.fetchImpl = opts.fetch ?? ((globalThis as { fetch?: FetchLike }).fetch as FetchLike);\n this.timeoutMs = opts.timeoutMs ?? 30000;\n if (!this.fetchImpl) {\n throw new Error('RAGFlow adapter: no fetch available; pass options.fetch');\n }\n }\n\n async upsert(docs: KnowledgeDocument[], ctx: AdapterContext): Promise<void> {\n const { datasetId } = extractRagflowOptions(ctx.source);\n // RAGFlow models documents in two layers: documents (file-like) and\n // chunks (text blocks). We treat each KnowledgeDocument as a single\n // chunk-set: delete existing chunks with the same external id, then\n // upload as `content` chunks tagged with our document id.\n for (const doc of docs) {\n await this.deleteChunksByDocumentId(datasetId, doc.id);\n await this.request(`/api/v1/datasets/${datasetId}/chunks`, {\n method: 'POST',\n body: JSON.stringify({\n content: doc.content,\n // RAGFlow accepts arbitrary metadata used for filtering at\n // retrieval time. We always stamp `objectstack_doc_id` so\n // delete() can find these chunks again.\n important_keywords: doc.title ? [doc.title] : undefined,\n metadata: {\n ...(doc.metadata ?? {}),\n objectstack_doc_id: doc.id,\n objectstack_source_id: doc.sourceId,\n objectstack_record_id: doc.sourceRecordId,\n title: doc.title,\n },\n }),\n });\n }\n }\n\n async delete(documentIds: string[], ctx: AdapterContext): Promise<void> {\n const { datasetId } = extractRagflowOptions(ctx.source);\n for (const id of documentIds) {\n await this.deleteChunksByDocumentId(datasetId, id);\n }\n }\n\n async search(query: string, opts: AdapterSearchOptions): Promise<KnowledgeHit[]> {\n const { datasetId, rerankModel, similarityThreshold, vectorSimilarityWeight } =\n extractRagflowOptions(opts.source);\n const body: Record<string, unknown> = {\n question: query,\n dataset_ids: [datasetId],\n top_k: opts.topK,\n keyword: true,\n };\n if (rerankModel) body.rerank_id = rerankModel;\n if (typeof similarityThreshold === 'number') body.similarity_threshold = similarityThreshold;\n if (typeof vectorSimilarityWeight === 'number')\n body.vector_similarity_weight = vectorSimilarityWeight;\n if (opts.filter) body.metadata_condition = { ...opts.filter };\n\n const res = await this.request('/api/v1/retrieval', {\n method: 'POST',\n body: JSON.stringify(body),\n });\n const data = (res?.data ?? {}) as { chunks?: RagflowChunkHit[] };\n const chunks = data.chunks ?? [];\n return chunks.slice(0, opts.topK).map<KnowledgeHit>((c) => {\n const md = (c.metadata ?? {}) as Record<string, unknown>;\n const docId =\n (md.objectstack_doc_id as string | undefined) ??\n c.document_id ??\n c.doc_id ??\n c.id;\n const recordId = md.objectstack_record_id as string | undefined;\n return {\n chunkId: c.id ?? `${docId}#${c.position ?? 0}`,\n documentId: docId ?? c.id ?? 'unknown',\n sourceId: opts.source.id,\n sourceRecordId: recordId,\n score: c.similarity ?? c.score ?? 0,\n snippet: c.content ?? c.content_with_weight ?? '',\n title: (md.title as string | undefined) ?? c.document_name,\n metadata: md,\n };\n });\n }\n\n async healthCheck(): Promise<{ ok: boolean; message?: string }> {\n try {\n await this.request('/api/v1/datasets?page=1&page_size=1', { method: 'GET' });\n return { ok: true };\n } catch (err) {\n return { ok: false, message: err instanceof Error ? err.message : String(err) };\n }\n }\n\n private async deleteChunksByDocumentId(datasetId: string, docId: string): Promise<void> {\n // Find chunks with our stamped metadata, then delete by chunk id.\n const found = (await this.request(`/api/v1/retrieval`, {\n method: 'POST',\n body: JSON.stringify({\n question: docId,\n dataset_ids: [datasetId],\n top_k: 256,\n keyword: false,\n metadata_condition: { objectstack_doc_id: docId },\n }),\n })) as { data?: { chunks?: Array<{ id?: string }> } };\n const ids = (found.data?.chunks ?? [])\n .map((c) => c.id)\n .filter((x): x is string => typeof x === 'string');\n if (ids.length === 0) return;\n await this.request(`/api/v1/datasets/${datasetId}/chunks`, {\n method: 'DELETE',\n body: JSON.stringify({ chunk_ids: ids }),\n });\n }\n\n private async request(\n path: string,\n init: { method: string; body?: string },\n ): Promise<{ data?: unknown; code?: number; message?: string }> {\n const controller = new AbortController();\n const t = setTimeout(() => controller.abort(), this.timeoutMs);\n try {\n const res = await this.fetchImpl(`${this.endpoint}${path}`, {\n method: init.method,\n headers: {\n 'content-type': 'application/json',\n authorization: `Bearer ${this.apiKey}`,\n },\n body: init.body,\n signal: controller.signal,\n });\n const raw = await res.text();\n let parsed: { data?: unknown; code?: number; message?: string } = {};\n if (raw) {\n try {\n parsed = JSON.parse(raw) as typeof parsed;\n } catch {\n if (!res.ok) {\n throw new Error(\n `RAGFlow ${init.method} ${path} → ${res.status} ${res.statusText}: ${raw.slice(0, 200)}`,\n );\n }\n }\n }\n if (!res.ok || (typeof parsed.code === 'number' && parsed.code !== 0 && parsed.code !== 200)) {\n throw new Error(\n `RAGFlow ${init.method} ${path} → ${res.status} ${res.statusText}${\n parsed.message ? ` (${parsed.message})` : ''\n }`,\n );\n }\n return parsed;\n } finally {\n clearTimeout(t);\n }\n }\n}\n\ninterface RagflowChunkHit {\n id?: string;\n document_id?: string;\n doc_id?: string;\n document_name?: string;\n content?: string;\n content_with_weight?: string;\n similarity?: number;\n score?: number;\n position?: number;\n metadata?: Record<string, unknown>;\n}\n\n/* ---------------------------------------------------------------- */\n/* Kernel plugin glue */\n/* ---------------------------------------------------------------- */\n\nexport interface KnowledgeRagflowPluginOptions extends KnowledgeRagflowAdapterOptions {}\n\nexport class KnowledgeRagflowPlugin implements Plugin {\n name = 'com.objectstack.plugin.knowledge-ragflow';\n version = '0.1.0';\n type = 'standard' as const;\n\n private readonly adapter: KnowledgeRagflowAdapter;\n\n constructor(opts: KnowledgeRagflowPluginOptions) {\n this.adapter = new KnowledgeRagflowAdapter(opts);\n }\n\n async init(_ctx: PluginContext): Promise<void> {\n // No-op: actual registration happens in start() once service is available.\n }\n\n async start(ctx: PluginContext): Promise<void> {\n let svc: IKnowledgeService | undefined;\n try {\n svc = ctx.getService<IKnowledgeService>(KNOWLEDGE_SERVICE);\n } catch {\n ctx.logger.warn?.(\n 'KnowledgeRagflowPlugin: IKnowledgeService not registered — install KnowledgeServicePlugin first.',\n );\n return;\n }\n svc.registerAdapter(this.adapter.id, this.adapter);\n ctx.logger.info?.(\n `KnowledgeRagflowPlugin: adapter '${this.adapter.id}' registered (endpoint=${(this.adapter as unknown as { endpoint: string }).endpoint}).`,\n );\n }\n}\n"],"mappings":";AAcA,SAAS,yBAAyB;AA6ClC,SAAS,sBAAsB,QAA+C;AAC5E,QAAM,OAAS,OAA4D,WAAW,CAAC;AAEvF,QAAM,YAAY,KAAK;AACvB,MAAI,OAAO,cAAc,YAAY,CAAC,WAAW;AAC/C,UAAM,IAAI;AAAA,MACR,gEAAgE,OAAO,EAAE;AAAA,IAC3E;AAAA,EACF;AACA,SAAO;AAAA,IACL;AAAA,IACA,aAAa,OAAO,KAAK,gBAAgB,WAAW,KAAK,cAAc;AAAA,IACvE,qBACE,OAAO,KAAK,wBAAwB,WAAW,KAAK,sBAAsB;AAAA,IAC5E,wBACE,OAAO,KAAK,2BAA2B,WACnC,KAAK,yBACL;AAAA,EACR;AACF;AAQO,IAAM,0BAAN,MAA2D;AAAA,EAOhE,YAAY,MAAsC;AAChD,QAAI,CAAC,KAAK,SAAU,OAAM,IAAI,MAAM,oCAAoC;AACxE,QAAI,CAAC,KAAK,OAAQ,OAAM,IAAI,MAAM,kCAAkC;AACpE,SAAK,KAAK,KAAK,MAAM;AACrB,SAAK,WAAW,KAAK,SAAS,QAAQ,QAAQ,EAAE;AAChD,SAAK,SAAS,KAAK;AACnB,SAAK,YAAY,KAAK,SAAW,WAAqC;AACtE,SAAK,YAAY,KAAK,aAAa;AACnC,QAAI,CAAC,KAAK,WAAW;AACnB,YAAM,IAAI,MAAM,yDAAyD;AAAA,IAC3E;AAAA,EACF;AAAA,EAEA,MAAM,OAAO,MAA2B,KAAoC;AAC1E,UAAM,EAAE,UAAU,IAAI,sBAAsB,IAAI,MAAM;AAKtD,eAAW,OAAO,MAAM;AACtB,YAAM,KAAK,yBAAyB,WAAW,IAAI,EAAE;AACrD,YAAM,KAAK,QAAQ,oBAAoB,SAAS,WAAW;AAAA,QACzD,QAAQ;AAAA,QACR,MAAM,KAAK,UAAU;AAAA,UACnB,SAAS,IAAI;AAAA;AAAA;AAAA;AAAA,UAIb,oBAAoB,IAAI,QAAQ,CAAC,IAAI,KAAK,IAAI;AAAA,UAC9C,UAAU;AAAA,YACR,GAAI,IAAI,YAAY,CAAC;AAAA,YACrB,oBAAoB,IAAI;AAAA,YACxB,uBAAuB,IAAI;AAAA,YAC3B,uBAAuB,IAAI;AAAA,YAC3B,OAAO,IAAI;AAAA,UACb;AAAA,QACF,CAAC;AAAA,MACH,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEA,MAAM,OAAO,aAAuB,KAAoC;AACtE,UAAM,EAAE,UAAU,IAAI,sBAAsB,IAAI,MAAM;AACtD,eAAW,MAAM,aAAa;AAC5B,YAAM,KAAK,yBAAyB,WAAW,EAAE;AAAA,IACnD;AAAA,EACF;AAAA,EAEA,MAAM,OAAO,OAAe,MAAqD;AAC/E,UAAM,EAAE,WAAW,aAAa,qBAAqB,uBAAuB,IAC1E,sBAAsB,KAAK,MAAM;AACnC,UAAM,OAAgC;AAAA,MACpC,UAAU;AAAA,MACV,aAAa,CAAC,SAAS;AAAA,MACvB,OAAO,KAAK;AAAA,MACZ,SAAS;AAAA,IACX;AACA,QAAI,YAAa,MAAK,YAAY;AAClC,QAAI,OAAO,wBAAwB,SAAU,MAAK,uBAAuB;AACzE,QAAI,OAAO,2BAA2B;AACpC,WAAK,2BAA2B;AAClC,QAAI,KAAK,OAAQ,MAAK,qBAAqB,EAAE,GAAG,KAAK,OAAO;AAE5D,UAAM,MAAM,MAAM,KAAK,QAAQ,qBAAqB;AAAA,MAClD,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU,IAAI;AAAA,IAC3B,CAAC;AACD,UAAM,OAAQ,KAAK,QAAQ,CAAC;AAC5B,UAAM,SAAS,KAAK,UAAU,CAAC;AAC/B,WAAO,OAAO,MAAM,GAAG,KAAK,IAAI,EAAE,IAAkB,CAAC,MAAM;AACzD,YAAM,KAAM,EAAE,YAAY,CAAC;AAC3B,YAAM,QACH,GAAG,sBACJ,EAAE,eACF,EAAE,UACF,EAAE;AACJ,YAAM,WAAW,GAAG;AACpB,aAAO;AAAA,QACL,SAAS,EAAE,MAAM,GAAG,KAAK,IAAI,EAAE,YAAY,CAAC;AAAA,QAC5C,YAAY,SAAS,EAAE,MAAM;AAAA,QAC7B,UAAU,KAAK,OAAO;AAAA,QACtB,gBAAgB;AAAA,QAChB,OAAO,EAAE,cAAc,EAAE,SAAS;AAAA,QAClC,SAAS,EAAE,WAAW,EAAE,uBAAuB;AAAA,QAC/C,OAAQ,GAAG,SAAgC,EAAE;AAAA,QAC7C,UAAU;AAAA,MACZ;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,cAA0D;AAC9D,QAAI;AACF,YAAM,KAAK,QAAQ,uCAAuC,EAAE,QAAQ,MAAM,CAAC;AAC3E,aAAO,EAAE,IAAI,KAAK;AAAA,IACpB,SAAS,KAAK;AACZ,aAAO,EAAE,IAAI,OAAO,SAAS,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,EAAE;AAAA,IAChF;AAAA,EACF;AAAA,EAEA,MAAc,yBAAyB,WAAmB,OAA8B;AAEtF,UAAM,QAAS,MAAM,KAAK,QAAQ,qBAAqB;AAAA,MACrD,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU;AAAA,QACnB,UAAU;AAAA,QACV,aAAa,CAAC,SAAS;AAAA,QACvB,OAAO;AAAA,QACP,SAAS;AAAA,QACT,oBAAoB,EAAE,oBAAoB,MAAM;AAAA,MAClD,CAAC;AAAA,IACH,CAAC;AACD,UAAM,OAAO,MAAM,MAAM,UAAU,CAAC,GACjC,IAAI,CAAC,MAAM,EAAE,EAAE,EACf,OAAO,CAAC,MAAmB,OAAO,MAAM,QAAQ;AACnD,QAAI,IAAI,WAAW,EAAG;AACtB,UAAM,KAAK,QAAQ,oBAAoB,SAAS,WAAW;AAAA,MACzD,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU,EAAE,WAAW,IAAI,CAAC;AAAA,IACzC,CAAC;AAAA,EACH;AAAA,EAEA,MAAc,QACZ,MACA,MAC8D;AAC9D,UAAM,aAAa,IAAI,gBAAgB;AACvC,UAAM,IAAI,WAAW,MAAM,WAAW,MAAM,GAAG,KAAK,SAAS;AAC7D,QAAI;AACF,YAAM,MAAM,MAAM,KAAK,UAAU,GAAG,KAAK,QAAQ,GAAG,IAAI,IAAI;AAAA,QAC1D,QAAQ,KAAK;AAAA,QACb,SAAS;AAAA,UACP,gBAAgB;AAAA,UAChB,eAAe,UAAU,KAAK,MAAM;AAAA,QACtC;AAAA,QACA,MAAM,KAAK;AAAA,QACX,QAAQ,WAAW;AAAA,MACrB,CAAC;AACD,YAAM,MAAM,MAAM,IAAI,KAAK;AAC3B,UAAI,SAA8D,CAAC;AACnE,UAAI,KAAK;AACP,YAAI;AACF,mBAAS,KAAK,MAAM,GAAG;AAAA,QACzB,QAAQ;AACN,cAAI,CAAC,IAAI,IAAI;AACX,kBAAM,IAAI;AAAA,cACR,WAAW,KAAK,MAAM,IAAI,IAAI,WAAM,IAAI,MAAM,IAAI,IAAI,UAAU,KAAK,IAAI,MAAM,GAAG,GAAG,CAAC;AAAA,YACxF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AACA,UAAI,CAAC,IAAI,MAAO,OAAO,OAAO,SAAS,YAAY,OAAO,SAAS,KAAK,OAAO,SAAS,KAAM;AAC5F,cAAM,IAAI;AAAA,UACR,WAAW,KAAK,MAAM,IAAI,IAAI,WAAM,IAAI,MAAM,IAAI,IAAI,UAAU,GAC9D,OAAO,UAAU,KAAK,OAAO,OAAO,MAAM,EAC5C;AAAA,QACF;AAAA,MACF;AACA,aAAO;AAAA,IACT,UAAE;AACA,mBAAa,CAAC;AAAA,IAChB;AAAA,EACF;AACF;AAqBO,IAAM,yBAAN,MAA+C;AAAA,EAOpD,YAAY,MAAqC;AANjD,gBAAO;AACP,mBAAU;AACV,gBAAO;AAKL,SAAK,UAAU,IAAI,wBAAwB,IAAI;AAAA,EACjD;AAAA,EAEA,MAAM,KAAK,MAAoC;AAAA,EAE/C;AAAA,EAEA,MAAM,MAAM,KAAmC;AAC7C,QAAI;AACJ,QAAI;AACF,YAAM,IAAI,WAA8B,iBAAiB;AAAA,IAC3D,QAAQ;AACN,UAAI,OAAO;AAAA,QACT;AAAA,MACF;AACA;AAAA,IACF;AACA,QAAI,gBAAgB,KAAK,QAAQ,IAAI,KAAK,OAAO;AACjD,QAAI,OAAO;AAAA,MACT,oCAAoC,KAAK,QAAQ,EAAE,0BAA2B,KAAK,QAA4C,QAAQ;AAAA,IACzI;AAAA,EACF;AACF;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@objectstack/knowledge-ragflow",
3
- "version": "17.1.0",
3
+ "version": "17.3.0",
4
4
  "license": "Apache-2.0",
5
5
  "description": "RAGFlow knowledge adapter for ObjectStack — production-grade RAG via the Apache 2.0 RAGFlow REST API.",
6
6
  "main": "dist/index.js",
@@ -13,12 +13,13 @@
13
13
  }
14
14
  },
15
15
  "dependencies": {
16
- "@objectstack/core": "17.1.0",
17
- "@objectstack/service-knowledge": "17.1.0",
18
- "@objectstack/spec": "17.1.0"
16
+ "@objectstack/core": "17.3.0",
17
+ "@objectstack/service-knowledge": "17.3.0",
18
+ "@objectstack/spec": "17.3.0"
19
19
  },
20
20
  "devDependencies": {
21
21
  "@types/node": "^26.2.0",
22
+ "tsx": "^4.23.12",
22
23
  "typescript": "^6.0.3",
23
24
  "vitest": "^4.1.10"
24
25
  },
@@ -34,8 +35,11 @@
34
35
  "CHANGELOG.md"
35
36
  ],
36
37
  "scripts": {
37
- "build": "tsup --config ../../../tsup.config.ts",
38
+ "build": "tsup --config ../../../tsup.config.ts && node ../../../scripts/check-dts-emitted.mjs",
38
39
  "dev": "tsc -w",
39
- "test": "vitest run"
40
+ "test": "vitest run",
41
+ "typecheck": "tsc --noEmit && pnpm check:test-typecheck",
42
+ "check:test-typecheck": "tsx ../../../scripts/check-test-typecheck.mts --self-test && tsx ../../../scripts/check-test-typecheck.mts --package packages/plugins/knowledge-ragflow --project tsconfig.test.json",
43
+ "gen:test-typecheck-debt": "tsx ../../../scripts/check-test-typecheck.mts --update --package packages/plugins/knowledge-ragflow --project tsconfig.test.json"
40
44
  }
41
45
  }