@ragable/sdk 0.0.3 → 0.4.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/dist/index.js CHANGED
@@ -23,14 +23,30 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
23
23
  var index_exports = {};
24
24
  __export(index_exports, {
25
25
  AgentsClient: () => AgentsClient,
26
+ PostgrestDeleteBuilder: () => PostgrestDeleteBuilder,
27
+ PostgrestInsertBuilder: () => PostgrestInsertBuilder,
28
+ PostgrestSelectBuilder: () => PostgrestSelectBuilder,
29
+ PostgrestTableApi: () => PostgrestTableApi,
30
+ PostgrestUpdateBuilder: () => PostgrestUpdateBuilder,
26
31
  Ragable: () => Ragable,
32
+ RagableBrowser: () => RagableBrowser,
33
+ RagableBrowserAgentsClient: () => RagableBrowserAgentsClient,
34
+ RagableBrowserAuthClient: () => RagableBrowserAuthClient,
35
+ RagableBrowserDatabaseClient: () => RagableBrowserDatabaseClient,
27
36
  RagableError: () => RagableError,
28
37
  RagableRequestClient: () => RagableRequestClient,
29
38
  ShiftClient: () => ShiftClient,
39
+ asPostgrestResponse: () => asPostgrestResponse,
40
+ createBrowserClient: () => createBrowserClient,
30
41
  createClient: () => createClient,
31
42
  createRagPipeline: () => createRagPipeline,
43
+ createRagableBrowserClient: () => createRagableBrowserClient,
44
+ createRagableServerClient: () => createRagableServerClient,
32
45
  extractErrorMessage: () => extractErrorMessage,
33
- formatRetrievalContext: () => formatRetrievalContext
46
+ formatRetrievalContext: () => formatRetrievalContext,
47
+ normalizeBrowserApiBase: () => normalizeBrowserApiBase,
48
+ parseSseDataLine: () => parseSseDataLine,
49
+ readSseStream: () => readSseStream
34
50
  });
35
51
  module.exports = __toCommonJS(index_exports);
36
52
 
@@ -255,6 +271,74 @@ function toArrayBuffer(value) {
255
271
  return copy.buffer;
256
272
  }
257
273
 
274
+ // src/sse.ts
275
+ async function parseMaybeJsonBody(response) {
276
+ const contentType = response.headers.get("content-type") ?? "";
277
+ if (contentType.includes("application/json")) {
278
+ try {
279
+ return await response.json();
280
+ } catch {
281
+ return null;
282
+ }
283
+ }
284
+ try {
285
+ return await response.text();
286
+ } catch {
287
+ return null;
288
+ }
289
+ }
290
+ function parseSseDataLine(line) {
291
+ const dataPrefix = "data: ";
292
+ if (!line.startsWith(dataPrefix)) {
293
+ return null;
294
+ }
295
+ const json = line.slice(dataPrefix.length).trim();
296
+ if (json.length === 0 || json === "[DONE]") {
297
+ return null;
298
+ }
299
+ try {
300
+ return JSON.parse(json);
301
+ } catch {
302
+ return null;
303
+ }
304
+ }
305
+ async function* readSseStream(body) {
306
+ const reader = body.getReader();
307
+ const decoder = new TextDecoder();
308
+ let buffer = "";
309
+ try {
310
+ while (true) {
311
+ const { done, value } = await reader.read();
312
+ if (done) {
313
+ break;
314
+ }
315
+ buffer += decoder.decode(value, { stream: true });
316
+ let boundary = buffer.indexOf("\n\n");
317
+ while (boundary !== -1) {
318
+ const block = buffer.slice(0, boundary);
319
+ buffer = buffer.slice(boundary + 2);
320
+ for (const line of block.split("\n")) {
321
+ const evt = parseSseDataLine(line);
322
+ if (evt) {
323
+ yield evt;
324
+ }
325
+ }
326
+ boundary = buffer.indexOf("\n\n");
327
+ }
328
+ }
329
+ if (buffer.trim().length > 0) {
330
+ for (const line of buffer.split("\n")) {
331
+ const evt = parseSseDataLine(line);
332
+ if (evt) {
333
+ yield evt;
334
+ }
335
+ }
336
+ }
337
+ } finally {
338
+ reader.releaseLock();
339
+ }
340
+ }
341
+
258
342
  // src/agents.ts
