ragpack-js 0.1.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/README.md ADDED
@@ -0,0 +1,128 @@
1
+ # RagPack
2
+
3
+ TypeScript SDK for [RagPack](https://github.com/eozsahin1993/ragpack) — a self-hosted semantic search and RAG engine.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install ragpack
9
+ ```
10
+
11
+ ## Quick start
12
+
13
+ ```ts
14
+ import { RagPack } from "ragpack";
15
+
16
+ const client = new RagPack({
17
+ baseUrl: "http://localhost:9000",
18
+ apiKey: "rp_...",
19
+ });
20
+
21
+ // Create a collection
22
+ const collection = await client.collections.create("my-docs");
23
+
24
+ // Ingest a file
25
+ await collection.ingest(file);
26
+
27
+ // Or ingest from a remote URI
28
+ await collection.ingest({ uri: "s3://my-bucket/report.pdf" });
29
+
30
+ // Wait for ingestion to finish
31
+ const job = await collection.ingest(file);
32
+ await collection.jobs.waitUntilComplete(job.id);
33
+
34
+ // RAG — retrieve relevant chunks and get an LLM answer
35
+ const { answer, chunks } = await collection.rag({ query: "how does auth work?" });
36
+ console.log(answer);
37
+
38
+ // Semantic search (without LLM)
39
+ const results = await collection.findSimilar({ query: "how does auth work?", topK: 5 });
40
+ for (const r of results) {
41
+ console.log(r.similarity, r.chunk_text);
42
+ }
43
+ ```
44
+
45
+ ## API
46
+
47
+ ### `new RagPack({ baseUrl, apiKey })`
48
+
49
+ | Option | Description |
50
+ |-----------|------------------------------------------------------|
51
+ | `baseUrl` | URL of your RagPack backend (e.g. `http://localhost:9000`) |
52
+ | `apiKey` | API key printed by the backend on first startup |
53
+
54
+ ### `client.collections`
55
+
56
+ | Method | Description |
57
+ |-------------------------------------|------------------------------------------|
58
+ | `list()` | List all collections |
59
+ | `create(name, options?)` | Create a collection, returns a scoped client |
60
+ | `get(slug)` | Get collection metadata by slug |
61
+ | `delete(slug)` | Delete a collection and all its documents |
62
+
63
+ ### `client.collection(slug)`
64
+
65
+ Returns a `CollectionClient` scoped to that collection.
66
+
67
+ | Method | Description |
68
+ |-------------------------------------|------------------------------------------|
69
+ | `ingest(file, filename?)` | Upload a file directly |
70
+ | `ingest({ uri, mimeType? })` | Ingest from a remote URI, MIME type auto-detected if omitted |
71
+ | `rag(options)` | Full RAG pipeline — retrieves chunks and returns an LLM answer |
72
+ | `findSimilar({ query, topK? })` | Semantic search without LLM, returns ranked chunks |
73
+ | `jobs.list()` | List ingestion jobs for this collection |
74
+ | `jobs.get(id)` | Get a single job by ID |
75
+ | `jobs.waitUntilComplete(id)` | Poll until job is `complete` or `failed` |
76
+ | `documents.list(options?)` | List indexed documents |
77
+ | `documents.delete(id)` | Delete a document and its chunks |
78
+
79
+ #### `rag(options)`
80
+
81
+ Runs the full RAG pipeline server-side: embeds the query, retrieves the top-K chunks, fills the prompt template, and calls the configured LLM.
82
+
83
+ ```ts
84
+ const { answer, chunks } = await collection.rag({
85
+ query: "How do I reset my password?",
86
+ // All options below are optional
87
+ promptSlug: "basic_rag", // defaults to "basic_rag" if omitted
88
+ topK: 5, // number of chunks to retrieve (default: 5)
89
+ model: "gpt-4o", // LLM model; falls back to server default
90
+ minSimilarity: 70, // drop chunks below this similarity score (0–100)
91
+ });
92
+
93
+ console.log(answer);
94
+
95
+ for (const chunk of chunks) {
96
+ console.log(chunk.similarity, chunk.chunk_text);
97
+ }
98
+ ```
99
+
100
+ #### Prompt templates
101
+
102
+ Three built-in prompts are always available: `basic_rag`, `rag_with_citations`, and `concise_rag`. List all available prompts (including any you've created in the admin UI) with:
103
+
104
+ ```ts
105
+ const prompts = await client.prompts.list();
106
+ // [{ slug: "basic_rag", name: "Basic RAG", is_system: true, ... }, ...]
107
+ ```
108
+
109
+ ## Error handling
110
+
111
+ All methods throw `RagPackError` on non-2xx responses:
112
+
113
+ ```ts
114
+ import { RagPack, RagPackError } from "ragpack";
115
+
116
+ try {
117
+ await collection.findSimilar({ query: "..." });
118
+ } catch (err) {
119
+ if (err instanceof RagPackError) {
120
+ console.error(err.status, err.message);
121
+ }
122
+ }
123
+ ```
124
+
125
+ ## Requirements
126
+
127
+ - Node.js 18+
128
+ - A running RagPack backend ([setup guide](https://github.com/eozsahin1993/ragpack))
package/dist/index.cjs ADDED
@@ -0,0 +1,330 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ RagPack: () => RagPack,
24
+ RagPackError: () => RagPackError
25
+ });
26
+ module.exports = __toCommonJS(index_exports);
27
+
28
+ // src/requester.ts
29
+ function createRequester(config) {
30
+ return async function req(path, init) {
31
+ const isFormData = init?.body instanceof FormData;
32
+ const res = await fetch(`${config.baseUrl}/api/v1${path}`, {
33
+ ...init,
34
+ headers: {
35
+ ...!isFormData && { "Content-Type": "application/json" },
36
+ Authorization: `Bearer ${config.apiKey}`,
37
+ ...init?.headers
38
+ }
39
+ });
40
+ if (res.status === 204) return void 0;
41
+ const body = await res.json();
42
+ if (!res.ok) throw new RagPackError(res.status, body.error ?? res.statusText);
43
+ return body;
44
+ };
45
+ }
46
+ var RagPackError = class extends Error {
47
+ constructor(status, message) {
48
+ super(message);
49
+ this.status = status;
50
+ this.name = "RagPackError";
51
+ }
52
+ };
53
+
54
+ // src/resources/jobs.ts
55
+ var JobsResource = class {
56
+ constructor(req, slug) {
57
+ this.req = req;
58
+ this.slug = slug;
59
+ }
60
+ /** List ingestion jobs for this collection, or all jobs if no collection is scoped. */
61
+ async list() {
62
+ const path = this.slug ? `/collections/${this.slug}/jobs` : "/jobs";
63
+ const r = await this.req(path);
64
+ return r.jobs;
65
+ }
66
+ /**
67
+ * Get a single ingestion job by ID.
68
+ * @param id - The job ID.
69
+ */
70
+ async get(id) {
71
+ const r = await this.req(`/collections/${this.slug}/jobs/${id}`);
72
+ return r.job;
73
+ }
74
+ /**
75
+ * Poll until the job reaches a terminal state (`complete` or `failed`).
76
+ * Throws {@link RagPackError} if the job fails or the timeout is exceeded.
77
+ *
78
+ * @example
79
+ * ```ts
80
+ * const job = await collection.ingest(file);
81
+ * await collection.jobs.waitUntilComplete(job.id);
82
+ * console.log("ingestion done, ready to search");
83
+ * ```
84
+ */
85
+ async waitUntilComplete(id, options = {}) {
86
+ const { pollIntervalMs = 1500, timeoutMs = 3e5 } = options;
87
+ const deadline = Date.now() + timeoutMs;
88
+ while (Date.now() < deadline) {
89
+ const job = await this.get(id);
90
+ if (job.status === "complete") return job;
91
+ if (job.status === "failed") {
92
+ throw new RagPackError(422, job.error ?? "ingestion job failed");
93
+ }
94
+ await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
95
+ }
96
+ throw new RagPackError(408, `job ${id} did not complete within ${timeoutMs}ms`);
97
+ }
98
+ };
99
+
100
+ // src/resources/documents.ts
101
+ var DocumentsResource = class {
102
+ constructor(req, slug) {
103
+ this.req = req;
104
+ this.slug = slug;
105
+ }
106
+ /**
107
+ * List documents in this collection.
108
+ * @param options.limit - Max number of documents to return. Defaults to 50.
109
+ * @param options.offset - Pagination offset. Defaults to 0.
110
+ */
111
+ async list(options) {
112
+ const params = new URLSearchParams({
113
+ limit: String(options?.limit ?? 50),
114
+ offset: String(options?.offset ?? 0)
115
+ });
116
+ const r = await this.req(
117
+ `/collections/${this.slug}/documents?${params}`
118
+ );
119
+ return r.documents;
120
+ }
121
+ /**
122
+ * Delete a document and all its chunks from this collection.
123
+ * @param id - The document ID.
124
+ */
125
+ delete(id) {
126
+ return this.req(`/collections/${this.slug}/documents/${id}`, {
127
+ method: "DELETE"
128
+ });
129
+ }
130
+ };
131
+
132
+ // src/resources/query.ts
133
+ var QueryResource = class {
134
+ constructor(req, slug) {
135
+ this.req = req;
136
+ this.slug = slug;
137
+ }
138
+ /**
139
+ * Find semantically similar content within this collection.
140
+ * @returns Ranked results with similarity scores and source chunks.
141
+ */
142
+ async findSimilar(options) {
143
+ const r = await this.req(
144
+ `/collections/${this.slug}/query`,
145
+ {
146
+ method: "POST",
147
+ body: JSON.stringify({ query: options.query, top_k: options.topK ?? 5 })
148
+ }
149
+ );
150
+ return r.results;
151
+ }
152
+ };
153
+
154
+ // src/collection-client.ts
155
+ var CollectionClient = class {
156
+ constructor(slug, req) {
157
+ this.slug = slug;
158
+ this._req = req;
159
+ this.jobs = new JobsResource(req, slug);
160
+ this.documents = new DocumentsResource(req, slug);
161
+ this._query = new QueryResource(req, slug);
162
+ }
163
+ ingest(input, filename) {
164
+ if (input instanceof Blob) {
165
+ const form = new FormData();
166
+ form.append("file", input, filename);
167
+ return this._req(`/collections/${this.slug}/ingest`, {
168
+ method: "POST",
169
+ body: form
170
+ });
171
+ }
172
+ return this._req(`/collections/${this.slug}/ingest`, {
173
+ method: "POST",
174
+ body: JSON.stringify({ file_uri: input.uri, mime_type: input.mimeType })
175
+ });
176
+ }
177
+ /**
178
+ * Find semantically similar content in this collection.
179
+ * @example
180
+ * ```ts
181
+ * const results = await collection.findSimilar({ query: "what is RagPack?", topK: 10 });
182
+ * ```
183
+ */
184
+ findSimilar(options) {
185
+ return this._query.findSimilar(options);
186
+ }
187
+ /**
188
+ * Full RAG pipeline: retrieve relevant chunks, build context, expand the
189
+ * prompt template, and call the configured LLM — all server-side.
190
+ *
191
+ * @example
192
+ * ```ts
193
+ * const { answer, chunks } = await collection.rag({
194
+ * prompt: "basic-rag",
195
+ * query: "How do I reset my password?",
196
+ * });
197
+ * ```
198
+ */
199
+ rag(options) {
200
+ return this._req(`/collections/${this.slug}/rag`, {
201
+ method: "POST",
202
+ body: JSON.stringify({
203
+ query: options.query,
204
+ top_k: options.topK ?? 5,
205
+ ...options.promptSlug ? { prompt_slug: options.promptSlug } : {},
206
+ ...options.model ? { model: options.model } : {},
207
+ ...options.minSimilarity != null ? { min_similarity: options.minSimilarity } : {}
208
+ })
209
+ });
210
+ }
211
+ };
212
+
213
+ // src/resources/collections.ts
214
+ var CollectionsResource = class {
215
+ constructor(req) {
216
+ this.req = req;
217
+ }
218
+ /** List all collections. */
219
+ async list() {
220
+ const r = await this.req("/collections");
221
+ return r.collections;
222
+ }
223
+ /**
224
+ * Create a new collection and return a scoped client for it.
225
+ * @param name - Display name for the collection.
226
+ * @param options.embedModel - Embedding model to use. Defaults to the server's configured provider.
227
+ * @param options.chunkConfig - Override chunking behaviour for this collection.
228
+ * Omit to use server defaults.
229
+ *
230
+ * @example
231
+ * ```ts
232
+ * const collection = await client.collections.create("my-docs");
233
+ * await collection.ingest(file);
234
+ * ```
235
+ */
236
+ async create(name, options) {
237
+ const col = await this.req("/collections", {
238
+ method: "POST",
239
+ body: JSON.stringify({
240
+ name,
241
+ embed_model: options?.embedModel,
242
+ chunk_config: options?.chunkConfig
243
+ })
244
+ });
245
+ return new CollectionClient(col.slug, this.req);
246
+ }
247
+ /**
248
+ * Get a collection by its slug.
249
+ * @param slug - The collection's URL-safe identifier.
250
+ */
251
+ get(slug) {
252
+ return this.req(`/collections/${slug}`);
253
+ }
254
+ /**
255
+ * Delete a collection and all its documents.
256
+ * @param slug - The collection's URL-safe identifier.
257
+ */
258
+ delete(slug) {
259
+ return this.req(`/collections/${slug}`, { method: "DELETE" });
260
+ }
261
+ };
262
+
263
+ // src/resources/prompts.ts
264
+ var PromptsResource = class {
265
+ constructor(req) {
266
+ this.req = req;
267
+ }
268
+ /** List all prompt templates (built-in system prompts first, then custom). */
269
+ async list() {
270
+ const r = await this.req("/prompts");
271
+ return [...r.system ?? [], ...r.user ?? []];
272
+ }
273
+ /** Fetch a prompt template by slug. */
274
+ get(slug) {
275
+ return this.req(`/prompts/${slug}`);
276
+ }
277
+ };
278
+
279
+ // src/resources/llms.ts
280
+ var LLMsResource = class {
281
+ constructor(req) {
282
+ this.req = req;
283
+ }
284
+ /** List all configured LLM models and the server default. */
285
+ list() {
286
+ return this.req("/llms");
287
+ }
288
+ };
289
+
290
+ // src/resources/embedders.ts
291
+ var EmbeddersResource = class {
292
+ constructor(req) {
293
+ this.req = req;
294
+ }
295
+ /** List all configured embedding models and the server default. */
296
+ list() {
297
+ return this.req("/embedders");
298
+ }
299
+ };
300
+
301
+ // src/index.ts
302
+ var RagPack = class {
303
+ constructor(config) {
304
+ this._req = createRequester(config);
305
+ this.collections = new CollectionsResource(this._req);
306
+ this.prompts = new PromptsResource(this._req);
307
+ this.llms = new LLMsResource(this._req);
308
+ this.embedders = new EmbeddersResource(this._req);
309
+ }
310
+ /**
311
+ * Scope all operations to a specific collection.
312
+ * @param slug - The collection's URL-safe identifier.
313
+ *
314
+ * @example
315
+ * ```ts
316
+ * const collection = client.collection("my-docs");
317
+ * await collection.ingest(file);
318
+ * await collection.findSimilar({ query: "..." });
319
+ * await collection.jobs.list();
320
+ * ```
321
+ */
322
+ collection(slug) {
323
+ return new CollectionClient(slug, this._req);
324
+ }
325
+ };
326
+ // Annotate the CommonJS export names for ESM import in node:
327
+ 0 && (module.exports = {
328
+ RagPack,
329
+ RagPackError
330
+ });