259
343
  var AgentsClient = class {
260
344
  constructor(client) {
@@ -298,72 +382,655 @@ var AgentsClient = class {
298
382
  if (!body) {
299
383
  return;
300
384
  }
301
- const reader = body.getReader();
302
- const decoder = new TextDecoder();
303
- let buffer = "";
304
- try {
305
- while (true) {
306
- const { done, value } = await reader.read();
307
- if (done) {
308
- break;
309
- }
310
- buffer += decoder.decode(value, { stream: true });
311
- let boundary = buffer.indexOf("\n\n");
312
- while (boundary !== -1) {
313
- const block = buffer.slice(0, boundary);
314
- buffer = buffer.slice(boundary + 2);
315
- for (const line of block.split("\n")) {
316
- const evt = parseSseDataLine(line);
317
- if (evt) {
318
- yield evt;
319
- }
320
- }
321
- boundary = buffer.indexOf("\n\n");
322
- }
385
+ yield* readSseStream(body);
386
+ }
387
+ };
388
+
389
+ // src/browser-postgrest.ts
390
+ function assertIdent(name, ctx) {
391
+ if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(name)) {
392
+ throw new RagableError(
393
+ `Invalid ${ctx} identifier "${name}" (use letters, numbers, underscore)`,
394
+ 400,
395
+ null
396
+ );
397
+ }
398
+ }
399
+ function quoteIdent(name) {
400
+ assertIdent(name, "column");
401
+ return `"${name}"`;
402
+ }
403
+ var OP_SQL = {
404
+ eq: "=",
405
+ neq: "<>",
406
+ gt: ">",
407
+ gte: ">=",
408
+ lt: "<",
409
+ lte: "<=",
410
+ like: "LIKE",
411
+ ilike: "ILIKE"
412
+ };
413
+ async function asPostgrestResponse(fn) {
414
+ try {
415
+ const data = await fn();
416
+ return { data, error: null };
417
+ } catch (e) {
418
+ const err = e instanceof RagableError ? e : new RagableError(e.message, 500, null);
419
+ return { data: null, error: err };
420
+ }
421
+ }
422
+ function buildWhere(filters, params) {
423
+ if (filters.length === 0) return { clause: "", nextIdx: 1 };
424
+ const parts = [];
425
+ let i = params.length;
426
+ for (const f of filters) {
427
+ assertIdent(f.column, "filter");
428
+ i += 1;
429
+ parts.push(`${quoteIdent(f.column)} ${OP_SQL[f.op]} $${i}`);
430
+ params.push(f.value);
431
+ }
432
+ return { clause: ` WHERE ${parts.join(" AND ")}`, nextIdx: i };
433
+ }
434
+ var PostgrestSelectBuilder = class {
435
+ constructor(run, databaseInstanceId, table, columns) {
436
+ this.run = run;
437
+ this.databaseInstanceId = databaseInstanceId;
438
+ this.table = table;
439
+ this.columns = columns;
440
+ __publicField(this, "filters", []);
441
+ __publicField(this, "_limit");
442
+ __publicField(this, "_order");
443
+ assertIdent(table, "table");
444
+ }
445
+ eq(column, value) {
446
+ this.filters.push({ op: "eq", column, value });
447
+ return this;
448
+ }
449
+ neq(column, value) {
450
+ this.filters.push({ op: "neq", column, value });
451
+ return this;
452
+ }
453
+ gt(column, value) {
454
+ this.filters.push({ op: "gt", column, value });
455
+ return this;
456
+ }
457
+ gte(column, value) {
458
+ this.filters.push({ op: "gte", column, value });
459
+ return this;
460
+ }
461
+ lt(column, value) {
462
+ this.filters.push({ op: "lt", column, value });
463
+ return this;
464
+ }
465
+ lte(column, value) {
466
+ this.filters.push({ op: "lte", column, value });
467
+ return this;
468
+ }
469
+ like(column, value) {
470
+ this.filters.push({ op: "like", column, value });
471
+ return this;
472
+ }
473
+ ilike(column, value) {
474
+ this.filters.push({ op: "ilike", column, value });
475
+ return this;
476
+ }
477
+ limit(n) {
478
+ this._limit = n;
479
+ return this;
480
+ }
481
+ order(column, options) {
482
+ this._order = { column, ascending: options?.ascending !== false };
483
+ return this;
484
+ }
485
+ /** @param includeUserLimit when false, omit `.limit()` (for `.single()` / `.maybeSingle()`). */
486
+ buildSelectCore(params, includeUserLimit) {
487
+ const tbl = quoteIdent(this.table);
488
+ const { clause } = buildWhere(this.filters, params);
489
+ let sql = `SELECT ${this.columns} FROM ${tbl}${clause}`;
490
+ if (this._order) {
491
+ sql += ` ORDER BY ${quoteIdent(this._order.column)} ${this._order.ascending ? "ASC" : "DESC"}`;
492
+ }
493
+ if (includeUserLimit && this._limit != null) {
494
+ sql += ` LIMIT ${Math.max(0, Math.floor(this._limit))}`;
495
+ }
496
+ return sql;
497
+ }
498
+ then(onfulfilled, onrejected) {
499
+ return this.executeMany().then(onfulfilled, onrejected);
500
+ }
501
+ async executeMany() {
502
+ return asPostgrestResponse(async () => {
503
+ const params = [];
504
+ const sql = this.buildSelectCore(params, true);
505
+ const res = await this.run({
506
+ databaseInstanceId: this.databaseInstanceId,
507
+ sql,
508
+ params,
509
+ readOnly: true
510
+ });
511
+ return res.rows;
512
+ });
513
+ }
514
+ async single() {
515
+ return asPostgrestResponse(async () => {
516
+ const params = [];
517
+ const base = this.buildSelectCore(params, false);
518
+ const sql = `${base} LIMIT 2`;
519
+ const res = await this.run({
520
+ databaseInstanceId: this.databaseInstanceId,
521
+ sql,
522
+ params,
523
+ readOnly: true
524
+ });
525
+ if (res.rows.length === 0) {
526
+ throw new RagableError("JSON object requested, multiple (or no) rows returned", 406, {
527
+ code: "PGRST116"
528
+ });
323
529
  }
324
- if (buffer.trim().length > 0) {
325
- for (const line of buffer.split("\n")) {
326
- const evt = parseSseDataLine(line);
327
- if (evt) {
328
- yield evt;
329
- }
530
+ if (res.rows.length > 1) {
531
+ throw new RagableError("JSON object requested, multiple (or no) rows returned", 406, {
532
+ code: "PGRST116"
533
+ });
534
+ }
535
+ return res.rows[0];
536
+ });
537
+ }
538
+ async maybeSingle() {
539
+ return asPostgrestResponse(async () => {
540
+ const params = [];
541
+ const base = this.buildSelectCore(params, false);
542
+ const sql = `${base} LIMIT 2`;
543
+ const res = await this.run({
544
+ databaseInstanceId: this.databaseInstanceId,
545
+ sql,
546
+ params,
547
+ readOnly: true
548
+ });
549
+ if (res.rows.length > 1) {
550
+ throw new RagableError("JSON object requested, multiple (or no) rows returned", 406, {
551
+ code: "PGRST116"
552
+ });
553
+ }
554
+ return res.rows[0] ?? null;
555
+ });
556
+ }
557
+ };
558
+ var PostgrestInsertBuilder = class {
559
+ constructor(run, databaseInstanceId, table, rows) {
560
+ this.run = run;
561
+ this.databaseInstanceId = databaseInstanceId;
562
+ this.table = table;
563
+ this.rows = rows;
564
+ __publicField(this, "returning", "*");
565
+ assertIdent(table, "table");
566
+ }
567
+ select(columns = "*") {
568
+ this.returning = columns;
569
+ return this;
570
+ }
571
+ then(onfulfilled, onrejected) {
572
+ return this.execute().then(onfulfilled, onrejected);
573
+ }
574
+ async execute() {
575
+ return asPostgrestResponse(async () => {
576
+ if (this.rows.length === 0) return [];
577
+ const keys = Object.keys(this.rows[0]);
578
+ for (const k of keys) assertIdent(k, "column");
579
+ const tbl = quoteIdent(this.table);
580
+ const params = [];
581
+ const valueGroups = [];
582
+ for (const row of this.rows) {
583
+ const placeholders = [];
584
+ for (const k of keys) {
585
+ params.push(row[k]);
586
+ placeholders.push(`$${params.length}`);
330
587
  }
588
+ valueGroups.push(`(${placeholders.join(", ")})`);
331
589
  }
332
- } finally {
333
- reader.releaseLock();
334
- }
590
+ const cols = keys.map(quoteIdent).join(", ");
591
+ const sql = `INSERT INTO ${tbl} (${cols}) VALUES ${valueGroups.join(", ")} RETURNING ${this.returning}`;
592
+ const res = await this.run({
593
+ databaseInstanceId: this.databaseInstanceId,
594
+ sql,
595
+ params,
596
+ readOnly: false
597
+ });
598
+ return res.rows;
599
+ });
335
600
  }
336
601
  };
337
- async function parseMaybeJsonBody(response) {
338
- const contentType = response.headers.get("content-type") ?? "";
339
- if (contentType.includes("application/json")) {
340
- try {
341
- return await response.json();
342
- } catch {
343
- return null;
344
- }
602
+ var PostgrestUpdateBuilder = class {
603
+ constructor(run, databaseInstanceId, table, patch) {
604
+ this.run = run;
605
+ this.databaseInstanceId = databaseInstanceId;
606
+ this.table = table;
607
+ this.patch = patch;
608
+ __publicField(this, "filters", []);
609
+ __publicField(this, "returning", "*");
610
+ assertIdent(table, "table");
345
611
  }
346
- try {
347
- return await response.text();
348
- } catch {
349
- return null;
612
+ eq(column, value) {
613
+ this.filters.push({ op: "eq", column, value });
614
+ return this;
615
+ }
616
+ select(columns = "*") {
617
+ this.returning = columns;
618
+ return this;
619
+ }
620
+ then(onfulfilled, onrejected) {
621
+ return this.execute().then(onfulfilled, onrejected);
622
+ }
623
+ async execute() {
624
+ return asPostgrestResponse(async () => {
625
+ const keys = Object.keys(this.patch);
626
+ if (keys.length === 0) {
627
+ throw new RagableError("Empty update payload", 400, null);
628
+ }
629
+ for (const k of keys) assertIdent(k, "column");
630
+ if (this.filters.length === 0) {
631
+ throw new RagableError(
632
+ "UPDATE requires a filter (e.g. .eq('id', value)) \u2014 refusing unscoped update",
633
+ 400,
634
+ null
635
+ );
636
+ }
637
+ const params = [];
638
+ const sets = [];
639
+ for (const k of keys) {
640
+ params.push(this.patch[k]);
641
+ sets.push(`${quoteIdent(k)} = $${params.length}`);
642
+ }
643
+ const { clause } = buildWhere(this.filters, params);
644
+ const tbl = quoteIdent(this.table);
645
+ const sql = `UPDATE ${tbl} SET ${sets.join(", ")}${clause} RETURNING ${this.returning}`;
646
+ const res = await this.run({
647
+ databaseInstanceId: this.databaseInstanceId,
648
+ sql,
649
+ params,
650
+ readOnly: false
651
+ });
652
+ return res.rows;
653
+ });
654
+ }
655
+ };
656
+ var PostgrestDeleteBuilder = class {
657
+ constructor(run, databaseInstanceId, table) {
658
+ this.run = run;
659
+ this.databaseInstanceId = databaseInstanceId;
660
+ this.table = table;
661
+ __publicField(this, "filters", []);
662
+ __publicField(this, "returning", "*");
663
+ assertIdent(table, "table");
664
+ }
665
+ eq(column, value) {
666
+ this.filters.push({ op: "eq", column, value });
667
+ return this;
668
+ }
669
+ select(columns = "*") {
670
+ this.returning = columns;
671
+ return this;
672
+ }
673
+ then(onfulfilled, onrejected) {
674
+ return this.execute().then(onfulfilled, onrejected);
675
+ }
676
+ async execute() {
677
+ return asPostgrestResponse(async () => {
678
+ if (this.filters.length === 0) {
679
+ throw new RagableError(
680
+ "DELETE requires a filter (e.g. .eq('id', value)) \u2014 refusing unscoped delete",
681
+ 400,
682
+ null
683
+ );
684
+ }
685
+ const params = [];
686
+ const { clause } = buildWhere(this.filters, params);
687
+ const tbl = quoteIdent(this.table);
688
+ const sql = `DELETE FROM ${tbl}${clause} RETURNING ${this.returning}`;
689
+ const res = await this.run({
690
+ databaseInstanceId: this.databaseInstanceId,
691
+ sql,
692
+ params,
693
+ readOnly: false
694
+ });
695
+ return res.rows;
696
+ });
697
+ }
698
+ };
699
+ var PostgrestTableApi = class {
700
+ constructor(run, databaseInstanceId, table) {
701
+ this.run = run;
702
+ this.databaseInstanceId = databaseInstanceId;
703
+ this.table = table;
704
+ }
705
+ select(columns = "*") {
706
+ return new PostgrestSelectBuilder(
707
+ this.run,
708
+ this.databaseInstanceId,
709
+ this.table,
710
+ columns
711
+ );
712
+ }
713
+ insert(values) {
714
+ const rows = Array.isArray(values) ? values : [values];
715
+ return new PostgrestInsertBuilder(
716
+ this.run,
717
+ this.databaseInstanceId,
718
+ this.table,
719
+ rows
720
+ );
721
+ }
722
+ update(patch) {
723
+ return new PostgrestUpdateBuilder(
724
+ this.run,
725
+ this.databaseInstanceId,
726
+ this.table,
727
+ patch
728
+ );
729
+ }
730
+ delete() {
731
+ return new PostgrestDeleteBuilder(
732
+ this.run,
733
+ this.databaseInstanceId,
734
+ this.table
735
+ );
350
736
  }
737
+ };
738
+
739
+ // src/browser.ts
740
+ function normalizeBrowserApiBase(baseUrl) {
741
+ return (baseUrl ?? "http://localhost:8080/api").replace(/\/+$/, "");
351
742
  }
352
- function parseSseDataLine(line) {
353
- const dataPrefix = "data: ";
354
- if (!line.startsWith(dataPrefix)) {
355
- return null;
743
+ function requireAuthGroupId(options) {
744
+ const id = options.authGroupId?.trim();
745
+ if (!id) {
746
+ throw new Error(
747
+ "authGroupId is required for auth and database methods on the browser client"
748
+ );
356
749
  }
357
- const json = line.slice(dataPrefix.length).trim();
358
- if (json.length === 0 || json === "[DONE]") {
359
- return null;
750
+ return id;
751
+ }
752
+ async function requireAccessToken(options) {
753
+ const getter = options.getAccessToken;
754
+ if (!getter) {
755
+ throw new Error(
756
+ "getAccessToken is required for this call (return the end-user access JWT)"
757
+ );
360
758
  }
361
- try {
362
- return JSON.parse(json);
363
- } catch {
364
- return null;
759
+ const token = await getter();
760
+ if (!token?.trim()) {
761
+ throw new Error("getAccessToken returned no token");
762
+ }
763
+ return token.trim();
764
+ }
765
+ async function parseJsonOrThrow(response) {
766
+ const payload = await parseMaybeJsonBody(response);
767
+ if (!response.ok) {
768
+ const message = extractErrorMessage(payload, response.statusText);
769
+ throw new RagableError(message, response.status, payload);
770
+ }
771
+ return payload;
772
+ }
773
+ function parseExpiresInSeconds(expiresIn) {
774
+ const s = expiresIn.trim().toLowerCase();
775
+ const m = /^(\d+)([smhd])?$/.exec(s);
776
+ if (m) {
777
+ const n = Number(m[1]);
778
+ const u = m[2] ?? "s";
779
+ const mult = u === "s" ? 1 : u === "m" ? 60 : u === "h" ? 3600 : u === "d" ? 86400 : 1;
780
+ return n * mult;
781
+ }
782
+ const asNum = Number(s);
783
+ return Number.isFinite(asNum) ? asNum : 0;
784
+ }
785
+ function toSupabaseSession(s) {
786
+ return {
787
+ access_token: s.accessToken,
788
+ refresh_token: s.refreshToken,
789
+ expires_in: parseExpiresInSeconds(s.expiresIn),
790
+ token_type: "bearer",
791
+ user: s.user
792
+ };
793
+ }
794
+ var RagableBrowserAuthClient = class {
795
+ constructor(options) {
796
+ this.options = options;
797
+ }
798
+ get fetchImpl() {
799
+ return this.options.fetch ?? fetch;
800
+ }
801
+ toUrl(path) {
802
+ return `${normalizeBrowserApiBase(this.options.baseUrl)}${path.startsWith("/") ? path : `/${path}`}`;
803
+ }
804
+ baseHeaders(json) {
805
+ const h = new Headers(this.options.headers);
806
+ if (json) {
807
+ h.set("Content-Type", "application/json");
808
+ }
809
+ return h;
810
+ }
811
+ authPrefix() {
812
+ const gid = requireAuthGroupId(this.options);
813
+ return `/auth-groups/${gid}/auth`;
814
+ }
815
+ /** Supabase: `signUp` → `{ data: { user, session }, error }` */
816
+ async signUp(credentials) {
817
+ return asPostgrestResponse(async () => {
818
+ const name = typeof credentials.options?.data?.name === "string" ? credentials.options.data.name : void 0;
819
+ const session = await this.register({
820
+ email: credentials.email,
821
+ password: credentials.password,
822
+ name
823
+ });
824
+ return { user: session.user, session: toSupabaseSession(session) };
825
+ });
826
+ }
827
+ /** Supabase: `signInWithPassword` */
828
+ async signInWithPassword(credentials) {
829
+ return asPostgrestResponse(async () => {
830
+ const session = await this.login(credentials);
831
+ return { user: session.user, session: toSupabaseSession(session) };
832
+ });
833
+ }
834
+ /** Supabase: `refreshSession` */
835
+ async refreshSession(refreshToken) {
836
+ return asPostgrestResponse(async () => {
837
+ const tokens = await this.refresh({ refreshToken });
838
+ const me = await this.getUserFromToken(tokens.accessToken);
839
+ const session = {
840
+ access_token: tokens.accessToken,
841
+ refresh_token: tokens.refreshToken,
842
+ expires_in: parseExpiresInSeconds(tokens.expiresIn),
843
+ token_type: "bearer",
844
+ user: me.user
845
+ };
846
+ return { session, user: me.user };
847
+ });
848
+ }
849
+ /** Supabase: `getUser()` — needs `getAccessToken` on the client */
850
+ async getUser() {
851
+ return asPostgrestResponse(() => this.getMe());
852
+ }
853
+ /** Supabase: `updateUser` */
854
+ async updateUser(attributes) {
855
+ return asPostgrestResponse(
856
+ () => this.updateMe({
857
+ password: attributes.password,
858
+ name: attributes.data?.name
859
+ })
860
+ );
861
+ }
862
+ /**
863
+ * Supabase/Firebase: no server call — clear tokens in your app.
864
+ * Returns `{ error: null }` for API compatibility.
865
+ */
866
+ async signOut(_options) {
867
+ return { error: null };
868
+ }
869
+ async getUserFromToken(accessToken) {
870
+ const headers = this.baseHeaders(false);
871
+ headers.set("Authorization", `Bearer ${accessToken}`);
872
+ const response = await this.fetchImpl(`${this.toUrl(this.authPrefix())}/me`, {
873
+ method: "GET",
874
+ headers
875
+ });
876
+ return parseJsonOrThrow(response);
877
+ }
878
+ async register(body) {
879
+ const response = await this.fetchImpl(`${this.toUrl(this.authPrefix())}/register`, {
880
+ method: "POST",
881
+ headers: this.baseHeaders(true),
882
+ body: JSON.stringify(body)
883
+ });
884
+ return parseJsonOrThrow(response);
365
885
  }
886
+ async login(body) {
887
+ const response = await this.fetchImpl(`${this.toUrl(this.authPrefix())}/login`, {
888
+ method: "POST",
889
+ headers: this.baseHeaders(true),
890
+ body: JSON.stringify(body)
891
+ });
892
+ return parseJsonOrThrow(response);
893
+ }
894
+ async refresh(body) {
895
+ const response = await this.fetchImpl(`${this.toUrl(this.authPrefix())}/refresh`, {
896
+ method: "POST",
897
+ headers: this.baseHeaders(true),
898
+ body: JSON.stringify(body)
899
+ });
900
+ return parseJsonOrThrow(response);
901
+ }
902
+ async getMe() {
903
+ const token = await requireAccessToken(this.options);
904
+ const headers = this.baseHeaders(false);
905
+ headers.set("Authorization", `Bearer ${token}`);
906
+ const response = await this.fetchImpl(`${this.toUrl(this.authPrefix())}/me`, {
907
+ method: "GET",
908
+ headers
909
+ });
910
+ return parseJsonOrThrow(response);
911
+ }
912
+ async updateMe(body) {
913
+ const token = await requireAccessToken(this.options);
914
+ const headers = this.baseHeaders(true);
915
+ headers.set("Authorization", `Bearer ${token}`);
916
+ const response = await this.fetchImpl(`${this.toUrl(this.authPrefix())}/me`, {
917
+ method: "PATCH",
918
+ headers,
919
+ body: JSON.stringify(body)
920
+ });
921
+ return parseJsonOrThrow(response);
922
+ }
923
+ };
924
+ var RagableBrowserDatabaseClient = class {
925
+ constructor(options) {
926
+ this.options = options;
927
+ }
928
+ get fetchImpl() {
929
+ return this.options.fetch ?? fetch;
930
+ }
931
+ toUrl(path) {
932
+ return `${normalizeBrowserApiBase(this.options.baseUrl)}${path.startsWith("/") ? path : `/${path}`}`;
933
+ }
934
+ async query(params) {
935
+ const gid = requireAuthGroupId(this.options);
936
+ const token = await requireAccessToken(this.options);
937
+ const headers = this.baseHeaders();
938
+ headers.set("Authorization", `Bearer ${token}`);
939
+ headers.set("Content-Type", "application/json");
940
+ const response = await this.fetchImpl(
941
+ this.toUrl(`/auth-groups/${gid}/data/query`),
942
+ {
943
+ method: "POST",
944
+ headers,
945
+ body: JSON.stringify({
946
+ databaseInstanceId: params.databaseInstanceId,
947
+ sql: params.sql,
948
+ ...params.params !== void 0 ? { params: params.params } : {},
949
+ ...params.readOnly === false ? { readOnly: false } : {},
950
+ ...params.timeoutMs !== void 0 ? { timeoutMs: params.timeoutMs } : {},
951
+ ...params.rowLimit !== void 0 ? { rowLimit: params.rowLimit } : {}
952
+ })
953
+ }
954
+ );
955
+ return parseJsonOrThrow(response);
956
+ }
957
+ baseHeaders() {
958
+ return new Headers(this.options.headers);
959
+ }
960
+ };
961
+ var RagableBrowserAgentsClient = class {
962
+ constructor(options) {
963
+ this.options = options;
964
+ }
965
+ get fetchImpl() {
966
+ return this.options.fetch ?? fetch;
967
+ }
968
+ toUrl(path) {
969
+ return `${normalizeBrowserApiBase(this.options.baseUrl)}${path.startsWith("/") ? path : `/${path}`}`;
970
+ }
971
+ /**
972
+ * Stream agent execution as SSE (`POST /public/organizations/:orgId/agents/:agentId/chat/stream`).
973
+ */
974
+ async *chatStream(agentId, params) {
975
+ const orgId = this.options.organizationId;
976
+ const body = {
977
+ message: params.message,
978
+ ...params.history !== void 0 ? { history: params.history } : {},
979
+ ...params.triggerSubtype !== void 0 ? { triggerSubtype: params.triggerSubtype } : {},
980
+ ...params.triggerNodeId !== void 0 ? { triggerNodeId: params.triggerNodeId } : {}
981
+ };
982
+ const headers = new Headers(this.options.headers);
983
+ headers.set("Content-Type", "application/json");
984
+ const response = await this.fetchImpl(
985
+ this.toUrl(`/public/organizations/${orgId}/agents/${agentId}/chat/stream`),
986
+ {
987
+ method: "POST",
988
+ headers,
989
+ body: JSON.stringify(body)
990
+ }
991
+ );
992
+ if (!response.ok) {
993
+ const payload = await parseMaybeJsonBody(response);
994
+ const message = extractErrorMessage(payload, response.statusText);
995
+ throw new RagableError(message, response.status, payload);
996
+ }
997
+ const streamBody = response.body;
998
+ if (!streamBody) {
999
+ return;
1000
+ }
1001
+ yield* readSseStream(streamBody);
1002
+ }
1003
+ };
1004
+ var RagableBrowser = class {
1005
+ constructor(options) {
1006
+ __publicField(this, "agents");
1007
+ __publicField(this, "auth");
1008
+ __publicField(this, "database");
1009
+ __publicField(this, "options");
1010
+ this.options = options;
1011
+ this.agents = new RagableBrowserAgentsClient(options);
1012
+ this.auth = new RagableBrowserAuthClient(options);
1013
+ this.database = new RagableBrowserDatabaseClient(options);
1014
+ }
1015
+ /**
1016
+ * Supabase-style table API: `.from('items').select().eq('id', 1).single()`.
1017
+ * Pass `databaseInstanceId` here or set `databaseInstanceId` on the client options.
1018
+ */
1019
+ from(table, databaseInstanceId) {
1020
+ const id = databaseInstanceId?.trim() || this.options.databaseInstanceId?.trim();
1021
+ if (!id) {
1022
+ throw new Error(
1023
+ "RagableBrowser.from() requires databaseInstanceId in client options or as the second argument"
1024
+ );
1025
+ }
1026
+ const run = (p) => this.database.query(p);
1027
+ return new PostgrestTableApi(run, id, table);
1028
+ }
1029
+ };
1030
+ function createBrowserClient(options) {
1031
+ return new RagableBrowser(options);
366
1032
  }
1033
+ var createRagableBrowserClient = createBrowserClient;
367
1034
 
368
1035
  // src/rag.ts
369
1036
  function formatRetrievalContext(results, options = {}) {
@@ -421,19 +1088,64 @@ var Ragable = class {
421
1088
  };
422
1089
  }
423
1090
  };
424
- function createClient(options) {
1091
+ function isServerClientOptions(o) {
1092
+ return typeof o === "object" && o !== null && "apiKey" in o && typeof o.apiKey === "string" && o.apiKey.length > 0;
1093
+ }
1094
+ function createClient(urlOrOptions, browserOptions) {
1095
+ if (typeof urlOrOptions === "string") {
1096
+ if (!browserOptions) {
1097
+ throw new Error(
1098
+ "createClient(url, options) requires options with at least organizationId"
1099
+ );
1100
+ }
1101
+ const raw = urlOrOptions.trim().replace(/\/+$/, "");
1102
+ const baseUrl = raw.endsWith("/api") ? raw : `${raw}/api`;
1103
+ return createBrowserClient({
1104
+ ...browserOptions,
1105
+ baseUrl: normalizeBrowserApiBase(baseUrl)
1106
+ });
1107
+ }
1108
+ if (isServerClientOptions(urlOrOptions)) {
1109
+ return new Ragable(urlOrOptions);
1110
+ }
1111
+ if (typeof urlOrOptions === "object" && urlOrOptions !== null && "organizationId" in urlOrOptions && typeof urlOrOptions.organizationId === "string") {
1112
+ return createBrowserClient(
1113
+ urlOrOptions
1114
+ );
1115
+ }
1116
+ throw new Error(
1117
+ "createClient(options) requires apiKey (server) or organizationId (browser)"
1118
+ );
1119
+ }
1120
+ function createRagableServerClient(options) {
425
1121
  return new Ragable(options);
426
1122
  }
427
1123
  // Annotate the CommonJS export names for ESM import in node:
428
1124
  0 && (module.exports = {
429
1125
  AgentsClient,
1126
+ PostgrestDeleteBuilder,
1127
+ PostgrestInsertBuilder,
1128
+ PostgrestSelectBuilder,
1129
+ PostgrestTableApi,
1130
+ PostgrestUpdateBuilder,
430
1131
  Ragable,
1132
+ RagableBrowser,
1133
+ RagableBrowserAgentsClient,
1134
+ RagableBrowserAuthClient,
1135
+ RagableBrowserDatabaseClient,
431
1136
  RagableError,
432
1137
  RagableRequestClient,
433
1138
  ShiftClient,
1139
+ asPostgrestResponse,
1140
+ createBrowserClient,
434
1141
  createClient,
435
1142
  createRagPipeline,
1143
+ createRagableBrowserClient,
1144
+ createRagableServerClient,
436
1145
  extractErrorMessage,
437
- formatRetrievalContext
1146
+ formatRetrievalContext,
1147
+ normalizeBrowserApiBase,
1148
+ parseSseDataLine,
1149
+ readSseStream
438
1150
  });
439
1151
  //# sourceMappingURL=index.js.map