@synapcores/sdk 0.1.0 → 0.2.1

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
@@ -35,10 +35,16 @@ __export(index_exports, {
35
35
  AutoMLModel: () => AutoMLModel,
36
36
  BackupClient: () => BackupClient,
37
37
  BatchOperationError: () => BatchOperationError,
38
+ ChatClient: () => ChatClient,
38
39
  Collection: () => Collection,
39
40
  ConnectionError: () => ConnectionError,
41
+ FilesystemCollectionsClient: () => FilesystemCollectionsClient,
42
+ GraphClient: () => GraphClient,
40
43
  ImportExportClient: () => ImportExportClient,
41
44
  IntegrationClient: () => IntegrationClient,
45
+ McpClient: () => McpClient,
46
+ MultimodalClient: () => MultimodalClient,
47
+ NL2SqlClient: () => NL2SqlClient,
42
48
  NLPClient: () => NLPClient,
43
49
  NotFoundError: () => NotFoundError,
44
50
  RateLimitError: () => RateLimitError,
@@ -49,8 +55,11 @@ __export(index_exports, {
49
55
  Subscription: () => Subscription,
50
56
  SynapCores: () => SynapCores,
51
57
  SynapCoresError: () => SynapCoresError,
58
+ SystemClient: () => SystemClient,
52
59
  TimeoutError: () => TimeoutError,
53
60
  TransactionError: () => TransactionError,
61
+ TransactionsClient: () => TransactionsClient,
62
+ Tx: () => Tx,
54
63
  VERSION: () => VERSION,
55
64
  ValidationError: () => ValidationError,
56
65
  VectorError: () => VectorError,
@@ -83,13 +92,14 @@ var Subscription = class extends import_events.EventEmitter {
83
92
  }
84
93
  async createConnection() {
85
94
  const client = this.collection.client;
86
- const protocol = client.config.useHttps ? "wss" : "ws";
87
- const url = `${protocol}://${client.config.host}:${client.config.port}/v1/ws`;
88
- const headers = {};
89
- if (client.config.apiKey) {
90
- headers["Authorization"] = `Bearer ${client.config.apiKey}`;
91
- }
92
- this.ws = new import_ws.default(url, { headers });
95
+ const { token } = await client.createWsTicket();
96
+ const wsBase = client._getWsBaseUrl ? client._getWsBaseUrl() : (() => {
97
+ const cfg = client.config ?? client._getConfig();
98
+ const protocol = cfg.useHttps ? "wss" : "ws";
99
+ return `${protocol}://${cfg.host}:${cfg.port}`;
100
+ })();
101
+ const url = `${wsBase}/ws?token=${encodeURIComponent(token)}`;
102
+ this.ws = new import_ws.default(url);
93
103
  this.ws.on("open", () => {
94
104
  this.reconnectAttempts = 0;
95
105
  this.subscribe();
@@ -400,19 +410,14 @@ var AutoMLModel = class {
400
410
  const isSingle = !Array.isArray(data);
401
411
  const inputs = isSingle ? [data] : data;
402
412
  const response = await this.client.synapCores._getHttpClient().post(
403
- "/ai/predict",
404
- {
405
- model_id: this.id,
406
- inputs
407
- }
413
+ `/automl/models/${this.id}/predict`,
414
+ { inputs }
408
415
  );
409
- const predictions = response.data.predictions;
416
+ const predictions = response.data.predictions ?? response.data;
410
417
  return isSingle ? predictions[0] : predictions;
411
418
  }
412
419
  async evaluate(testData, target) {
413
- const payload = {
414
- model_id: this.id
415
- };
420
+ const payload = {};
416
421
  if (typeof testData === "string") {
417
422
  payload.collection = testData;
418
423
  } else {
@@ -422,14 +427,14 @@ var AutoMLModel = class {
422
427
  }
423
428
  }
424
429
  const { data } = await this.client.synapCores._getHttpClient().post(
425
- "/ai/evaluate",
430
+ `/automl/models/${this.id}/evaluate`,
426
431
  payload
427
432
  );
428
433
  return data;
429
434
  }
430
435
  async delete() {
431
436
  await this.client.synapCores._getHttpClient().delete(
432
- `/ai/models/${this.id}`
437
+ `/automl/models/${this.id}`
433
438
  );
434
439
  }
435
440
  };
@@ -438,7 +443,7 @@ var AutoMLClient = class {
438
443
  this.synapCores = synapCores;
439
444
  }
440
445
  async train(options) {
441
- const { data } = await this.synapCores._getHttpClient().post("/ai/train", {
446
+ const { data } = await this.synapCores._getHttpClient().post("/automl/train", {
442
447
  collection: options.collection,
443
448
  target: options.target,
444
449
  features: options.features,
@@ -455,15 +460,15 @@ var AutoMLClient = class {
455
460
  task: data.task,
456
461
  status: data.status,
457
462
  accuracy: data.accuracy,
458
- createdAt: new Date(data.created_at),
463
+ createdAt: new Date(data.created_at ?? Date.now()),
459
464
  updatedAt: data.updated_at ? new Date(data.updated_at) : void 0,
460
- config: data.config
465
+ config: data.config ?? {}
461
466
  };
462
467
  return new AutoMLModel(this, modelInfo);
463
468
  }
464
469
  async getModel(modelId) {
465
470
  const { data } = await this.synapCores._getHttpClient().get(
466
- `/ai/models/${modelId}`
471
+ `/automl/models/${modelId}`
467
472
  );
468
473
  const modelInfo = {
469
474
  id: data.id,
@@ -471,32 +476,35 @@ var AutoMLClient = class {
471
476
  task: data.task,
472
477
  status: data.status,
473
478
  accuracy: data.accuracy,
474
- createdAt: new Date(data.created_at),
479
+ createdAt: new Date(data.created_at ?? Date.now()),
475
480
  updatedAt: data.updated_at ? new Date(data.updated_at) : void 0,
476
- config: data.config
481
+ config: data.config ?? {}
477
482
  };
478
483
  return new AutoMLModel(this, modelInfo);
479
484
  }
480
485
  async listModels(filters) {
481
- const { data } = await this.synapCores._getHttpClient().get("/ai/models", {
486
+ const { data } = await this.synapCores._getHttpClient().get("/automl/models", {
482
487
  params: filters
483
488
  });
484
- return data.models.map((model) => ({
489
+ return (data.models ?? data ?? []).map((model) => ({
485
490
  id: model.id,
486
491
  name: model.name,
487
492
  task: model.task,
488
493
  status: model.status,
489
494
  accuracy: model.accuracy,
490
- createdAt: new Date(model.created_at),
495
+ createdAt: new Date(model.created_at ?? Date.now()),
491
496
  updatedAt: model.updated_at ? new Date(model.updated_at) : void 0,
492
- config: model.config
497
+ config: model.config ?? {}
493
498
  }));
494
499
  }
495
500
  /**
496
- * Start async training job
501
+ * Start async training job.
502
+ *
503
+ * In v1.5.0-ce there is no separate /train/async endpoint — /automl/train
504
+ * itself returns a job descriptor when the training is long-running.
497
505
  */
498
506
  async trainAsync(options) {
499
- const { data } = await this.synapCores._getHttpClient().post("/ai/train/async", {
507
+ const { data } = await this.synapCores._getHttpClient().post("/automl/train", {
500
508
  collection: options.collection,
501
509
  target: options.target,
502
510
  features: options.features,
@@ -506,49 +514,20 @@ var AutoMLClient = class {
506
514
  validation_split: options.validationSplit || 0.2,
507
515
  max_trials: options.maxTrials || 10,
508
516
  timeout_minutes: options.timeoutMinutes || 60,
517
+ async: true,
509
518
  callback_url: options.callback_url,
510
519
  webhook_url: options.webhook_url
511
520
  });
512
- return {
513
- id: data.id || data.job_id,
514
- name: data.name,
515
- status: data.status,
516
- progress: data.progress || 0,
517
- phase: data.phase,
518
- task: data.task,
519
- current_trial: data.current_trial,
520
- total_trials: data.total_trials || options.maxTrials || 10,
521
- best_accuracy: data.best_accuracy,
522
- eta_ms: data.eta_ms || data.estimated_time_remaining_ms,
523
- error: data.error,
524
- started_at: new Date(data.started_at || Date.now()),
525
- completed_at: data.completed_at ? new Date(data.completed_at) : void 0,
526
- model_id: data.model_id
527
- };
521
+ return this.mapTrainingJob(data, options.maxTrials || 10);
528
522
  }
529
523
  /**
530
524
  * Get training job status
531
525
  */
532
526
  async getTrainingJob(jobId) {
533
527
  const { data } = await this.synapCores._getHttpClient().get(
534
- `/ai/train/jobs/${jobId}`
528
+ `/automl/jobs/${jobId}`
535
529
  );
536
- return {
537
- id: data.id || jobId,
538
- name: data.name,
539
- status: data.status,
540
- progress: data.progress || 0,
541
- phase: data.phase,
542
- task: data.task,
543
- current_trial: data.current_trial,
544
- total_trials: data.total_trials,
545
- best_accuracy: data.best_accuracy,
546
- eta_ms: data.eta_ms || data.estimated_time_remaining_ms,
547
- error: data.error,
548
- started_at: new Date(data.started_at),
549
- completed_at: data.completed_at ? new Date(data.completed_at) : void 0,
550
- model_id: data.model_id
551
- };
530
+ return this.mapTrainingJob(data);
552
531
  }
553
532
  /**
554
533
  * List training jobs
@@ -558,45 +537,36 @@ var AutoMLClient = class {
558
537
  if (options.status) params.append("status", options.status);
559
538
  if (options.page) params.append("page", options.page.toString());
560
539
  if (options.page_size) params.append("page_size", options.page_size.toString());
540
+ const qs = params.toString();
561
541
  const { data } = await this.synapCores._getHttpClient().get(
562
- `/ai/train/jobs?${params.toString()}`
542
+ `/automl/jobs${qs ? `?${qs}` : ""}`
563
543
  );
564
- return (data.jobs || data).map((job) => ({
565
- id: job.id,
566
- name: job.name,
567
- status: job.status,
568
- progress: job.progress || 0,
569
- phase: job.phase,
570
- task: job.task,
571
- current_trial: job.current_trial,
572
- total_trials: job.total_trials,
573
- best_accuracy: job.best_accuracy,
574
- eta_ms: job.eta_ms || job.estimated_time_remaining_ms,
575
- error: job.error,
576
- started_at: new Date(job.started_at),
577
- completed_at: job.completed_at ? new Date(job.completed_at) : void 0,
578
- model_id: job.model_id
579
- }));
544
+ return (data.jobs ?? data ?? []).map((job) => this.mapTrainingJob(job));
580
545
  }
581
546
  /**
582
- * Cancel a training job
547
+ * Cancel/stop a training job
583
548
  */
584
549
  async cancelTrainingJob(jobId) {
585
- await this.synapCores._getHttpClient().post(`/ai/train/jobs/${jobId}/cancel`);
550
+ await this.synapCores._getHttpClient().post(`/automl/jobs/${jobId}/stop`);
586
551
  }
587
552
  /**
588
- * Get training metrics for a job
553
+ * Get training metrics for a job.
554
+ *
555
+ * v1.5.0-ce: gateway no longer has a dedicated /metrics route — metrics
556
+ * (when available) ship inside the /automl/jobs/:id payload as
557
+ * `metrics` or `trial_metrics`. We just unwrap that field here.
589
558
  */
590
559
  async getTrainingMetrics(jobId) {
591
560
  const { data } = await this.synapCores._getHttpClient().get(
592
- `/ai/train/jobs/${jobId}/metrics`
561
+ `/automl/jobs/${jobId}`
593
562
  );
594
- return (data.metrics || data).map((metric) => ({
563
+ const metrics = data.metrics ?? data.trial_metrics ?? [];
564
+ return metrics.map((metric) => ({
595
565
  trial: metric.trial,
596
566
  accuracy: metric.accuracy,
597
567
  loss: metric.loss,
598
568
  metrics: metric.metrics,
599
- timestamp: new Date(metric.timestamp)
569
+ timestamp: new Date(metric.timestamp ?? Date.now())
600
570
  }));
601
571
  }
602
572
  /**
@@ -629,6 +599,24 @@ var AutoMLClient = class {
629
599
  await new Promise((resolve) => setTimeout(resolve, pollInterval));
630
600
  }
631
601
  }
602
+ mapTrainingJob(data, fallbackMaxTrials) {
603
+ return {
604
+ id: data.id ?? data.job_id,
605
+ name: data.name,
606
+ status: data.status,
607
+ progress: data.progress ?? 0,
608
+ phase: data.phase,
609
+ task: data.task,
610
+ current_trial: data.current_trial,
611
+ total_trials: data.total_trials ?? fallbackMaxTrials,
612
+ best_accuracy: data.best_accuracy,
613
+ eta_ms: data.eta_ms ?? data.estimated_time_remaining_ms,
614
+ error: data.error,
615
+ started_at: new Date(data.started_at ?? Date.now()),
616
+ completed_at: data.completed_at ? new Date(data.completed_at) : void 0,
617
+ model_id: data.model_id
618
+ };
619
+ }
632
620
  };
633
621
 
634
622
  // src/nlp.ts
@@ -636,32 +624,67 @@ var NLPClient = class {
636
624
  constructor(synapCores) {
637
625
  this.synapCores = synapCores;
638
626
  }
627
+ /**
628
+ * Run multiple NLP tasks in parallel and stitch them into a single
629
+ * NLPAnalysis (or array of them, matching the input shape).
630
+ */
639
631
  async analyze(options) {
640
632
  const isBatch = Array.isArray(options.text);
641
633
  const texts = isBatch ? options.text : [options.text];
642
- const { data } = await this.synapCores._getHttpClient().post("/ai/analyze", {
643
- texts,
644
- tasks: options.tasks || ["sentiment", "entities", "keywords"],
645
- language: options.language
646
- });
647
- const results = data.results.map((r) => ({
648
- sentiment: r.sentiment ? {
649
- label: r.sentiment.label,
650
- score: r.sentiment.score,
651
- confidence: r.sentiment.confidence
652
- } : void 0,
653
- entities: r.entities ? r.entities.map((e) => ({
654
- text: e.text,
655
- type: e.type,
656
- start: e.start,
657
- end: e.end,
658
- score: e.score
659
- })) : void 0,
660
- summary: r.summary,
661
- keywords: r.keywords,
662
- language: r.language
663
- }));
664
- return isBatch ? results : results[0];
634
+ const tasks = options.tasks || ["sentiment", "entities", "summarize"];
635
+ const http = this.synapCores._getHttpClient();
636
+ const wantSentiment = tasks.includes("sentiment");
637
+ const wantEntities = tasks.includes("entities");
638
+ const wantSummarize = tasks.includes("summarize") || tasks.includes("summary");
639
+ const wantKeywords = tasks.includes("keywords");
640
+ const results = await Promise.all(
641
+ texts.map(async (text) => {
642
+ const out = {};
643
+ const calls = [];
644
+ if (wantSentiment) {
645
+ calls.push(
646
+ http.post("/ai/sentiment", { texts: [text], language: options.language }).then(({ data }) => {
647
+ const s = (data.sentiments ?? [])[0] ?? data.sentiment ?? data;
648
+ if (s) {
649
+ out.sentiment = {
650
+ label: s.label,
651
+ score: s.score,
652
+ confidence: s.confidence
653
+ };
654
+ }
655
+ }).catch(() => void 0)
656
+ );
657
+ }
658
+ if (wantEntities) {
659
+ calls.push(
660
+ http.post("/ai/entities", { text, language: options.language }).then(({ data }) => {
661
+ const arr = data.entities ?? [];
662
+ out.entities = arr.map((e) => ({
663
+ text: e.text,
664
+ type: e.type,
665
+ start: e.start,
666
+ end: e.end,
667
+ score: e.score
668
+ }));
669
+ }).catch(() => void 0)
670
+ );
671
+ }
672
+ if (wantSummarize) {
673
+ calls.push(
674
+ http.post("/ai/summarize", { text }).then(({ data }) => {
675
+ out.summary = data.summary;
676
+ }).catch(() => void 0)
677
+ );
678
+ }
679
+ if (wantKeywords) {
680
+ out.keywords = void 0;
681
+ }
682
+ await Promise.all(calls);
683
+ return out;
684
+ })
685
+ );
686
+ if (isBatch) return results;
687
+ return results[0] ?? {};
665
688
  }
666
689
  async summarize(options) {
667
690
  const { data } = await this.synapCores._getHttpClient().post("/ai/summarize", {
@@ -676,7 +699,7 @@ var NLPClient = class {
676
699
  text,
677
700
  entity_types: entityTypes
678
701
  });
679
- return data.entities.map((e) => ({
702
+ return (data.entities ?? []).map((e) => ({
680
703
  text: e.text,
681
704
  type: e.type,
682
705
  start: e.start,
@@ -690,7 +713,7 @@ var NLPClient = class {
690
713
  const { data } = await this.synapCores._getHttpClient().post("/ai/sentiment", {
691
714
  texts
692
715
  });
693
- const results = data.sentiments.map((s) => ({
716
+ const results = (data.sentiments ?? []).map((s) => ({
694
717
  label: s.label,
695
718
  score: s.score,
696
719
  confidence: s.confidence
@@ -707,6 +730,22 @@ var NLPClient = class {
707
730
  });
708
731
  return isBatch ? data.classifications : data.classifications[0];
709
732
  }
733
+ /**
734
+ * Question-answering against an optional context window.
735
+ */
736
+ async qa(question, context, opts = {}) {
737
+ const { data } = await this.synapCores._getHttpClient().post("/ai/qa", {
738
+ question,
739
+ context,
740
+ max_answer_tokens: opts.maxAnswerTokens
741
+ });
742
+ return {
743
+ answer: data.answer ?? data.text ?? "",
744
+ score: data.score ?? data.confidence,
745
+ start: data.start,
746
+ end: data.end
747
+ };
748
+ }
710
749
  };
711
750
 
712
751
  // src/recipes.ts
@@ -850,11 +889,142 @@ var RecipeClient = class {
850
889
  };
851
890
  }
852
891
  /**
853
- * List available recipe categories
892
+ * List available recipe categories with counts.
893
+ *
894
+ * v0.2.0: gateway path is /recipes/categories/counts.
895
+ * Returns the array of category names; for the {category, count}
896
+ * payload use `listCategoriesWithCounts`.
854
897
  */
855
898
  async listCategories() {
856
- const { data } = await this.synapCores._getHttpClient().get("/recipes/categories");
857
- return data.categories || [];
899
+ const data = await this.listCategoriesWithCounts();
900
+ return data.map((c) => c.category);
901
+ }
902
+ async listCategoriesWithCounts() {
903
+ const { data } = await this.synapCores._getHttpClient().get(
904
+ "/recipes/categories/counts"
905
+ );
906
+ const arr = data.categories ?? data ?? [];
907
+ return arr.map((c) => ({
908
+ category: c.category ?? c.name ?? c,
909
+ count: c.count ?? c.recipe_count ?? 0
910
+ }));
911
+ }
912
+ /**
913
+ * Validate a recipe payload before saving/executing.
914
+ */
915
+ async validate(body) {
916
+ const { data } = await this.synapCores._getHttpClient().post("/recipes/validate", body);
917
+ return {
918
+ is_valid: data.is_valid ?? data.valid ?? false,
919
+ errors: data.errors ?? [],
920
+ warnings: data.warnings ?? []
921
+ };
922
+ }
923
+ /**
924
+ * Get execution history for a specific recipe.
925
+ */
926
+ async getHistory(id) {
927
+ const { data } = await this.synapCores._getHttpClient().get(`/recipes/${id}/history`);
928
+ const arr = data.history ?? data.executions ?? data ?? [];
929
+ return arr.map((row) => ({
930
+ id: row.id ?? row.execution_id ?? "",
931
+ success: row.success ?? row.status === "completed",
932
+ results: row.results,
933
+ error: row.error,
934
+ execution_time_ms: row.execution_time_ms ?? row.took_ms ?? 0,
935
+ statements_executed: row.statements_executed ?? 0
936
+ }));
937
+ }
938
+ /**
939
+ * List built-in / shared recipe templates.
940
+ */
941
+ async listTemplates() {
942
+ const { data } = await this.synapCores._getHttpClient().get("/recipes/templates");
943
+ return (data.templates ?? data ?? []).map((t) => ({
944
+ id: t.id,
945
+ name: t.name,
946
+ description: t.description ?? "",
947
+ category: t.category ?? "template",
948
+ tags: t.tags ?? [],
949
+ created_at: new Date(t.created_at ?? Date.now()),
950
+ updated_at: new Date(t.updated_at ?? t.created_at ?? Date.now()),
951
+ author: t.author,
952
+ execution_count: t.execution_count
953
+ }));
954
+ }
955
+ /**
956
+ * Get a specific recipe template.
957
+ */
958
+ async getTemplate(id) {
959
+ const { data } = await this.synapCores._getHttpClient().get(`/recipes/templates/${id}`);
960
+ return {
961
+ id: data.id,
962
+ name: data.name,
963
+ description: data.description ?? "",
964
+ category: data.category ?? "template",
965
+ content: data.content ?? "",
966
+ tags: data.tags ?? [],
967
+ parameters: data.parameters ?? [],
968
+ created_at: new Date(data.created_at ?? Date.now()),
969
+ updated_at: new Date(data.updated_at ?? data.created_at ?? Date.now()),
970
+ author: data.author,
971
+ execution_count: data.execution_count,
972
+ version: data.version
973
+ };
974
+ }
975
+ /**
976
+ * Execute a recipe template with a parameter set.
977
+ */
978
+ async executeTemplate(id, params = {}) {
979
+ const { data } = await this.synapCores._getHttpClient().post(
980
+ `/recipes/templates/${id}/execute`,
981
+ { parameters: params }
982
+ );
983
+ return {
984
+ id: data.id ?? data.execution_id ?? "",
985
+ success: data.success ?? false,
986
+ results: data.results,
987
+ error: data.error,
988
+ execution_time_ms: data.execution_time_ms ?? data.took_ms ?? 0,
989
+ statements_executed: data.statements_executed ?? 0
990
+ };
991
+ }
992
+ /**
993
+ * List all recipe executions across recipes.
994
+ */
995
+ async listExecutions(options = {}) {
996
+ const params = new URLSearchParams();
997
+ if (options.limit) params.append("limit", options.limit.toString());
998
+ if (options.status) params.append("status", options.status);
999
+ const qs = params.toString();
1000
+ const { data } = await this.synapCores._getHttpClient().get(
1001
+ `/recipes/executions${qs ? `?${qs}` : ""}`
1002
+ );
1003
+ const arr = data.executions ?? data ?? [];
1004
+ return arr.map((row) => ({
1005
+ id: row.id ?? row.execution_id ?? "",
1006
+ success: row.success ?? row.status === "completed",
1007
+ results: row.results,
1008
+ error: row.error,
1009
+ execution_time_ms: row.execution_time_ms ?? row.took_ms ?? 0,
1010
+ statements_executed: row.statements_executed ?? 0
1011
+ }));
1012
+ }
1013
+ /**
1014
+ * Get a single execution by ID.
1015
+ */
1016
+ async getExecution(id) {
1017
+ const { data } = await this.synapCores._getHttpClient().get(
1018
+ `/recipes/executions/${id}`
1019
+ );
1020
+ return {
1021
+ id: data.id ?? id,
1022
+ success: data.success ?? data.status === "completed",
1023
+ results: data.results,
1024
+ error: data.error,
1025
+ execution_time_ms: data.execution_time_ms ?? data.took_ms ?? 0,
1026
+ statements_executed: data.statements_executed ?? 0
1027
+ };
858
1028
  }
859
1029
  };
860
1030
 
@@ -864,17 +1034,30 @@ var SchemaClient = class {
864
1034
  this.synapCores = synapCores;
865
1035
  }
866
1036
  /**
867
- * List all tables in the database
1037
+ * List all databases visible to the current authentication context.
1038
+ */
1039
+ async listDatabases() {
1040
+ const { data } = await this.synapCores._getHttpClient().get("/schema/databases");
1041
+ return (data.databases ?? data ?? []).map((db) => ({
1042
+ name: db.name,
1043
+ table_count: db.table_count,
1044
+ size_bytes: db.size_bytes,
1045
+ is_default: db.is_default
1046
+ }));
1047
+ }
1048
+ /**
1049
+ * List all tables in the current database.
868
1050
  */
869
1051
  async listTables(options = {}) {
870
1052
  const params = new URLSearchParams();
871
1053
  if (options.includeSystem) {
872
1054
  params.append("include_system", "true");
873
1055
  }
1056
+ const qs = params.toString();
874
1057
  const { data } = await this.synapCores._getHttpClient().get(
875
- `/schema/tables?${params.toString()}`
1058
+ `/schema/tables${qs ? `?${qs}` : ""}`
876
1059
  );
877
- return (data.tables || data).map((table) => ({
1060
+ return (data.tables || data || []).map((table) => ({
878
1061
  name: table.name,
879
1062
  type: table.type || "table",
880
1063
  column_count: table.column_count || 0,
@@ -886,24 +1069,33 @@ var SchemaClient = class {
886
1069
  }));
887
1070
  }
888
1071
  /**
889
- * Get complete schema for a specific table
1072
+ * Get complete schema for a specific table.
1073
+ *
1074
+ * Combines /schema/tables/:t with /schema/tables/:t/columns and
1075
+ * /schema/tables/:t/indexes side-channels because the table-only payload
1076
+ * does not always include columns and indexes inline.
890
1077
  */
891
1078
  async getTable(tableName) {
892
- const { data } = await this.synapCores._getHttpClient().get(
893
- `/schema/tables/${tableName}`
894
- );
1079
+ const [tableRes, colsRes, idxRes] = await Promise.all([
1080
+ this.synapCores._getHttpClient().get(`/schema/tables/${tableName}`),
1081
+ this.synapCores._getHttpClient().get(`/schema/tables/${tableName}/columns`),
1082
+ this.synapCores._getHttpClient().get(`/schema/tables/${tableName}/indexes`)
1083
+ ]);
1084
+ const table = tableRes.data ?? {};
1085
+ const columns = colsRes.data?.columns ?? colsRes.data ?? [];
1086
+ const indexes = idxRes.data?.indexes ?? idxRes.data ?? [];
895
1087
  return {
896
1088
  table: {
897
- name: data.name,
898
- type: data.type || "table",
899
- column_count: data.columns?.length || 0,
900
- row_count: data.row_count,
901
- size_bytes: data.size_bytes,
902
- created_at: data.created_at ? new Date(data.created_at) : void 0,
903
- updated_at: data.updated_at ? new Date(data.updated_at) : void 0,
904
- comment: data.comment
1089
+ name: table.name ?? tableName,
1090
+ type: table.type || "table",
1091
+ column_count: columns.length,
1092
+ row_count: table.row_count,
1093
+ size_bytes: table.size_bytes,
1094
+ created_at: table.created_at ? new Date(table.created_at) : void 0,
1095
+ updated_at: table.updated_at ? new Date(table.updated_at) : void 0,
1096
+ comment: table.comment
905
1097
  },
906
- columns: (data.columns || []).map((col) => ({
1098
+ columns: columns.map((col) => ({
907
1099
  name: col.name,
908
1100
  data_type: col.data_type || col.type,
909
1101
  nullable: col.nullable !== false,
@@ -915,7 +1107,7 @@ var SchemaClient = class {
915
1107
  comment: col.comment,
916
1108
  ordinal_position: col.ordinal_position || col.position
917
1109
  })),
918
- indexes: (data.indexes || []).map((idx) => ({
1110
+ indexes: indexes.map((idx) => ({
919
1111
  name: idx.name,
920
1112
  table: idx.table || tableName,
921
1113
  type: idx.type || "btree",
@@ -925,8 +1117,8 @@ var SchemaClient = class {
925
1117
  size_bytes: idx.size_bytes,
926
1118
  created_at: idx.created_at ? new Date(idx.created_at) : void 0
927
1119
  })),
928
- constraints: data.constraints || [],
929
- relationships: (data.relationships || []).map((rel) => ({
1120
+ constraints: table.constraints || [],
1121
+ relationships: (table.relationships || []).map((rel) => ({
930
1122
  type: rel.type,
931
1123
  from_table: rel.from_table || rel.source_table,
932
1124
  from_column: rel.from_column || rel.source_column,
@@ -937,106 +1129,186 @@ var SchemaClient = class {
937
1129
  };
938
1130
  }
939
1131
  /**
940
- * Get columns for a specific table
1132
+ * Get columns for a specific table.
941
1133
  */
942
1134
  async getColumns(tableName) {
943
- const schema = await this.getTable(tableName);
944
- return schema.columns;
1135
+ const { data } = await this.synapCores._getHttpClient().get(
1136
+ `/schema/tables/${tableName}/columns`
1137
+ );
1138
+ const cols = data.columns ?? data ?? [];
1139
+ return cols.map((col) => ({
1140
+ name: col.name,
1141
+ data_type: col.data_type || col.type,
1142
+ nullable: col.nullable !== false,
1143
+ default_value: col.default_value || col.default,
1144
+ is_primary_key: col.is_primary_key || col.primary_key,
1145
+ is_unique: col.is_unique || col.unique,
1146
+ is_indexed: col.is_indexed || col.indexed,
1147
+ foreign_key: col.foreign_key,
1148
+ comment: col.comment,
1149
+ ordinal_position: col.ordinal_position || col.position
1150
+ }));
945
1151
  }
946
1152
  /**
947
- * Get indexes for a specific table
1153
+ * Get indexes for a specific table.
948
1154
  */
949
1155
  async getIndexes(tableName) {
950
- const schema = await this.getTable(tableName);
951
- return schema.indexes;
952
- }
953
- /**
954
- * Get all relationships in the database
955
- */
956
- async getRelationships() {
957
- const { data } = await this.synapCores._getHttpClient().get("/schema/relationships");
958
- return (data.relationships || data).map((rel) => ({
959
- type: rel.type,
960
- from_table: rel.from_table || rel.source_table,
961
- from_column: rel.from_column || rel.source_column,
962
- to_table: rel.to_table || rel.target_table,
963
- to_column: rel.to_column || rel.target_column,
964
- name: rel.name
1156
+ const { data } = await this.synapCores._getHttpClient().get(
1157
+ `/schema/tables/${tableName}/indexes`
1158
+ );
1159
+ const idxs = data.indexes ?? data ?? [];
1160
+ return idxs.map((idx) => ({
1161
+ name: idx.name,
1162
+ table: idx.table || tableName,
1163
+ type: idx.type || "btree",
1164
+ columns: idx.columns || [],
1165
+ is_unique: idx.is_unique || idx.unique || false,
1166
+ is_primary: idx.is_primary || idx.primary || false,
1167
+ size_bytes: idx.size_bytes,
1168
+ created_at: idx.created_at ? new Date(idx.created_at) : void 0
965
1169
  }));
966
1170
  }
967
1171
  /**
968
- * Get schema statistics
1172
+ * Preview rows from a table without writing SQL.
1173
+ *
1174
+ * GET /schema/tables/:t/data?limit=&offset=
969
1175
  */
970
- async getStatistics() {
971
- const { data } = await this.synapCores._getHttpClient().get("/schema/statistics");
1176
+ async previewTable(tableName, opts = {}) {
1177
+ const params = new URLSearchParams();
1178
+ if (opts.limit !== void 0) params.append("limit", String(opts.limit));
1179
+ if (opts.offset !== void 0) params.append("offset", String(opts.offset));
1180
+ const qs = params.toString();
1181
+ const { data } = await this.synapCores._getHttpClient().get(
1182
+ `/schema/tables/${tableName}/data${qs ? `?${qs}` : ""}`
1183
+ );
972
1184
  return {
973
- table_count: data.table_count || 0,
974
- view_count: data.view_count || 0,
975
- index_count: data.index_count || 0,
976
- relationship_count: data.relationship_count || 0,
977
- total_size_bytes: data.total_size_bytes || 0,
978
- total_rows: data.total_rows || 0,
979
- version: data.version,
980
- analyzed_at: data.analyzed_at ? new Date(data.analyzed_at) : void 0
1185
+ columns: data.columns ?? [],
1186
+ rows: data.rows ?? data.data ?? [],
1187
+ total_rows: data.total_rows ?? data.total
981
1188
  };
982
1189
  }
983
- /**
984
- * Validate a schema definition
985
- */
986
- async validateSchema(schema) {
987
- const { data } = await this.synapCores._getHttpClient().post("/schema/validate", {
988
- schema
989
- });
990
- return {
991
- is_valid: data.is_valid || data.valid,
992
- errors: data.errors || [],
993
- warnings: data.warnings || []
994
- };
1190
+ };
1191
+
1192
+ // src/errors.ts
1193
+ var SynapCoresError = class _SynapCoresError extends Error {
1194
+ constructor(message, code, details) {
1195
+ super(message);
1196
+ this.name = "SynapCoresError";
1197
+ this.code = code;
1198
+ this.details = details;
1199
+ if (Error.captureStackTrace) {
1200
+ Error.captureStackTrace(this, _SynapCoresError);
1201
+ }
995
1202
  }
996
- /**
997
- * Compare two schemas
998
- */
999
- async compareSchemas(schema1, schema2) {
1000
- const { data } = await this.synapCores._getHttpClient().post("/schema/compare", {
1001
- schema1,
1002
- schema2
1003
- });
1004
- return {
1005
- differences: data.differences || [],
1006
- added: data.added || [],
1007
- removed: data.removed || [],
1008
- modified: data.modified || []
1009
- };
1203
+ };
1204
+ var ConnectionError = class extends SynapCoresError {
1205
+ constructor(message, details) {
1206
+ super(message, "CONNECTION_ERROR", details);
1207
+ this.name = "ConnectionError";
1010
1208
  }
1011
- /**
1012
- * Generate SQL DDL for a table
1013
- */
1014
- async generateDDL(tableName) {
1015
- const { data } = await this.synapCores._getHttpClient().get(
1016
- `/schema/tables/${tableName}/ddl`
1017
- );
1018
- return data.ddl || data.sql;
1209
+ };
1210
+ var AuthenticationError = class extends SynapCoresError {
1211
+ constructor(message, details) {
1212
+ super(message, "AUTH_ERROR", details);
1213
+ this.name = "AuthenticationError";
1019
1214
  }
1020
- /**
1021
- * Analyze table and update statistics
1022
- */
1023
- async analyzeTable(tableName) {
1024
- await this.synapCores._getHttpClient().post(`/schema/tables/${tableName}/analyze`);
1215
+ };
1216
+ var ValidationError = class extends SynapCoresError {
1217
+ constructor(message, details) {
1218
+ super(message, "VALIDATION_ERROR", details);
1219
+ this.name = "ValidationError";
1220
+ }
1221
+ };
1222
+ var NotFoundError = class extends SynapCoresError {
1223
+ constructor(message, details) {
1224
+ super(message, "NOT_FOUND", details);
1225
+ this.name = "NotFoundError";
1226
+ }
1227
+ };
1228
+ var ServerError = class extends SynapCoresError {
1229
+ constructor(message, details) {
1230
+ super(message, "SERVER_ERROR", details);
1231
+ this.name = "ServerError";
1232
+ }
1233
+ };
1234
+ var TimeoutError = class extends SynapCoresError {
1235
+ constructor(message, details) {
1236
+ super(message, "TIMEOUT_ERROR", details);
1237
+ this.name = "TimeoutError";
1238
+ }
1239
+ };
1240
+ var RateLimitError = class extends SynapCoresError {
1241
+ constructor(message, retryAfter, details) {
1242
+ super(message, "RATE_LIMIT_ERROR", details);
1243
+ this.name = "RateLimitError";
1244
+ this.retryAfter = retryAfter;
1245
+ }
1246
+ };
1247
+ var SQLError = class extends SynapCoresError {
1248
+ constructor(message, code, severity = "ERROR", position, hint, detail, details) {
1249
+ super(message, code, details);
1250
+ this.name = "SQLError";
1251
+ this.severity = severity;
1252
+ this.position = position;
1253
+ this.hint = hint;
1254
+ this.detail = detail;
1255
+ }
1256
+ };
1257
+ var VectorError = class extends SynapCoresError {
1258
+ constructor(message, code, vectorDimensions, expectedDimensions, operation, details) {
1259
+ super(message, code, details);
1260
+ this.name = "VectorError";
1261
+ this.vectorDimensions = vectorDimensions;
1262
+ this.expectedDimensions = expectedDimensions;
1263
+ this.operation = operation;
1264
+ }
1265
+ };
1266
+ var TransactionError = class extends SynapCoresError {
1267
+ constructor(message, code, transactionId, transactionState, details) {
1268
+ super(message, code, details);
1269
+ this.name = "TransactionError";
1270
+ this.transactionId = transactionId;
1271
+ this.transactionState = transactionState;
1272
+ }
1273
+ };
1274
+ var BatchOperationError = class extends SynapCoresError {
1275
+ constructor(message, code, failedItems, totalProcessed, successfulCount, details) {
1276
+ super(message, code, details);
1277
+ this.name = "BatchOperationError";
1278
+ this.failedItems = failedItems;
1279
+ this.totalProcessed = totalProcessed;
1280
+ this.successfulCount = successfulCount;
1025
1281
  }
1026
1282
  };
1027
1283
 
1028
1284
  // src/import.ts
1285
+ var NOT_SUPPORTED_MSG = "not supported in v1.5.0-ce \u2014 use SynapCores.executeQuery with COPY ... or process locally";
1029
1286
  var ImportExportClient = class {
1030
1287
  constructor(synapCores) {
1031
1288
  this.synapCores = synapCores;
1032
1289
  }
1033
1290
  /**
1034
- * Import data into a table
1291
+ * Import data into a table.
1292
+ *
1293
+ * Routes to /v1/data/import/csv or /v1/data/import/json based on
1294
+ * `options.format`. NDJSON falls under the JSON endpoint.
1035
1295
  */
1036
1296
  async import(options) {
1037
- const formData = new FormData();
1297
+ const fmt = options.format;
1298
+ if (fmt !== "csv" && fmt !== "json" && fmt !== "ndjson") {
1299
+ throw new ValidationError(
1300
+ `Unsupported import format '${fmt}' \u2014 gateway v1.5.0-ce only accepts csv or json`
1301
+ );
1302
+ }
1303
+ const path = fmt === "csv" ? "/data/import/csv" : "/data/import/json";
1304
+ let FormDataClass;
1305
+ try {
1306
+ FormDataClass = require("form-data");
1307
+ } catch {
1308
+ FormDataClass = globalThis.FormData;
1309
+ }
1310
+ const formData = new FormDataClass();
1038
1311
  formData.append("table", options.table);
1039
- formData.append("format", options.format);
1040
1312
  if (options.mode) formData.append("mode", options.mode);
1041
1313
  if (options.column_mapping) {
1042
1314
  formData.append("column_mapping", JSON.stringify(options.column_mapping));
@@ -1045,7 +1317,9 @@ var ImportExportClient = class {
1045
1317
  formData.append("skip_header", options.skip_header.toString());
1046
1318
  }
1047
1319
  if (options.delimiter) formData.append("delimiter", options.delimiter);
1048
- if (options.batch_size) formData.append("batch_size", options.batch_size.toString());
1320
+ if (options.batch_size) {
1321
+ formData.append("batch_size", options.batch_size.toString());
1322
+ }
1049
1323
  if (options.continue_on_error !== void 0) {
1050
1324
  formData.append("continue_on_error", options.continue_on_error.toString());
1051
1325
  }
@@ -1053,228 +1327,88 @@ var ImportExportClient = class {
1053
1327
  formData.append("primary_keys", JSON.stringify(options.primary_keys));
1054
1328
  }
1055
1329
  if (Buffer.isBuffer(options.data)) {
1056
- formData.append("file", new Blob([options.data]), "data");
1330
+ formData.append("file", options.data, { filename: `data.${fmt}` });
1057
1331
  } else {
1058
- formData.append("data", options.data);
1332
+ formData.append("file", Buffer.from(String(options.data)), {
1333
+ filename: `data.${fmt}`
1334
+ });
1059
1335
  }
1060
- const { data } = await this.synapCores._getHttpClient().post("/import", formData, {
1061
- headers: {
1062
- "Content-Type": "multipart/form-data"
1063
- }
1336
+ const headers = {};
1337
+ if (typeof formData.getHeaders === "function") {
1338
+ Object.assign(headers, formData.getHeaders());
1339
+ } else {
1340
+ headers["Content-Type"] = "multipart/form-data";
1341
+ }
1342
+ const { data } = await this.synapCores._getHttpClient().post(path, formData, {
1343
+ headers,
1344
+ maxBodyLength: Infinity,
1345
+ maxContentLength: Infinity
1064
1346
  });
1065
1347
  return {
1066
- id: data.id || data.job_id,
1067
- success: data.success,
1068
- rows_processed: data.rows_processed || 0,
1069
- rows_imported: data.rows_imported || 0,
1070
- rows_failed: data.rows_failed || 0,
1071
- duration_ms: data.duration_ms || data.took_ms || 0,
1072
- errors: data.errors || [],
1073
- warnings: data.warnings || []
1348
+ id: data.id ?? data.job_id ?? "",
1349
+ success: data.success ?? true,
1350
+ rows_processed: data.rows_processed ?? 0,
1351
+ rows_imported: data.rows_imported ?? data.rows_processed ?? 0,
1352
+ rows_failed: data.rows_failed ?? 0,
1353
+ duration_ms: data.duration_ms ?? data.took_ms ?? 0,
1354
+ errors: data.errors ?? [],
1355
+ warnings: data.warnings ?? []
1074
1356
  };
1075
1357
  }
1076
- /**
1077
- * Export data from a table or query
1078
- */
1079
- async export(options) {
1080
- const { data } = await this.synapCores._getHttpClient().post("/export", {
1081
- source: options.source,
1082
- format: options.format,
1083
- destination: options.destination || "response",
1084
- columns: options.columns,
1085
- filter: options.filter,
1086
- order_by: options.order_by,
1087
- limit: options.limit,
1088
- include_header: options.include_header,
1089
- delimiter: options.delimiter,
1090
- compress: options.compress
1091
- });
1092
- return {
1093
- id: data.id || data.job_id,
1094
- success: data.success,
1095
- rows_exported: data.rows_exported || 0,
1096
- duration_ms: data.duration_ms || data.took_ms || 0,
1097
- file_path: data.file_path,
1098
- data: data.data,
1099
- size_bytes: data.size_bytes,
1100
- download_url: data.download_url,
1101
- expires_at: data.expires_at ? new Date(data.expires_at) : void 0
1102
- };
1358
+ // ---------------------------------------------------------------------
1359
+ // Removed methods: every export route, every job-tracking route, bulk
1360
+ // import, validate, template — none of those endpoints exist in the
1361
+ // v1.5.0-ce gateway. We keep the shape so old callers get a clear error
1362
+ // instead of a silent 404.
1363
+ // ---------------------------------------------------------------------
1364
+ async export(_options) {
1365
+ throw new ValidationError(`export() ${NOT_SUPPORTED_MSG}`);
1103
1366
  }
1104
- /**
1105
- * Get import job status
1106
- */
1107
- async getImportStatus(jobId) {
1108
- const { data } = await this.synapCores._getHttpClient().get(`/import/${jobId}/status`);
1109
- return {
1110
- id: data.id || jobId,
1111
- status: data.status,
1112
- progress: data.progress || 0,
1113
- phase: data.phase,
1114
- rows_processed: data.rows_processed,
1115
- eta_ms: data.eta_ms || data.estimated_time_remaining_ms,
1116
- error: data.error,
1117
- started_at: data.started_at ? new Date(data.started_at) : void 0,
1118
- completed_at: data.completed_at ? new Date(data.completed_at) : void 0
1119
- };
1367
+ async getImportStatus(_jobId) {
1368
+ throw new ValidationError(`getImportStatus() ${NOT_SUPPORTED_MSG}`);
1120
1369
  }
1121
- /**
1122
- * Get export job status
1123
- */
1124
- async getExportStatus(jobId) {
1125
- const { data } = await this.synapCores._getHttpClient().get(`/export/${jobId}/status`);
1126
- return {
1127
- id: data.id || jobId,
1128
- status: data.status,
1129
- progress: data.progress || 0,
1130
- phase: data.phase,
1131
- rows_exported: data.rows_exported,
1132
- eta_ms: data.eta_ms || data.estimated_time_remaining_ms,
1133
- error: data.error,
1134
- started_at: data.started_at ? new Date(data.started_at) : void 0,
1135
- completed_at: data.completed_at ? new Date(data.completed_at) : void 0
1136
- };
1370
+ async getExportStatus(_jobId) {
1371
+ throw new ValidationError(`getExportStatus() ${NOT_SUPPORTED_MSG}`);
1137
1372
  }
1138
- /**
1139
- * Cancel an import job
1140
- */
1141
- async cancelImport(jobId) {
1142
- await this.synapCores._getHttpClient().post(`/import/${jobId}/cancel`);
1373
+ async cancelImport(_jobId) {
1374
+ throw new ValidationError(`cancelImport() ${NOT_SUPPORTED_MSG}`);
1143
1375
  }
1144
- /**
1145
- * Cancel an export job
1146
- */
1147
- async cancelExport(jobId) {
1148
- await this.synapCores._getHttpClient().post(`/export/${jobId}/cancel`);
1376
+ async cancelExport(_jobId) {
1377
+ throw new ValidationError(`cancelExport() ${NOT_SUPPORTED_MSG}`);
1149
1378
  }
1150
- /**
1151
- * Import data from multiple sources in bulk
1152
- */
1153
- async bulkImport(options) {
1154
- const { data } = await this.synapCores._getHttpClient().post("/import/bulk", {
1155
- jobs: options.jobs,
1156
- parallel: options.parallel || false,
1157
- stop_on_error: options.stop_on_error || false
1158
- });
1159
- return {
1160
- id: data.id || data.bulk_id,
1161
- success: data.success,
1162
- results: data.results || [],
1163
- total_rows_imported: data.total_rows_imported || 0,
1164
- total_duration_ms: data.total_duration_ms || data.took_ms || 0
1165
- };
1379
+ async bulkImport(_options) {
1380
+ throw new ValidationError(`bulkImport() ${NOT_SUPPORTED_MSG}`);
1166
1381
  }
1167
- /**
1168
- * Validate data before import
1169
- */
1170
- async validateData(options) {
1171
- const { data } = await this.synapCores._getHttpClient().post("/import/validate", {
1172
- table: options.table,
1173
- data: options.data,
1174
- mode: options.mode || "strict",
1175
- check_foreign_keys: options.check_foreign_keys,
1176
- check_unique: options.check_unique
1177
- });
1178
- return {
1179
- is_valid: data.is_valid || data.valid,
1180
- errors: data.errors || [],
1181
- warnings: data.warnings || [],
1182
- rows_validated: data.rows_validated || options.data.length
1183
- };
1382
+ async validateData(_options) {
1383
+ throw new ValidationError(`validateData() ${NOT_SUPPORTED_MSG}`);
1184
1384
  }
1185
- /**
1186
- * Get import template for a table
1187
- */
1188
- async getImportTemplate(tableName, format = "csv") {
1189
- const { data } = await this.synapCores._getHttpClient().get(
1190
- `/import/template/${tableName}?format=${format}`
1191
- );
1192
- return data.template || data.content || data;
1385
+ async getImportTemplate(_tableName, _format = "csv") {
1386
+ throw new ValidationError(`getImportTemplate() ${NOT_SUPPORTED_MSG}`);
1193
1387
  }
1194
- /**
1195
- * List import/export jobs
1196
- */
1197
- async listJobs(options = {}) {
1198
- const params = new URLSearchParams();
1199
- if (options.type) params.append("type", options.type);
1200
- if (options.status) params.append("status", options.status);
1201
- if (options.limit) params.append("limit", options.limit.toString());
1202
- const { data } = await this.synapCores._getHttpClient().get(
1203
- `/import/jobs?${params.toString()}`
1204
- );
1205
- return (data.jobs || data).map((job) => ({
1206
- id: job.id,
1207
- status: job.status,
1208
- progress: job.progress || 0,
1209
- phase: job.phase,
1210
- rows_processed: job.rows_processed,
1211
- rows_exported: job.rows_exported,
1212
- eta_ms: job.eta_ms,
1213
- error: job.error,
1214
- started_at: job.started_at ? new Date(job.started_at) : void 0,
1215
- completed_at: job.completed_at ? new Date(job.completed_at) : void 0
1216
- }));
1388
+ async listJobs(_options = {}) {
1389
+ throw new ValidationError(`listJobs() ${NOT_SUPPORTED_MSG}`);
1217
1390
  }
1218
- /**
1219
- * Download exported data
1220
- */
1221
- async downloadExport(jobId) {
1222
- const { data } = await this.synapCores._getHttpClient().get(`/export/${jobId}/download`, {
1223
- responseType: "arraybuffer"
1224
- });
1225
- return Buffer.from(data);
1391
+ async downloadExport(_jobId) {
1392
+ throw new ValidationError(`downloadExport() ${NOT_SUPPORTED_MSG}`);
1226
1393
  }
1227
- /**
1228
- * Stream import data (for large files)
1229
- */
1230
- async streamImport(options, onProgress) {
1231
- const result = await this.import(options);
1232
- const jobId = result.id;
1233
- if (onProgress) {
1234
- const pollInterval = setInterval(async () => {
1235
- try {
1236
- const status = await this.getImportStatus(jobId);
1237
- onProgress(status);
1238
- if (status.status === "completed" || status.status === "failed" || status.status === "cancelled") {
1239
- clearInterval(pollInterval);
1240
- }
1241
- } catch (error) {
1242
- clearInterval(pollInterval);
1243
- }
1244
- }, 1e3);
1245
- }
1246
- return result;
1394
+ async streamImport(options, _onProgress) {
1395
+ return this.import(options);
1247
1396
  }
1248
- /**
1249
- * Stream export data (for large datasets)
1250
- */
1251
- async streamExport(options, onProgress) {
1252
- const result = await this.export(options);
1253
- const jobId = result.id;
1254
- if (onProgress) {
1255
- const pollInterval = setInterval(async () => {
1256
- try {
1257
- const status = await this.getExportStatus(jobId);
1258
- onProgress(status);
1259
- if (status.status === "completed" || status.status === "failed" || status.status === "cancelled") {
1260
- clearInterval(pollInterval);
1261
- }
1262
- } catch (error) {
1263
- clearInterval(pollInterval);
1264
- }
1265
- }, 1e3);
1266
- }
1267
- return result;
1397
+ async streamExport(_options, _onProgress) {
1398
+ throw new ValidationError(`streamExport() ${NOT_SUPPORTED_MSG}`);
1268
1399
  }
1269
1400
  };
1270
1401
 
1271
1402
  // src/integrations.ts
1403
+ var NOT_SUPPORTED = "not supported in v1.5.0-ce \u2014 see SynapCores integrations API";
1272
1404
  var IntegrationClient = class {
1273
1405
  constructor(synapCores) {
1274
1406
  this.synapCores = synapCores;
1275
1407
  }
1276
1408
  /**
1277
- * Create a new integration
1409
+ * Create a new integration. Gateway v1.5.0-ce keys integrations by
1410
+ * `type` (slug). The body still carries the type so old call sites
1411
+ * remain backwards compatible.
1278
1412
  */
1279
1413
  async create(options) {
1280
1414
  const { data } = await this.synapCores._getHttpClient().post("/integrations", {
@@ -1288,7 +1422,7 @@ var IntegrationClient = class {
1288
1422
  return this.mapIntegration(data);
1289
1423
  }
1290
1424
  /**
1291
- * List integrations with optional filters
1425
+ * List integrations (optional filters).
1292
1426
  */
1293
1427
  async list(options = {}) {
1294
1428
  const params = new URLSearchParams();
@@ -1300,79 +1434,41 @@ var IntegrationClient = class {
1300
1434
  if (options.tags && options.tags.length > 0) {
1301
1435
  params.append("tags", options.tags.join(","));
1302
1436
  }
1437
+ const qs = params.toString();
1303
1438
  const { data } = await this.synapCores._getHttpClient().get(
1304
- `/integrations?${params.toString()}`
1439
+ `/integrations${qs ? `?${qs}` : ""}`
1305
1440
  );
1306
- return (data.integrations || data).map(
1441
+ return (data.integrations || data || []).map(
1307
1442
  (integration) => this.mapIntegration(integration)
1308
1443
  );
1309
1444
  }
1310
1445
  /**
1311
- * Get a specific integration by ID
1446
+ * Get a specific integration by type-slug.
1312
1447
  */
1313
- async get(id) {
1314
- const { data } = await this.synapCores._getHttpClient().get(`/integrations/${id}`);
1448
+ async get(type) {
1449
+ const { data } = await this.synapCores._getHttpClient().get(
1450
+ `/integrations/${type}`
1451
+ );
1315
1452
  return this.mapIntegration(data);
1316
1453
  }
1317
1454
  /**
1318
- * Update an existing integration
1455
+ * Update an existing integration by type-slug.
1319
1456
  */
1320
- async update(id, updates) {
1457
+ async update(type, updates) {
1321
1458
  const { data } = await this.synapCores._getHttpClient().put(
1322
- `/integrations/${id}`,
1459
+ `/integrations/${type}`,
1323
1460
  updates
1324
1461
  );
1325
1462
  return this.mapIntegration(data);
1326
1463
  }
1327
1464
  /**
1328
- * Delete an integration
1329
- */
1330
- async delete(id) {
1331
- await this.synapCores._getHttpClient().delete(`/integrations/${id}`);
1332
- }
1333
- /**
1334
- * Activate an integration
1335
- */
1336
- async activate(id) {
1337
- const { data } = await this.synapCores._getHttpClient().post(
1338
- `/integrations/${id}/activate`
1339
- );
1340
- return this.mapIntegration(data);
1341
- }
1342
- /**
1343
- * Deactivate an integration
1344
- */
1345
- async deactivate(id) {
1346
- const { data } = await this.synapCores._getHttpClient().post(
1347
- `/integrations/${id}/deactivate`
1348
- );
1349
- return this.mapIntegration(data);
1350
- }
1351
- /**
1352
- * Execute an integration
1465
+ * Delete an integration by type-slug.
1353
1466
  */
1354
- async execute(options) {
1355
- const { data } = await this.synapCores._getHttpClient().post(
1356
- `/integrations/${options.integration}/execute`,
1357
- {
1358
- payload: options.payload,
1359
- config_override: options.config_override,
1360
- sync: options.sync !== false
1361
- }
1362
- );
1363
- return {
1364
- id: data.id || data.execution_id,
1365
- success: data.success,
1366
- response: data.response,
1367
- status_code: data.status_code,
1368
- error: data.error,
1369
- execution_time_ms: data.execution_time_ms || data.took_ms || 0,
1370
- retry_count: data.retry_count || 0,
1371
- executed_at: data.executed_at ? new Date(data.executed_at) : /* @__PURE__ */ new Date()
1372
- };
1467
+ async delete(type) {
1468
+ await this.synapCores._getHttpClient().delete(`/integrations/${type}`);
1373
1469
  }
1374
1470
  /**
1375
- * Test an integration without executing
1471
+ * Test an integration connection.
1376
1472
  */
1377
1473
  async test(options) {
1378
1474
  const { data } = await this.synapCores._getHttpClient().post(
@@ -1391,160 +1487,88 @@ var IntegrationClient = class {
1391
1487
  };
1392
1488
  }
1393
1489
  /**
1394
- * Get integration execution history
1490
+ * List supported integration types and their config schemas.
1395
1491
  */
1396
- async getExecutionHistory(integrationId, options = {}) {
1397
- const params = new URLSearchParams();
1398
- if (options.limit) params.append("limit", options.limit.toString());
1399
- if (options.offset) params.append("offset", options.offset.toString());
1400
- const { data } = await this.synapCores._getHttpClient().get(
1401
- `/integrations/${integrationId}/executions?${params.toString()}`
1402
- );
1403
- return (data.executions || data).map((exec) => ({
1404
- id: exec.id || exec.execution_id,
1405
- success: exec.success,
1406
- response: exec.response,
1407
- status_code: exec.status_code,
1408
- error: exec.error,
1409
- execution_time_ms: exec.execution_time_ms || exec.took_ms || 0,
1410
- retry_count: exec.retry_count || 0,
1411
- executed_at: exec.executed_at ? new Date(exec.executed_at) : /* @__PURE__ */ new Date()
1492
+ async listTypes() {
1493
+ const { data } = await this.synapCores._getHttpClient().get("/integrations/types");
1494
+ return (data.types ?? data ?? []).map((t) => ({
1495
+ type: t.type ?? t.name,
1496
+ display_name: t.display_name ?? t.label,
1497
+ description: t.description,
1498
+ config_schema: t.config_schema ?? t.schema
1412
1499
  }));
1413
1500
  }
1414
1501
  /**
1415
- * Get integration statistics
1502
+ * Get the integrations audit trail.
1416
1503
  */
1417
- async getStats(integrationId) {
1504
+ async audit(options = {}) {
1505
+ const params = new URLSearchParams();
1506
+ if (options.limit) params.append("limit", options.limit.toString());
1507
+ if (options.type) params.append("type", options.type);
1508
+ const qs = params.toString();
1418
1509
  const { data } = await this.synapCores._getHttpClient().get(
1419
- `/integrations/${integrationId}/stats`
1510
+ `/integrations/audit${qs ? `?${qs}` : ""}`
1420
1511
  );
1421
- return {
1422
- integration_id: integrationId,
1423
- total_executions: data.total_executions || 0,
1424
- successful_executions: data.successful_executions || 0,
1425
- failed_executions: data.failed_executions || 0,
1426
- avg_execution_time_ms: data.avg_execution_time_ms || 0,
1427
- executions_24h: data.executions_24h || 0,
1428
- uptime_percentage: data.uptime_percentage || 0,
1429
- last_success_at: data.last_success_at ? new Date(data.last_success_at) : void 0,
1430
- last_error_at: data.last_error_at ? new Date(data.last_error_at) : void 0
1431
- };
1512
+ return (data.entries ?? data.audit ?? data ?? []).map((row) => ({
1513
+ id: row.id,
1514
+ type: row.type ?? row.integration_type,
1515
+ action: row.action ?? row.event,
1516
+ user: row.user ?? row.actor,
1517
+ timestamp: new Date(row.timestamp ?? row.created_at ?? Date.now()),
1518
+ details: row.details ?? row.data
1519
+ }));
1432
1520
  }
1433
- /**
1434
- * Create a webhook for an integration
1435
- */
1436
- async createWebhook(options) {
1437
- const { data } = await this.synapCores._getHttpClient().post("/integrations/webhooks", {
1438
- integration_id: options.integration_id,
1439
- event: options.event,
1440
- url: options.url,
1441
- secret: options.secret,
1442
- activate: options.activate !== false
1443
- });
1444
- return {
1445
- id: data.id,
1446
- integration_id: data.integration_id,
1447
- event: data.event,
1448
- url: data.url,
1449
- active: data.active,
1450
- secret: data.secret,
1451
- created_at: new Date(data.created_at)
1452
- };
1521
+ // -------------------------------------------------------------------
1522
+ // Methods removed from v1.5.0-ce (gateway has no matching route).
1523
+ // We keep the names for backwards-compat but throw a clear error.
1524
+ // -------------------------------------------------------------------
1525
+ async activate(_type) {
1526
+ throw new ValidationError(`integrations.activate() ${NOT_SUPPORTED} \u2014 use update() with {activate:true}`);
1453
1527
  }
1454
- /**
1455
- * List webhooks for an integration
1456
- */
1457
- async listWebhooks(integrationId) {
1458
- const { data } = await this.synapCores._getHttpClient().get(
1459
- `/integrations/${integrationId}/webhooks`
1460
- );
1461
- return (data.webhooks || data).map((webhook) => ({
1462
- id: webhook.id,
1463
- integration_id: webhook.integration_id,
1464
- event: webhook.event,
1465
- url: webhook.url,
1466
- active: webhook.active,
1467
- secret: webhook.secret,
1468
- created_at: new Date(webhook.created_at)
1469
- }));
1528
+ async deactivate(_type) {
1529
+ throw new ValidationError(`integrations.deactivate() ${NOT_SUPPORTED} \u2014 use update() with {activate:false}`);
1470
1530
  }
1471
- /**
1472
- * Delete a webhook
1473
- */
1474
- async deleteWebhook(webhookId) {
1475
- await this.synapCores._getHttpClient().delete(`/integrations/webhooks/${webhookId}`);
1531
+ async execute(_options) {
1532
+ throw new ValidationError(`integrations.execute() ${NOT_SUPPORTED}`);
1476
1533
  }
1477
- /**
1478
- * Get integration events
1479
- */
1480
- async getEvents(integrationId, options = {}) {
1481
- const params = new URLSearchParams();
1482
- if (options.limit) params.append("limit", options.limit.toString());
1483
- if (options.status) params.append("status", options.status);
1484
- const { data } = await this.synapCores._getHttpClient().get(
1485
- `/integrations/${integrationId}/events?${params.toString()}`
1486
- );
1487
- return (data.events || data).map((event) => ({
1488
- id: event.id,
1489
- integration_id: event.integration_id,
1490
- event: event.event,
1491
- data: event.data,
1492
- timestamp: new Date(event.timestamp),
1493
- status: event.status,
1494
- error: event.error
1495
- }));
1534
+ async getExecutionHistory(_type, _options = {}) {
1535
+ throw new ValidationError(`integrations.getExecutionHistory() ${NOT_SUPPORTED}`);
1496
1536
  }
1497
- /**
1498
- * Get integration logs
1499
- */
1500
- async getLogs(integrationId, options = {}) {
1501
- const params = new URLSearchParams();
1502
- if (options.limit) params.append("limit", options.limit.toString());
1503
- if (options.level) params.append("level", options.level);
1504
- const { data } = await this.synapCores._getHttpClient().get(
1505
- `/integrations/${integrationId}/logs?${params.toString()}`
1506
- );
1507
- return (data.logs || data).map((log) => ({
1508
- id: log.id,
1509
- integration_id: log.integration_id,
1510
- level: log.level,
1511
- message: log.message,
1512
- data: log.data,
1513
- timestamp: new Date(log.timestamp)
1514
- }));
1537
+ async getStats(_type) {
1538
+ throw new ValidationError(`integrations.getStats() ${NOT_SUPPORTED}`);
1515
1539
  }
1516
- /**
1517
- * Retry a failed execution
1518
- */
1519
- async retryExecution(executionId) {
1520
- const { data } = await this.synapCores._getHttpClient().post(
1521
- `/integrations/executions/${executionId}/retry`
1522
- );
1523
- return {
1524
- id: data.id || data.execution_id,
1525
- success: data.success,
1526
- response: data.response,
1527
- status_code: data.status_code,
1528
- error: data.error,
1529
- execution_time_ms: data.execution_time_ms || data.took_ms || 0,
1530
- retry_count: data.retry_count || 0,
1531
- executed_at: data.executed_at ? new Date(data.executed_at) : /* @__PURE__ */ new Date()
1532
- };
1540
+ async createWebhook(_options) {
1541
+ throw new ValidationError(`integrations.createWebhook() ${NOT_SUPPORTED}`);
1542
+ }
1543
+ async listWebhooks(_type) {
1544
+ throw new ValidationError(`integrations.listWebhooks() ${NOT_SUPPORTED}`);
1545
+ }
1546
+ async deleteWebhook(_webhookId) {
1547
+ throw new ValidationError(`integrations.deleteWebhook() ${NOT_SUPPORTED}`);
1548
+ }
1549
+ async getEvents(_type, _options = {}) {
1550
+ throw new ValidationError(`integrations.getEvents() ${NOT_SUPPORTED}`);
1551
+ }
1552
+ async getLogs(_type, _options = {}) {
1553
+ throw new ValidationError(`integrations.getLogs() ${NOT_SUPPORTED}`);
1554
+ }
1555
+ async retryExecution(_executionId) {
1556
+ throw new ValidationError(`integrations.retryExecution() ${NOT_SUPPORTED}`);
1533
1557
  }
1534
1558
  /**
1535
- * Map raw integration data to Integration type
1559
+ * Map raw integration data to Integration type.
1536
1560
  */
1537
1561
  mapIntegration(data) {
1538
1562
  return {
1539
- id: data.id,
1540
- name: data.name,
1563
+ id: data.id ?? data.type,
1564
+ name: data.name ?? data.type,
1541
1565
  type: data.type,
1542
- status: data.status,
1543
- config: data.config,
1566
+ status: data.status ?? (data.active ? "active" : "inactive"),
1567
+ config: data.config ?? {},
1544
1568
  description: data.description,
1545
1569
  tags: data.tags || [],
1546
- created_at: new Date(data.created_at),
1547
- updated_at: new Date(data.updated_at),
1570
+ created_at: new Date(data.created_at ?? Date.now()),
1571
+ updated_at: new Date(data.updated_at ?? data.created_at ?? Date.now()),
1548
1572
  last_success_at: data.last_success_at ? new Date(data.last_success_at) : void 0,
1549
1573
  last_error: data.last_error,
1550
1574
  execution_count: data.execution_count
@@ -1677,18 +1701,9 @@ var BackupClient = class {
1677
1701
  completed_at: data.completed_at ? new Date(data.completed_at) : void 0
1678
1702
  };
1679
1703
  }
1680
- /**
1681
- * Cancel a backup in progress
1682
- */
1683
- async cancelBackup(backupId) {
1684
- await this.synapCores._getHttpClient().post(`/backups/${backupId}/cancel`);
1685
- }
1686
- /**
1687
- * Cancel a restore in progress
1688
- */
1689
- async cancelRestore(restoreId) {
1690
- await this.synapCores._getHttpClient().post(`/backups/restore/${restoreId}/cancel`);
1691
- }
1704
+ // cancelBackup() / cancelRestore() removed — gateway v1.5.0-ce has no
1705
+ // /backups/:id/cancel or /backups/restore/:id/cancel routes. Use
1706
+ // delete() to clean up an aborted backup record.
1692
1707
  /**
1693
1708
  * Download a backup file
1694
1709
  */
@@ -1823,155 +1838,972 @@ var BackupClient = class {
1823
1838
  };
1824
1839
  }
1825
1840
  /**
1826
- * Deactivate a schedule
1841
+ * Deactivate a schedule
1842
+ */
1843
+ async deactivateSchedule(scheduleId) {
1844
+ const { data } = await this.synapCores._getHttpClient().post(
1845
+ `/backups/schedules/${scheduleId}/deactivate`
1846
+ );
1847
+ return {
1848
+ id: data.id,
1849
+ name: data.name,
1850
+ cron: data.cron,
1851
+ backup_options: data.backup_options,
1852
+ active: data.active,
1853
+ last_run_at: data.last_run_at ? new Date(data.last_run_at) : void 0,
1854
+ next_run_at: data.next_run_at ? new Date(data.next_run_at) : void 0,
1855
+ created_at: new Date(data.created_at),
1856
+ tags: data.tags || []
1857
+ };
1858
+ }
1859
+ // getMetrics() removed — gateway v1.5.0-ce has no /backups/metrics route.
1860
+ // Aggregate metrics can be derived client-side from list().
1861
+ /**
1862
+ * Map raw backup data to Backup type
1863
+ */
1864
+ mapBackup(data) {
1865
+ return {
1866
+ id: data.id,
1867
+ name: data.name,
1868
+ description: data.description,
1869
+ type: data.type,
1870
+ status: data.status,
1871
+ size_bytes: data.size_bytes,
1872
+ compressed_size_bytes: data.compressed_size_bytes,
1873
+ table_count: data.table_count,
1874
+ created_at: new Date(data.created_at),
1875
+ completed_at: data.completed_at ? new Date(data.completed_at) : void 0,
1876
+ duration_ms: data.duration_ms || data.took_ms,
1877
+ storage: data.storage,
1878
+ storage_path: data.storage_path,
1879
+ encrypted: data.encrypted || false,
1880
+ tags: data.tags || [],
1881
+ parent_backup_id: data.parent_backup_id,
1882
+ error: data.error
1883
+ };
1884
+ }
1885
+ };
1886
+
1887
+ // src/graph.ts
1888
+ var GraphNodeApi = class {
1889
+ constructor(synapCores) {
1890
+ this.synapCores = synapCores;
1891
+ }
1892
+ async create(label, props = {}) {
1893
+ const { data } = await this.synapCores._getHttpClient().post("/graph/nodes", {
1894
+ label,
1895
+ properties: props
1896
+ });
1897
+ return this.normalize(data);
1898
+ }
1899
+ async get(id) {
1900
+ const { data } = await this.synapCores._getHttpClient().get(`/graph/nodes/${id}`);
1901
+ return this.normalize(data);
1902
+ }
1903
+ async update(id, patch) {
1904
+ const { data } = await this.synapCores._getHttpClient().patch(
1905
+ `/graph/nodes/${id}`,
1906
+ { properties: patch }
1907
+ );
1908
+ return this.normalize(data);
1909
+ }
1910
+ async delete(id) {
1911
+ await this.synapCores._getHttpClient().delete(`/graph/nodes/${id}`);
1912
+ }
1913
+ async neighbors(id, opts = {}) {
1914
+ const params = new URLSearchParams();
1915
+ if (opts.direction) params.append("direction", opts.direction);
1916
+ if (opts.limit !== void 0) params.append("limit", String(opts.limit));
1917
+ if (opts.type) params.append("type", opts.type);
1918
+ const qs = params.toString();
1919
+ const { data } = await this.synapCores._getHttpClient().get(
1920
+ `/graph/nodes/${id}/neighbors${qs ? `?${qs}` : ""}`
1921
+ );
1922
+ return {
1923
+ nodes: (data.nodes ?? []).map((n) => this.normalize(n)),
1924
+ edges: (data.edges ?? []).map((e) => this.normalizeEdge(e))
1925
+ };
1926
+ }
1927
+ normalize(data) {
1928
+ return {
1929
+ id: String(data.id ?? data.node_id ?? ""),
1930
+ label: data.label,
1931
+ labels: data.labels,
1932
+ properties: data.properties ?? data.props ?? {}
1933
+ };
1934
+ }
1935
+ normalizeEdge(data) {
1936
+ return {
1937
+ id: data.id !== void 0 ? String(data.id) : void 0,
1938
+ from: String(data.from ?? data.source ?? ""),
1939
+ to: String(data.to ?? data.target ?? ""),
1940
+ type: data.type ?? data.label ?? "",
1941
+ properties: data.properties ?? data.props ?? {}
1942
+ };
1943
+ }
1944
+ };
1945
+ var GraphEdgeApi = class {
1946
+ constructor(synapCores) {
1947
+ this.synapCores = synapCores;
1948
+ }
1949
+ async create(from, to, type, props = {}) {
1950
+ const { data } = await this.synapCores._getHttpClient().post("/graph/edges", {
1951
+ from,
1952
+ to,
1953
+ type,
1954
+ properties: props
1955
+ });
1956
+ return {
1957
+ id: data.id !== void 0 ? String(data.id) : void 0,
1958
+ from: String(data.from ?? from),
1959
+ to: String(data.to ?? to),
1960
+ type: data.type ?? type,
1961
+ properties: data.properties ?? props
1962
+ };
1963
+ }
1964
+ };
1965
+ var GraphIndexesApi = class {
1966
+ constructor(synapCores) {
1967
+ this.synapCores = synapCores;
1968
+ }
1969
+ /**
1970
+ * Create a graph index (label/property index, fulltext, or vector
1971
+ * depending on the gateway's accepted DDL strings).
1972
+ */
1973
+ async create(stmt) {
1974
+ const { data } = await this.synapCores._getHttpClient().post("/graph/indexes", {
1975
+ statement: stmt
1976
+ });
1977
+ return { name: data.name ?? data.index_name, raw: data };
1978
+ }
1979
+ };
1980
+ var GraphAlgorithmsApi = class {
1981
+ constructor(synapCores) {
1982
+ this.synapCores = synapCores;
1983
+ }
1984
+ async run(name, opts = {}) {
1985
+ const { data } = await this.synapCores._getHttpClient().post("/graph/algorithms", {
1986
+ algorithm: name,
1987
+ ...opts
1988
+ });
1989
+ return {
1990
+ algorithm: name,
1991
+ results: data.results ?? data.result ?? data,
1992
+ stats: data.stats,
1993
+ execution_time_ms: data.execution_time_ms ?? data.took_ms
1994
+ };
1995
+ }
1996
+ };
1997
+ var GraphsApi = class {
1998
+ constructor(synapCores) {
1999
+ this.synapCores = synapCores;
2000
+ }
2001
+ async list() {
2002
+ const { data } = await this.synapCores._getHttpClient().get("/graphs");
2003
+ return (data.graphs ?? data ?? []).map((g) => this.normalize(g));
2004
+ }
2005
+ async create(name, opts = {}) {
2006
+ const { data } = await this.synapCores._getHttpClient().post("/graphs", {
2007
+ name,
2008
+ description: opts.description
2009
+ });
2010
+ return this.normalize(data);
2011
+ }
2012
+ async get(name) {
2013
+ const { data } = await this.synapCores._getHttpClient().get(`/graphs/${name}`);
2014
+ return this.normalize(data);
2015
+ }
2016
+ async delete(name) {
2017
+ await this.synapCores._getHttpClient().delete(`/graphs/${name}`);
2018
+ }
2019
+ normalize(data) {
2020
+ return {
2021
+ name: data.name,
2022
+ node_count: data.node_count ?? data.nodes,
2023
+ edge_count: data.edge_count ?? data.edges,
2024
+ created_at: data.created_at ? new Date(data.created_at) : void 0,
2025
+ description: data.description
2026
+ };
2027
+ }
2028
+ };
2029
+ var GraphClient = class {
2030
+ constructor(synapCores) {
2031
+ this.synapCores = synapCores;
2032
+ this.nodes = new GraphNodeApi(synapCores);
2033
+ this.edges = new GraphEdgeApi(synapCores);
2034
+ this.indexes = new GraphIndexesApi(synapCores);
2035
+ this.algorithms = new GraphAlgorithmsApi(synapCores);
2036
+ this.graphs = new GraphsApi(synapCores);
2037
+ }
2038
+ /**
2039
+ * Run a Cypher / MATCH query.
2040
+ *
2041
+ * The gateway's MatchRequest expects `sql: String` (see
2042
+ * crates/aidb-gateway/src/routes/graph.rs MatchRequest); we keep the
2043
+ * SDK-facing parameter named `query` because every caller writes
2044
+ * Cypher, not SQL — the gateway's field name is a historical artifact.
2045
+ */
2046
+ async cypher(query, params = {}, graph) {
2047
+ const { data } = await this.synapCores._getHttpClient().post("/graph/match", {
2048
+ sql: query,
2049
+ params,
2050
+ graph
2051
+ });
2052
+ return this.normalizeCypher(data);
2053
+ }
2054
+ /**
2055
+ * Profile a Cypher / MATCH query (returns plan/profile metadata).
2056
+ */
2057
+ async cypherProfile(query, params = {}, graph) {
2058
+ const { data } = await this.synapCores._getHttpClient().post("/graph/match/profile", {
2059
+ sql: query,
2060
+ params,
2061
+ graph
2062
+ });
2063
+ return {
2064
+ ...this.normalizeCypher(data),
2065
+ plan: data.plan,
2066
+ profile: data.profile ?? data.profile_data
2067
+ };
2068
+ }
2069
+ /**
2070
+ * Run LLM-based extraction over text into the given graph.
2071
+ */
2072
+ async extract(req, graphName) {
2073
+ const body = typeof req === "string" ? { text: req, graph: graphName } : req;
2074
+ const { data } = await this.synapCores._getHttpClient().post("/graph/extract", body);
2075
+ return {
2076
+ nodes: (data.nodes ?? []).map((n) => ({
2077
+ id: String(n.id ?? ""),
2078
+ label: n.label,
2079
+ labels: n.labels,
2080
+ properties: n.properties ?? n.props ?? {}
2081
+ })),
2082
+ edges: (data.edges ?? []).map((e) => ({
2083
+ id: e.id !== void 0 ? String(e.id) : void 0,
2084
+ from: String(e.from ?? e.source ?? ""),
2085
+ to: String(e.to ?? e.target ?? ""),
2086
+ type: e.type ?? e.label ?? "",
2087
+ properties: e.properties ?? e.props ?? {}
2088
+ })),
2089
+ spans: data.spans
2090
+ };
2091
+ }
2092
+ normalizeCypher(data) {
2093
+ return {
2094
+ columns: data.columns ?? data.fields,
2095
+ rows: data.rows ?? data.values ?? [],
2096
+ records: data.records ?? data.results,
2097
+ stats: data.stats,
2098
+ execution_time_ms: data.execution_time_ms ?? data.took_ms
2099
+ };
2100
+ }
2101
+ };
2102
+
2103
+ // src/nl2sql.ts
2104
+ var NL2SqlClient = class {
2105
+ constructor(synapCores) {
2106
+ this.synapCores = synapCores;
2107
+ }
2108
+ /**
2109
+ * Ask a question in natural language. The gateway returns the
2110
+ * generated SQL and optionally the executed result set when
2111
+ * `execute=true`.
2112
+ */
2113
+ async ask(question, opts = {}) {
2114
+ const { data } = await this.synapCores._getHttpClient().post("/nl2sql/query", {
2115
+ question,
2116
+ ...opts
2117
+ });
2118
+ return {
2119
+ sql: data.sql ?? data.generated_sql ?? "",
2120
+ confidence: data.confidence,
2121
+ rows: data.rows ?? data.data,
2122
+ columns: data.columns,
2123
+ execution_time_ms: data.execution_time_ms ?? data.took_ms,
2124
+ trace: data.trace ?? data.plan,
2125
+ question
2126
+ };
2127
+ }
2128
+ /**
2129
+ * Push schema context the model should use for subsequent ask() calls.
2130
+ */
2131
+ async updateSchemaContext(payload) {
2132
+ const { data } = await this.synapCores._getHttpClient().post(
2133
+ "/nl2sql/schema/context",
2134
+ payload
2135
+ );
2136
+ return { accepted: data.accepted ?? data.success ?? true, raw: data };
2137
+ }
2138
+ /**
2139
+ * Retrieve recent NL2SQL history for the current authenticated user.
2140
+ */
2141
+ async history(opts = {}) {
2142
+ const params = new URLSearchParams();
2143
+ if (opts.limit) params.append("limit", String(opts.limit));
2144
+ if (opts.session_id) params.append("session_id", opts.session_id);
2145
+ const qs = params.toString();
2146
+ const { data } = await this.synapCores._getHttpClient().get(
2147
+ `/nl2sql/history${qs ? `?${qs}` : ""}`
2148
+ );
2149
+ return (data.history ?? data.entries ?? data ?? []).map((row) => ({
2150
+ id: String(row.id ?? row.entry_id ?? ""),
2151
+ question: row.question ?? row.prompt ?? "",
2152
+ sql: row.sql ?? row.generated_sql ?? "",
2153
+ created_at: new Date(row.created_at ?? row.timestamp ?? Date.now()),
2154
+ executed: row.executed,
2155
+ success: row.success
2156
+ }));
2157
+ }
2158
+ /**
2159
+ * Validate a SQL string against the current schema and policies.
2160
+ */
2161
+ async validate(sql) {
2162
+ const { data } = await this.synapCores._getHttpClient().post("/nl2sql/validate", {
2163
+ sql
2164
+ });
2165
+ return {
2166
+ is_valid: data.is_valid ?? data.valid ?? false,
2167
+ errors: data.errors ?? [],
2168
+ warnings: data.warnings ?? [],
2169
+ rewritten_sql: data.rewritten_sql ?? data.sql
2170
+ };
2171
+ }
2172
+ };
2173
+
2174
+ // src/filesystem.ts
2175
+ var import_ws2 = __toESM(require("ws"));
2176
+ var FsCollectionsApi = class {
2177
+ constructor(synapCores) {
2178
+ this.synapCores = synapCores;
2179
+ }
2180
+ async create(opts) {
2181
+ const { data } = await this.synapCores._getHttpClient().post(
2182
+ "/filesystem-collections",
2183
+ opts
2184
+ );
2185
+ return this.normalize(data);
2186
+ }
2187
+ async list() {
2188
+ const { data } = await this.synapCores._getHttpClient().get("/filesystem-collections");
2189
+ return (data.collections ?? data ?? []).map((c) => this.normalize(c));
2190
+ }
2191
+ async get(id) {
2192
+ const { data } = await this.synapCores._getHttpClient().get(
2193
+ `/filesystem-collections/${id}`
2194
+ );
2195
+ return this.normalize(data);
2196
+ }
2197
+ async patch(id, p) {
2198
+ const { data } = await this.synapCores._getHttpClient().patch(
2199
+ `/filesystem-collections/${id}`,
2200
+ p
2201
+ );
2202
+ return this.normalize(data);
2203
+ }
2204
+ async delete(id) {
2205
+ await this.synapCores._getHttpClient().delete(`/filesystem-collections/${id}`);
2206
+ }
2207
+ async documents(id, opts = {}) {
2208
+ const params = new URLSearchParams();
2209
+ if (opts.page) params.append("page", String(opts.page));
2210
+ if (opts.page_size) params.append("page_size", String(opts.page_size));
2211
+ const qs = params.toString();
2212
+ const { data } = await this.synapCores._getHttpClient().get(
2213
+ `/filesystem-collections/${id}/documents${qs ? `?${qs}` : ""}`
2214
+ );
2215
+ return (data.documents ?? data ?? []).map((d) => ({
2216
+ id: String(d.id ?? d.document_id ?? ""),
2217
+ collection_id: d.collection_id !== void 0 ? String(d.collection_id) : id,
2218
+ filename: d.filename ?? d.name,
2219
+ path: d.path,
2220
+ status: d.status,
2221
+ size_bytes: d.size_bytes,
2222
+ created_at: d.created_at ? new Date(d.created_at) : void 0,
2223
+ updated_at: d.updated_at ? new Date(d.updated_at) : void 0
2224
+ }));
2225
+ }
2226
+ async reprocess(id, fileId) {
2227
+ const body = fileId ? { document_id: fileId } : {};
2228
+ const { data } = await this.synapCores._getHttpClient().post(
2229
+ `/filesystem-collections/${id}/reprocess`,
2230
+ body
2231
+ );
2232
+ return { accepted: data.accepted ?? data.success ?? true, raw: data };
2233
+ }
2234
+ /**
2235
+ * Stream progress events for an in-flight ingestion. Each tick maps to
2236
+ * a JSON payload broadcast by the gateway over the WS channel. The
2237
+ * iterator ends when the server closes the socket or the consumer
2238
+ * breaks out of the for-await loop.
2239
+ */
2240
+ async *subscribeProgress(id, opts = {}) {
2241
+ const { token } = await this.synapCores.createWsTicket();
2242
+ const wsBase = this.synapCores._getWsBaseUrl();
2243
+ const url = `${wsBase}/ws/filesystem-collections/${id}/progress?token=${encodeURIComponent(token)}`;
2244
+ const ws = new import_ws2.default(url);
2245
+ const queue = [];
2246
+ let resolver = null;
2247
+ const push = (p) => {
2248
+ if (resolver) {
2249
+ const r = resolver;
2250
+ resolver = null;
2251
+ r(p);
2252
+ } else {
2253
+ queue.push(p);
2254
+ }
2255
+ };
2256
+ ws.on("message", (raw) => {
2257
+ try {
2258
+ const obj = JSON.parse(raw.toString());
2259
+ push({
2260
+ kind: "value",
2261
+ value: {
2262
+ type: obj.type ?? obj.event ?? "progress",
2263
+ collection_id: obj.collection_id !== void 0 ? String(obj.collection_id) : id,
2264
+ document_id: obj.document_id !== void 0 ? String(obj.document_id) : void 0,
2265
+ filename: obj.filename ?? obj.path,
2266
+ status: obj.status,
2267
+ progress: obj.progress,
2268
+ message: obj.message,
2269
+ error: obj.error,
2270
+ timestamp: obj.timestamp ? new Date(obj.timestamp) : void 0,
2271
+ raw: obj
2272
+ }
2273
+ });
2274
+ } catch (e) {
2275
+ push({ kind: "error", error: e });
2276
+ }
2277
+ });
2278
+ ws.on("error", (err) => push({ kind: "error", error: err }));
2279
+ ws.on("close", () => push({ kind: "done" }));
2280
+ const onAbort = () => {
2281
+ try {
2282
+ ws.close();
2283
+ } catch {
2284
+ }
2285
+ };
2286
+ if (opts.signal) {
2287
+ if (opts.signal.aborted) onAbort();
2288
+ else opts.signal.addEventListener("abort", onAbort);
2289
+ }
2290
+ try {
2291
+ while (true) {
2292
+ const next = await new Promise((resolve) => {
2293
+ if (queue.length > 0) {
2294
+ resolve(queue.shift());
2295
+ } else {
2296
+ resolver = resolve;
2297
+ }
2298
+ });
2299
+ if (next.kind === "value") yield next.value;
2300
+ else if (next.kind === "error") throw next.error;
2301
+ else return;
2302
+ }
2303
+ } finally {
2304
+ try {
2305
+ ws.close();
2306
+ } catch {
2307
+ }
2308
+ if (opts.signal) opts.signal.removeEventListener("abort", onAbort);
2309
+ }
2310
+ }
2311
+ normalize(data) {
2312
+ return {
2313
+ id: String(data.id ?? data.collection_id ?? ""),
2314
+ name: data.name,
2315
+ description: data.description,
2316
+ path: data.path,
2317
+ status: data.status,
2318
+ document_count: data.document_count ?? data.documents,
2319
+ created_at: data.created_at ? new Date(data.created_at) : void 0,
2320
+ updated_at: data.updated_at ? new Date(data.updated_at) : void 0,
2321
+ config: data.config
2322
+ };
2323
+ }
2324
+ };
2325
+ var FilesystemCollectionsClient = class {
2326
+ constructor(synapCores) {
2327
+ this.collections = new FsCollectionsApi(synapCores);
2328
+ }
2329
+ };
2330
+
2331
+ // src/chat.ts
2332
+ var ChatSessionsApi = class {
2333
+ constructor(synapCores) {
2334
+ this.synapCores = synapCores;
2335
+ }
2336
+ async create(opts = {}) {
2337
+ const { data } = await this.synapCores._getHttpClient().post("/ai/sessions", opts);
2338
+ return this.normalize(data);
2339
+ }
2340
+ async list(opts = {}) {
2341
+ const params = new URLSearchParams();
2342
+ if (opts.limit) params.append("limit", String(opts.limit));
2343
+ if (opts.offset) params.append("offset", String(opts.offset));
2344
+ const qs = params.toString();
2345
+ const { data } = await this.synapCores._getHttpClient().get(
2346
+ `/ai/sessions${qs ? `?${qs}` : ""}`
2347
+ );
2348
+ return (data.sessions ?? data ?? []).map((s) => this.normalize(s));
2349
+ }
2350
+ async get(id) {
2351
+ const { data } = await this.synapCores._getHttpClient().get(`/ai/sessions/${id}`);
2352
+ return this.normalize(data);
2353
+ }
2354
+ async delete(id) {
2355
+ await this.synapCores._getHttpClient().delete(`/ai/sessions/${id}`);
2356
+ }
2357
+ async messages(id, opts = {}) {
2358
+ const params = new URLSearchParams();
2359
+ if (opts.limit) params.append("limit", String(opts.limit));
2360
+ if (opts.offset) params.append("offset", String(opts.offset));
2361
+ const qs = params.toString();
2362
+ const { data } = await this.synapCores._getHttpClient().get(
2363
+ `/ai/sessions/${id}/messages${qs ? `?${qs}` : ""}`
2364
+ );
2365
+ return (data.messages ?? data ?? []).map((m) => this.normalizeMessage(m, id));
2366
+ }
2367
+ normalize(data) {
2368
+ return {
2369
+ id: String(data.id ?? data.session_id ?? ""),
2370
+ title: data.title,
2371
+ model: data.model,
2372
+ system_prompt: data.system_prompt,
2373
+ created_at: new Date(data.created_at ?? Date.now()),
2374
+ updated_at: data.updated_at ? new Date(data.updated_at) : void 0,
2375
+ message_count: data.message_count ?? data.messages,
2376
+ metadata: data.metadata
2377
+ };
2378
+ }
2379
+ normalizeMessage(m, sessionId) {
2380
+ return {
2381
+ id: String(m.id ?? m.message_id ?? ""),
2382
+ session_id: m.session_id !== void 0 ? String(m.session_id) : sessionId,
2383
+ role: m.role,
2384
+ content: m.content ?? m.text ?? "",
2385
+ created_at: new Date(m.created_at ?? Date.now()),
2386
+ metadata: m.metadata
2387
+ };
2388
+ }
2389
+ };
2390
+ var ChatToolsApi = class {
2391
+ constructor(synapCores) {
2392
+ this.synapCores = synapCores;
2393
+ }
2394
+ async list() {
2395
+ const { data } = await this.synapCores._getHttpClient().get("/ai/tools");
2396
+ return (data.tools ?? data ?? []).map((t) => ({
2397
+ name: t.name,
2398
+ description: t.description,
2399
+ parameters: t.parameters ?? t.schema
2400
+ }));
2401
+ }
2402
+ async execute(name, args = {}) {
2403
+ const { data } = await this.synapCores._getHttpClient().post("/ai/tools/execute", {
2404
+ tool: name,
2405
+ arguments: args
2406
+ });
2407
+ return data;
2408
+ }
2409
+ async sql(sql, params = []) {
2410
+ const { data } = await this.synapCores._getHttpClient().post("/ai/tools/sql", {
2411
+ sql,
2412
+ parameters: params
2413
+ });
2414
+ return data;
2415
+ }
2416
+ };
2417
+ var ChatCacheApi = class {
2418
+ constructor(synapCores) {
2419
+ this.synapCores = synapCores;
2420
+ }
2421
+ async stats() {
2422
+ const { data } = await this.synapCores._getHttpClient().get("/ai/cache/stats");
2423
+ return {
2424
+ size_bytes: data.size_bytes ?? data.bytes,
2425
+ hit_count: data.hit_count ?? data.hits,
2426
+ miss_count: data.miss_count ?? data.misses,
2427
+ entries: data.entries ?? data.count,
2428
+ raw: data
2429
+ };
2430
+ }
2431
+ async clear() {
2432
+ await this.synapCores._getHttpClient().post("/ai/cache/clear", {});
2433
+ }
2434
+ };
2435
+ var ChatClient = class {
2436
+ constructor(synapCores) {
2437
+ this.synapCores = synapCores;
2438
+ this.sessions = new ChatSessionsApi(synapCores);
2439
+ this.tools = new ChatToolsApi(synapCores);
2440
+ this.cache = new ChatCacheApi(synapCores);
2441
+ }
2442
+ /**
2443
+ * Send a one-shot chat message. The gateway accepts both /ai/chat and
2444
+ * the alias /ai/ — we use /ai/chat for clarity.
2445
+ */
2446
+ async send(sessionId, content, opts = {}) {
2447
+ const { data } = await this.synapCores._getHttpClient().post("/ai/chat", {
2448
+ session_id: sessionId,
2449
+ content,
2450
+ ...opts
2451
+ });
2452
+ const messageData = data.message ?? data;
2453
+ return {
2454
+ message: {
2455
+ id: String(messageData.id ?? messageData.message_id ?? ""),
2456
+ session_id: sessionId,
2457
+ role: messageData.role ?? "assistant",
2458
+ content: messageData.content ?? messageData.text ?? "",
2459
+ created_at: new Date(messageData.created_at ?? Date.now()),
2460
+ metadata: messageData.metadata
2461
+ },
2462
+ tool_calls: data.tool_calls,
2463
+ usage: data.usage
2464
+ };
2465
+ }
2466
+ /**
2467
+ * Stream a chat completion. Returns an async iterator over SSE chunks.
2468
+ */
2469
+ async *stream(sessionId, content, opts = {}) {
2470
+ const http = this.synapCores._getHttpClient();
2471
+ const response = await http.post(
2472
+ "/ai/chat/stream",
2473
+ {
2474
+ session_id: sessionId,
2475
+ content,
2476
+ ...opts
2477
+ },
2478
+ { responseType: "stream" }
2479
+ );
2480
+ const stream = response.data;
2481
+ let buffer = "";
2482
+ for await (const chunk of stream) {
2483
+ buffer += chunk.toString();
2484
+ const frames = buffer.split(/\n\n/);
2485
+ buffer = frames.pop() ?? "";
2486
+ for (const frame of frames) {
2487
+ const trimmed = frame.trim();
2488
+ if (!trimmed) continue;
2489
+ const line = trimmed.startsWith("data:") ? trimmed.slice(5).trim() : trimmed;
2490
+ if (line === "[DONE]") {
2491
+ yield { done: true };
2492
+ return;
2493
+ }
2494
+ try {
2495
+ const obj = JSON.parse(line);
2496
+ yield {
2497
+ delta: obj.delta ?? obj.choices?.[0]?.delta?.content ?? obj.text ?? void 0,
2498
+ content: obj.content ?? obj.message?.content,
2499
+ type: obj.type ?? obj.event,
2500
+ done: obj.done ?? obj.finished,
2501
+ raw: obj
2502
+ };
2503
+ } catch {
2504
+ yield { delta: line, raw: line };
2505
+ }
2506
+ }
2507
+ }
2508
+ if (buffer.trim()) {
2509
+ try {
2510
+ yield { raw: JSON.parse(buffer) };
2511
+ } catch {
2512
+ yield { delta: buffer };
2513
+ }
2514
+ }
2515
+ }
2516
+ /**
2517
+ * Get prompt suggestions, e.g. for an empty session UI.
2518
+ */
2519
+ async suggestions(opts = {}) {
2520
+ const { data } = await this.synapCores._getHttpClient().post("/ai/suggestions", opts);
2521
+ return (data.suggestions ?? data ?? []).map((s) => ({
2522
+ prompt: s.prompt ?? s.text ?? "",
2523
+ category: s.category,
2524
+ meta: s.meta ?? s.metadata
2525
+ }));
2526
+ }
2527
+ /**
2528
+ * List configured chat models.
1827
2529
  */
1828
- async deactivateSchedule(scheduleId) {
1829
- const { data } = await this.synapCores._getHttpClient().post(
1830
- `/backups/schedules/${scheduleId}/deactivate`
1831
- );
1832
- return {
1833
- id: data.id,
1834
- name: data.name,
1835
- cron: data.cron,
1836
- backup_options: data.backup_options,
1837
- active: data.active,
1838
- last_run_at: data.last_run_at ? new Date(data.last_run_at) : void 0,
1839
- next_run_at: data.next_run_at ? new Date(data.next_run_at) : void 0,
1840
- created_at: new Date(data.created_at),
1841
- tags: data.tags || []
1842
- };
2530
+ async models() {
2531
+ const { data } = await this.synapCores._getHttpClient().get("/ai/models");
2532
+ return (data.models ?? data ?? []).map((m) => ({
2533
+ id: m.id ?? m.name,
2534
+ name: m.name,
2535
+ provider: m.provider,
2536
+ context_window: m.context_window ?? m.max_context,
2537
+ capabilities: m.capabilities
2538
+ }));
1843
2539
  }
1844
2540
  /**
1845
- * Get backup metrics
2541
+ * List the available system prompts library.
1846
2542
  */
1847
- async getMetrics() {
1848
- const { data } = await this.synapCores._getHttpClient().get("/backups/metrics");
2543
+ async systemPrompts() {
2544
+ const { data } = await this.synapCores._getHttpClient().get("/ai/system-prompts");
2545
+ return (data.prompts ?? data.system_prompts ?? data ?? []).map((p) => ({
2546
+ id: String(p.id ?? p.name ?? ""),
2547
+ name: p.name,
2548
+ content: p.content ?? p.text ?? "",
2549
+ description: p.description,
2550
+ category: p.category
2551
+ }));
2552
+ }
2553
+ };
2554
+
2555
+ // src/multimodal.ts
2556
+ var MultimodalClient = class {
2557
+ constructor(synapCores) {
2558
+ this.synapCores = synapCores;
2559
+ }
2560
+ async similarity(a, b, opts = {}) {
2561
+ const { data } = await this.synapCores._getHttpClient().post("/multimodal/similarity", {
2562
+ a: typeof a === "string" ? { type: "text", text: a } : a,
2563
+ b: typeof b === "string" ? { type: "text", text: b } : b,
2564
+ ...opts
2565
+ });
1849
2566
  return {
1850
- total_backups: data.total_backups || 0,
1851
- total_size_bytes: data.total_size_bytes || 0,
1852
- successful_backups: data.successful_backups || 0,
1853
- failed_backups: data.failed_backups || 0,
1854
- avg_backup_size_bytes: data.avg_backup_size_bytes || 0,
1855
- avg_duration_ms: data.avg_duration_ms || 0,
1856
- last_backup_at: data.last_backup_at ? new Date(data.last_backup_at) : void 0,
1857
- next_scheduled_at: data.next_scheduled_at ? new Date(data.next_scheduled_at) : void 0
2567
+ similarity: data.similarity ?? data.score ?? 0,
2568
+ metric: data.metric ?? opts.metric,
2569
+ raw: data
1858
2570
  };
1859
2571
  }
1860
- /**
1861
- * Map raw backup data to Backup type
1862
- */
1863
- mapBackup(data) {
2572
+ async search(query, opts = {}) {
2573
+ const { data } = await this.synapCores._getHttpClient().post("/multimodal/search", {
2574
+ query: typeof query === "string" ? { type: "text", text: query } : query,
2575
+ ...opts
2576
+ });
2577
+ return (data.results ?? data.hits ?? data ?? []).map((r) => ({
2578
+ id: String(r.id ?? r.document_id ?? ""),
2579
+ score: r.score ?? r.similarity ?? 0,
2580
+ modality: r.modality,
2581
+ metadata: r.metadata
2582
+ }));
2583
+ }
2584
+ async join(left, right, opts = {}) {
2585
+ const normalize = (side) => Array.isArray(side) ? side.map((s) => typeof s === "string" ? { type: "text", text: s } : s) : side;
2586
+ const { data } = await this.synapCores._getHttpClient().post("/multimodal/join", {
2587
+ left: normalize(left),
2588
+ right: normalize(right),
2589
+ ...opts
2590
+ });
1864
2591
  return {
1865
- id: data.id,
1866
- name: data.name,
1867
- description: data.description,
1868
- type: data.type,
1869
- status: data.status,
1870
- size_bytes: data.size_bytes,
1871
- compressed_size_bytes: data.compressed_size_bytes,
1872
- table_count: data.table_count,
1873
- created_at: new Date(data.created_at),
1874
- completed_at: data.completed_at ? new Date(data.completed_at) : void 0,
1875
- duration_ms: data.duration_ms || data.took_ms,
1876
- storage: data.storage,
1877
- storage_path: data.storage_path,
1878
- encrypted: data.encrypted || false,
1879
- tags: data.tags || [],
1880
- parent_backup_id: data.parent_backup_id,
1881
- error: data.error
2592
+ pairs: (data.pairs ?? data.results ?? []).map((p) => ({
2593
+ left: p.left,
2594
+ right: p.right,
2595
+ score: p.score ?? p.similarity ?? 0
2596
+ }))
2597
+ };
2598
+ }
2599
+ async embed(input, model) {
2600
+ const { data } = await this.synapCores._getHttpClient().post("/multimodal/embed", {
2601
+ input: typeof input === "string" ? { type: "text", text: input } : input,
2602
+ model
2603
+ });
2604
+ const embedding = data.embedding ?? data.vector ?? [];
2605
+ return {
2606
+ embedding,
2607
+ modality: data.modality,
2608
+ model: data.model ?? model,
2609
+ dimensions: data.dimensions ?? embedding.length
1882
2610
  };
1883
2611
  }
1884
2612
  };
1885
2613
 
1886
- // src/errors.ts
1887
- var SynapCoresError = class _SynapCoresError extends Error {
1888
- constructor(message, code, details) {
1889
- super(message);
1890
- this.name = "SynapCoresError";
1891
- this.code = code;
1892
- this.details = details;
1893
- if (Error.captureStackTrace) {
1894
- Error.captureStackTrace(this, _SynapCoresError);
2614
+ // src/system.ts
2615
+ var VisionApi = class {
2616
+ constructor(synapCores) {
2617
+ this.synapCores = synapCores;
2618
+ }
2619
+ async get() {
2620
+ try {
2621
+ const { data } = await this.synapCores._getHttpClient().get("/system/vision");
2622
+ if (!data || Object.keys(data).length === 0) return null;
2623
+ return data;
2624
+ } catch (e) {
2625
+ if (e?.statusCode === 404 || e?.code === "NOT_FOUND") return null;
2626
+ throw e;
1895
2627
  }
1896
2628
  }
1897
- };
1898
- var ConnectionError = class extends SynapCoresError {
1899
- constructor(message, details) {
1900
- super(message, "CONNECTION_ERROR", details);
1901
- this.name = "ConnectionError";
2629
+ async set(cfg) {
2630
+ const { data } = await this.synapCores._getHttpClient().put("/system/vision", cfg);
2631
+ return data;
1902
2632
  }
1903
- };
1904
- var AuthenticationError = class extends SynapCoresError {
1905
- constructor(message, details) {
1906
- super(message, "AUTH_ERROR", details);
1907
- this.name = "AuthenticationError";
2633
+ async delete() {
2634
+ await this.synapCores._getHttpClient().delete("/system/vision");
1908
2635
  }
1909
- };
1910
- var ValidationError = class extends SynapCoresError {
1911
- constructor(message, details) {
1912
- super(message, "VALIDATION_ERROR", details);
1913
- this.name = "ValidationError";
2636
+ async test(payload = {}) {
2637
+ const { data } = await this.synapCores._getHttpClient().post("/system/vision/test", payload);
2638
+ return {
2639
+ success: data.success ?? false,
2640
+ latency_ms: data.latency_ms,
2641
+ response: data.response,
2642
+ error: data.error
2643
+ };
1914
2644
  }
1915
2645
  };
1916
- var NotFoundError = class extends SynapCoresError {
1917
- constructor(message, details) {
1918
- super(message, "NOT_FOUND", details);
1919
- this.name = "NotFoundError";
2646
+ var SystemClient = class {
2647
+ constructor(synapCores) {
2648
+ this.vision = new VisionApi(synapCores);
1920
2649
  }
1921
2650
  };
1922
- var ServerError = class extends SynapCoresError {
1923
- constructor(message, details) {
1924
- super(message, "SERVER_ERROR", details);
1925
- this.name = "ServerError";
2651
+
2652
+ // src/transactions.ts
2653
+ var Tx = class {
2654
+ constructor(http, id, options) {
2655
+ this.http = http;
2656
+ this.id = id;
2657
+ this.options = options;
2658
+ this.active = true;
1926
2659
  }
1927
- };
1928
- var TimeoutError = class extends SynapCoresError {
1929
- constructor(message, details) {
1930
- super(message, "TIMEOUT_ERROR", details);
1931
- this.name = "TimeoutError";
2660
+ isActive() {
2661
+ return this.active;
1932
2662
  }
1933
- };
1934
- var RateLimitError = class extends SynapCoresError {
1935
- constructor(message, retryAfter, details) {
1936
- super(message, "RATE_LIMIT_ERROR", details);
1937
- this.name = "RateLimitError";
1938
- this.retryAfter = retryAfter;
2663
+ async execute(sql, params = []) {
2664
+ this.assertActive();
2665
+ const { data } = await this.http.post(`/transactions/${this.id}/execute`, {
2666
+ sql,
2667
+ parameters: params
2668
+ });
2669
+ return {
2670
+ columns: data.columns ?? [],
2671
+ rows: data.rows ?? [],
2672
+ rows_affected: data.rows_affected,
2673
+ execution_time_ms: data.execution_time_ms ?? data.took_ms
2674
+ };
1939
2675
  }
1940
- };
1941
- var SQLError = class extends SynapCoresError {
1942
- constructor(message, code, severity = "ERROR", position, hint, detail, details) {
1943
- super(message, code, details);
1944
- this.name = "SQLError";
1945
- this.severity = severity;
1946
- this.position = position;
1947
- this.hint = hint;
1948
- this.detail = detail;
2676
+ async commit() {
2677
+ this.assertActive();
2678
+ await this.http.post(`/transactions/${this.id}/commit`, {});
2679
+ this.active = false;
2680
+ }
2681
+ async rollback() {
2682
+ this.assertActive();
2683
+ await this.http.post(`/transactions/${this.id}/rollback`, {});
2684
+ this.active = false;
2685
+ }
2686
+ async savepoint(name) {
2687
+ this.assertActive();
2688
+ await this.http.post(`/transactions/${this.id}/savepoint`, { name });
2689
+ }
2690
+ async rollbackTo(name) {
2691
+ this.assertActive();
2692
+ await this.http.post(`/transactions/${this.id}/savepoint/${name}/rollback`, {});
2693
+ }
2694
+ assertActive() {
2695
+ if (!this.active) {
2696
+ throw new Error(`Transaction ${this.id} has already been committed/rolled back`);
2697
+ }
1949
2698
  }
1950
2699
  };
1951
- var VectorError = class extends SynapCoresError {
1952
- constructor(message, code, vectorDimensions, expectedDimensions, operation, details) {
1953
- super(message, code, details);
1954
- this.name = "VectorError";
1955
- this.vectorDimensions = vectorDimensions;
1956
- this.expectedDimensions = expectedDimensions;
1957
- this.operation = operation;
2700
+ var TxHistoryApi = class {
2701
+ constructor(synapCores) {
2702
+ this.synapCores = synapCores;
2703
+ }
2704
+ async list(opts = {}) {
2705
+ const params = new URLSearchParams();
2706
+ if (opts.limit) params.append("limit", String(opts.limit));
2707
+ if (opts.status) params.append("status", opts.status);
2708
+ const qs = params.toString();
2709
+ const { data } = await this.synapCores._getHttpClient().get(
2710
+ `/transactions/history${qs ? `?${qs}` : ""}`
2711
+ );
2712
+ return (data.transactions ?? data.history ?? data ?? []).map((row) => ({
2713
+ id: String(row.id ?? row.transaction_id ?? ""),
2714
+ status: row.status ?? "unknown",
2715
+ started_at: new Date(row.started_at ?? row.created_at ?? Date.now()),
2716
+ completed_at: row.completed_at ? new Date(row.completed_at) : void 0,
2717
+ isolation_level: row.isolation_level,
2718
+ read_only: row.read_only,
2719
+ statement_count: row.statement_count ?? row.statements,
2720
+ metrics: row.metrics
2721
+ }));
2722
+ }
2723
+ async get(id) {
2724
+ const { data } = await this.synapCores._getHttpClient().get(
2725
+ `/transactions/history/${id}`
2726
+ );
2727
+ return {
2728
+ id: String(data.id ?? id),
2729
+ status: data.status ?? "unknown",
2730
+ started_at: new Date(data.started_at ?? data.created_at ?? Date.now()),
2731
+ completed_at: data.completed_at ? new Date(data.completed_at) : void 0,
2732
+ isolation_level: data.isolation_level,
2733
+ read_only: data.read_only,
2734
+ statement_count: data.statement_count ?? data.statements,
2735
+ metrics: data.metrics
2736
+ };
1958
2737
  }
1959
2738
  };
1960
- var TransactionError = class extends SynapCoresError {
1961
- constructor(message, code, transactionId, transactionState, details) {
1962
- super(message, code, details);
1963
- this.name = "TransactionError";
1964
- this.transactionId = transactionId;
1965
- this.transactionState = transactionState;
2739
+ var TransactionsClient = class {
2740
+ constructor(synapCores) {
2741
+ this.synapCores = synapCores;
2742
+ this.history = new TxHistoryApi(synapCores);
2743
+ }
2744
+ /**
2745
+ * Begin a new server-side transaction.
2746
+ */
2747
+ async begin(opts = {}) {
2748
+ const { data } = await this.synapCores._getHttpClient().post("/transactions", opts);
2749
+ const id = String(data.id ?? data.transaction_id ?? "");
2750
+ if (!id) {
2751
+ throw new Error("begin(): server did not return a transaction id");
2752
+ }
2753
+ return new Tx(this.synapCores._getHttpClient(), id, opts);
1966
2754
  }
1967
2755
  };
1968
- var BatchOperationError = class extends SynapCoresError {
1969
- constructor(message, code, failedItems, totalProcessed, successfulCount, details) {
1970
- super(message, code, details);
1971
- this.name = "BatchOperationError";
1972
- this.failedItems = failedItems;
1973
- this.totalProcessed = totalProcessed;
1974
- this.successfulCount = successfulCount;
2756
+
2757
+ // src/mcp.ts
2758
+ var mcpRequestCounter = 0;
2759
+ function withId(req) {
2760
+ if (req.id !== void 0 && req.id !== null) return req;
2761
+ mcpRequestCounter += 1;
2762
+ return { ...req, id: `mcp-${Date.now()}-${mcpRequestCounter}` };
2763
+ }
2764
+ var McpClient = class {
2765
+ constructor(synapCores) {
2766
+ this.synapCores = synapCores;
2767
+ }
2768
+ /**
2769
+ * Invoke a single MCP method.
2770
+ */
2771
+ async invoke(req) {
2772
+ const body = withId(req);
2773
+ const { data } = await this.synapCores._getHttpClient().post("/mcp", body);
2774
+ return {
2775
+ id: data.id ?? body.id,
2776
+ result: data.result,
2777
+ error: data.error,
2778
+ raw: data
2779
+ };
2780
+ }
2781
+ /**
2782
+ * Send an array of MCP invocations and resolve to the matching array
2783
+ * of responses (in the order returned by the gateway).
2784
+ */
2785
+ async batch(reqs) {
2786
+ const body = reqs.map(withId);
2787
+ const { data } = await this.synapCores._getHttpClient().post("/mcp/batch", body);
2788
+ const arr = Array.isArray(data) ? data : data.responses ?? data.results ?? [];
2789
+ return arr.map((r) => ({
2790
+ id: r.id,
2791
+ result: r.result,
2792
+ error: r.error,
2793
+ raw: r
2794
+ }));
2795
+ }
2796
+ /**
2797
+ * Discover the server's MCP capabilities and tools.
2798
+ */
2799
+ async info() {
2800
+ const { data } = await this.synapCores._getHttpClient().get("/mcp/info");
2801
+ return {
2802
+ version: data.version ?? data.mcp_version ?? "0",
2803
+ capabilities: data.capabilities,
2804
+ tools: data.tools,
2805
+ meta: data.meta ?? data.metadata
2806
+ };
1975
2807
  }
1976
2808
  };
1977
2809
 
@@ -2010,7 +2842,7 @@ var SynapCores = class {
2010
2842
  timeout: this.config.timeout,
2011
2843
  headers: {
2012
2844
  "Content-Type": "application/json",
2013
- "User-Agent": "synapcores-nodejs/0.1.0",
2845
+ "User-Agent": "synapcores-nodejs/0.2.0",
2014
2846
  ...authHeader
2015
2847
  },
2016
2848
  ...httpsAgent && { httpsAgent }
@@ -2026,6 +2858,44 @@ var SynapCores = class {
2026
2858
  this.import = new ImportExportClient(this);
2027
2859
  this.integrations = new IntegrationClient(this);
2028
2860
  this.backup = new BackupClient(this);
2861
+ this.graph = new GraphClient(this);
2862
+ this.nl2sql = new NL2SqlClient(this);
2863
+ this.filesystem = new FilesystemCollectionsClient(this);
2864
+ this.chat = new ChatClient(this);
2865
+ this.multimodal = new MultimodalClient(this);
2866
+ this.system = new SystemClient(this);
2867
+ this.transactions = new TransactionsClient(this);
2868
+ this.mcp = new McpClient(this);
2869
+ }
2870
+ /**
2871
+ * Build the WebSocket base URL (ws:// or wss://).
2872
+ */
2873
+ _getWsBaseUrl() {
2874
+ const protocol = this.config.useHttps ? "wss" : "ws";
2875
+ return `${protocol}://${this.config.host}:${this.config.port}`;
2876
+ }
2877
+ /**
2878
+ * Read-only access to the configured host/port for WS-clients.
2879
+ */
2880
+ _getConfig() {
2881
+ return this.config;
2882
+ }
2883
+ /**
2884
+ * Exchange the current credentials (JWT or API key) for a short-lived
2885
+ * WebSocket ticket. Use the returned token as the `?token=` query
2886
+ * param when opening any /ws endpoint.
2887
+ */
2888
+ async createWsTicket() {
2889
+ const { data } = await this.httpClient.post("/ws/ticket", {});
2890
+ const token = data.token ?? data.ticket;
2891
+ const expiresAt = typeof data.expiresAt === "number" ? data.expiresAt : data.expires_at ? Date.parse(data.expires_at) : Date.now() + 6e4;
2892
+ return { token, expiresAt };
2893
+ }
2894
+ /**
2895
+ * Revoke a previously-issued ticket (best-effort).
2896
+ */
2897
+ async revokeWsTicket(token) {
2898
+ await this.httpClient.post("/ws/ticket/revoke", { token });
2029
2899
  }
2030
2900
  handleError(error) {
2031
2901
  if (!error.response) {
@@ -2214,11 +3084,11 @@ var SynapCores = class {
2214
3084
  async embed(text, options = {}) {
2215
3085
  const isBatch = Array.isArray(text);
2216
3086
  const texts = isBatch ? text : [text];
2217
- const { data } = await this.httpClient.post("/ai/embed", {
2218
- texts,
2219
- model: options.model || "default"
2220
- });
2221
- return isBatch ? data.embeddings : data.embeddings[0];
3087
+ const path = isBatch ? "/ai/embeddings/batch" : "/ai/embeddings";
3088
+ const body = isBatch ? { texts, model: options.model } : { text: texts[0], model: options.model };
3089
+ const { data } = await this.httpClient.post(path, body);
3090
+ if (isBatch) return data.embeddings ?? data;
3091
+ return data.embedding ?? data.embeddings?.[0] ?? data;
2222
3092
  }
2223
3093
  // Internal method for HTTP client access
2224
3094
  _getHttpClient() {
@@ -2345,8 +3215,16 @@ var SynapCores = class {
2345
3215
  * @returns Promise resolving to table information
2346
3216
  */
2347
3217
  async describeTable(tableName) {
2348
- const { data } = await this.httpClient.get(`/table/${tableName}/info`);
2349
- return data;
3218
+ const [tableRes, colsRes, idxRes] = await Promise.all([
3219
+ this.httpClient.get(`/schema/tables/${tableName}`),
3220
+ this.httpClient.get(`/schema/tables/${tableName}/columns`),
3221
+ this.httpClient.get(`/schema/tables/${tableName}/indexes`)
3222
+ ]);
3223
+ return {
3224
+ ...tableRes.data,
3225
+ columns: colsRes.data?.columns ?? colsRes.data ?? [],
3226
+ indexes: idxRes.data?.indexes ?? idxRes.data ?? []
3227
+ };
2350
3228
  }
2351
3229
  /**
2352
3230
  * Lists all tables in the current database
@@ -2479,19 +3357,26 @@ var SynapCores = class {
2479
3357
  * @returns Promise resolving to batch operation result
2480
3358
  */
2481
3359
  async batchInsert(options) {
2482
- const { data } = await this.httpClient.post("/batch/insert", {
2483
- table_name: options.tableName,
2484
- columns: options.columns,
2485
- rows: options.rows,
2486
- on_conflict: options.onConflict,
2487
- batch_size: options.batchSize || 1e3
2488
- });
2489
- return {
2490
- totalProcessed: data.total_processed,
2491
- successful: data.successful,
2492
- failed: data.failed,
2493
- errors: data.errors,
2494
- tookMs: data.took_ms
3360
+ const cols = options.columns ?? [];
3361
+ const queries = options.rows.map((row) => {
3362
+ const values = Array.isArray(row) ? row : cols.map((c) => row[c]);
3363
+ return {
3364
+ sql: `INSERT INTO ${options.tableName} (${cols.join(", ")}) VALUES (${values.map((_, i) => "$" + (i + 1)).join(", ")})`,
3365
+ parameters: values
3366
+ };
3367
+ });
3368
+ const { data } = await this.httpClient.post("/query/execute/batch", {
3369
+ queries,
3370
+ transactional: false
3371
+ });
3372
+ const results = data.results ?? [];
3373
+ const successful = results.filter((r) => !r.error).length;
3374
+ return {
3375
+ totalProcessed: results.length,
3376
+ successful,
3377
+ failed: results.length - successful,
3378
+ errors: results.filter((r) => r.error).map((r) => r.error),
3379
+ tookMs: data.total_execution_time_ms ?? 0
2495
3380
  };
2496
3381
  }
2497
3382
  /**
@@ -2500,17 +3385,27 @@ var SynapCores = class {
2500
3385
  * @returns Promise resolving to batch operation result
2501
3386
  */
2502
3387
  async batchUpdate(options) {
2503
- const { data } = await this.httpClient.post("/batch/update", {
2504
- table_name: options.tableName,
2505
- updates: options.updates,
2506
- batch_size: options.batchSize || 1e3
3388
+ const queries = options.updates.map((u) => {
3389
+ const setClause = Object.keys(u.set ?? {}).map((k, i) => `${k} = $${i + 1}`).join(", ");
3390
+ const setVals = Object.values(u.set ?? {});
3391
+ const whereStr = u.where ?? "1=1";
3392
+ return {
3393
+ sql: `UPDATE ${options.tableName} SET ${setClause} WHERE ${whereStr}`,
3394
+ parameters: setVals
3395
+ };
2507
3396
  });
3397
+ const { data } = await this.httpClient.post("/query/execute/batch", {
3398
+ queries,
3399
+ transactional: false
3400
+ });
3401
+ const results = data.results ?? [];
3402
+ const successful = results.filter((r) => !r.error).length;
2508
3403
  return {
2509
- totalProcessed: data.total_processed,
2510
- successful: data.successful,
2511
- failed: data.failed,
2512
- errors: data.errors,
2513
- tookMs: data.took_ms
3404
+ totalProcessed: results.length,
3405
+ successful,
3406
+ failed: results.length - successful,
3407
+ errors: results.filter((r) => r.error).map((r) => r.error),
3408
+ tookMs: data.total_execution_time_ms ?? 0
2514
3409
  };
2515
3410
  }
2516
3411
  /**
@@ -2519,17 +3414,22 @@ var SynapCores = class {
2519
3414
  * @returns Promise resolving to batch operation result
2520
3415
  */
2521
3416
  async batchDelete(options) {
2522
- const { data } = await this.httpClient.post("/batch/delete", {
2523
- table_name: options.tableName,
2524
- where_conditions: options.whereConditions,
2525
- batch_size: options.batchSize || 1e3
3417
+ const queries = (options.whereConditions ?? []).map((cond) => ({
3418
+ sql: `DELETE FROM ${options.tableName} WHERE ${typeof cond === "string" ? cond : JSON.stringify(cond)}`,
3419
+ parameters: []
3420
+ }));
3421
+ const { data } = await this.httpClient.post("/query/execute/batch", {
3422
+ queries,
3423
+ transactional: false
2526
3424
  });
3425
+ const results = data.results ?? [];
3426
+ const successful = results.filter((r) => !r.error).length;
2527
3427
  return {
2528
- totalProcessed: data.total_processed,
2529
- successful: data.successful,
2530
- failed: data.failed,
2531
- errors: data.errors,
2532
- tookMs: data.took_ms
3428
+ totalProcessed: results.length,
3429
+ successful,
3430
+ failed: results.length - successful,
3431
+ errors: results.filter((r) => r.error).map((r) => r.error),
3432
+ tookMs: data.total_execution_time_ms ?? 0
2533
3433
  };
2534
3434
  }
2535
3435
  // =================================================================
@@ -2542,15 +3442,15 @@ var SynapCores = class {
2542
3442
  * @returns Promise resolving to prepared statement
2543
3443
  */
2544
3444
  async prepareStatement(sql, options = {}) {
2545
- const { data } = await this.httpClient.post("/prepare", {
3445
+ const { data } = await this.httpClient.post("/query/prepare", {
2546
3446
  sql,
2547
3447
  name: options.name,
2548
3448
  parameter_types: options.parameterTypes
2549
3449
  });
2550
3450
  const prepared = {
2551
- id: data.statement_id,
3451
+ id: data.statement_id ?? data.id,
2552
3452
  sql,
2553
- parameterCount: data.parameter_count
3453
+ parameterCount: data.parameter_count ?? data.parameters_count ?? 0
2554
3454
  };
2555
3455
  if (options.name) {
2556
3456
  this.preparedStatements.set(options.name, prepared);
@@ -2567,7 +3467,7 @@ var SynapCores = class {
2567
3467
  if (this.preparedStatements.has(statementId)) {
2568
3468
  statementId = this.preparedStatements.get(statementId).id;
2569
3469
  }
2570
- const { data } = await this.httpClient.post("/execute-prepared", {
3470
+ const { data } = await this.httpClient.post("/query/exec", {
2571
3471
  statement_id: statementId,
2572
3472
  parameters: params
2573
3473
  });
@@ -2587,10 +3487,10 @@ var SynapCores = class {
2587
3487
  async deallocatePrepared(statementId) {
2588
3488
  if (this.preparedStatements.has(statementId)) {
2589
3489
  const prepared = this.preparedStatements.get(statementId);
2590
- await this.httpClient.delete(`/prepare/${prepared.id}`);
3490
+ await this.httpClient.post("/query/close", { statement_id: prepared.id });
2591
3491
  this.preparedStatements.delete(statementId);
2592
3492
  } else {
2593
- await this.httpClient.delete(`/prepare/${statementId}`);
3493
+ await this.httpClient.post("/query/close", { statement_id: statementId });
2594
3494
  }
2595
3495
  }
2596
3496
  /**
@@ -2681,231 +3581,198 @@ var SynapCores = class {
2681
3581
  if (vector1.length !== vector2.length) {
2682
3582
  throw new VectorError("Vector dimensions must match", "DIMENSION_MISMATCH");
2683
3583
  }
2684
- const { data } = await this.httpClient.post("/vectors/add", {
2685
- vector1,
2686
- vector2
3584
+ const { data } = await this.httpClient.post("/vector-algebra/operation", {
3585
+ op: "add",
3586
+ a: vector1,
3587
+ b: vector2
2687
3588
  });
3589
+ const result = data.result ?? data.vector ?? [];
2688
3590
  return {
2689
- result: { values: data.result, dimensions: data.result.length },
3591
+ result: { values: result, dimensions: result.length },
2690
3592
  operation: "addition",
2691
3593
  tookMs: data.took_ms
2692
3594
  };
2693
3595
  }
2694
3596
  /**
2695
3597
  * Performs vector subtraction
2696
- * @param vector1 - First vector (minuend)
2697
- * @param vector2 - Second vector (subtrahend)
2698
- * @returns Promise resolving to vector subtraction result
2699
3598
  */
2700
3599
  async vectorSubtract(vector1, vector2) {
2701
3600
  if (vector1.length !== vector2.length) {
2702
3601
  throw new VectorError("Vector dimensions must match", "DIMENSION_MISMATCH");
2703
3602
  }
2704
- const { data } = await this.httpClient.post("/vectors/subtract", {
2705
- vector1,
2706
- vector2
3603
+ const { data } = await this.httpClient.post("/vector-algebra/operation", {
3604
+ op: "subtract",
3605
+ a: vector1,
3606
+ b: vector2
2707
3607
  });
3608
+ const result = data.result ?? data.vector ?? [];
2708
3609
  return {
2709
- result: { values: data.result, dimensions: data.result.length },
3610
+ result: { values: result, dimensions: result.length },
2710
3611
  operation: "subtraction",
2711
3612
  tookMs: data.took_ms
2712
3613
  };
2713
3614
  }
2714
3615
  /**
2715
3616
  * Performs scalar multiplication on a vector
2716
- * @param vector - Input vector
2717
- * @param scalar - Scalar value to multiply by
2718
- * @returns Promise resolving to scalar multiplication result
2719
3617
  */
2720
3618
  async vectorScalarMultiply(vector, scalar) {
2721
- const { data } = await this.httpClient.post("/vectors/scalar-multiply", {
2722
- vector,
3619
+ const { data } = await this.httpClient.post("/vector-algebra/operation", {
3620
+ op: "scalar_multiply",
3621
+ a: vector,
2723
3622
  scalar
2724
3623
  });
3624
+ const result = data.result ?? data.vector ?? [];
2725
3625
  return {
2726
- result: { values: data.result, dimensions: data.result.length },
3626
+ result: { values: result, dimensions: result.length },
2727
3627
  operation: "scalar_multiplication",
2728
3628
  tookMs: data.took_ms
2729
3629
  };
2730
3630
  }
2731
3631
  /**
2732
3632
  * Calculates the dot product of two vectors
2733
- * @param vector1 - First vector
2734
- * @param vector2 - Second vector
2735
- * @returns Promise resolving to dot product result
2736
3633
  */
2737
3634
  async vectorDotProduct(vector1, vector2) {
2738
3635
  if (vector1.length !== vector2.length) {
2739
3636
  throw new VectorError("Vector dimensions must match", "DIMENSION_MISMATCH");
2740
3637
  }
2741
- const { data } = await this.httpClient.post("/vectors/dot-product", {
2742
- vector1,
2743
- vector2
3638
+ const { data } = await this.httpClient.post("/vector-algebra/operation", {
3639
+ op: "dot_product",
3640
+ a: vector1,
3641
+ b: vector2
2744
3642
  });
2745
- return {
2746
- dotProduct: data.dot_product,
2747
- tookMs: data.took_ms
2748
- };
3643
+ return { dotProduct: data.scalar ?? data.dot_product ?? 0, tookMs: data.took_ms };
2749
3644
  }
2750
3645
  /**
2751
3646
  * Calculates cosine similarity between two vectors
2752
- * @param vector1 - First vector
2753
- * @param vector2 - Second vector
2754
- * @returns Promise resolving to cosine similarity result
2755
3647
  */
2756
3648
  async cosineSimilarity(vector1, vector2) {
2757
3649
  if (vector1.length !== vector2.length) {
2758
3650
  throw new VectorError("Vector dimensions must match", "DIMENSION_MISMATCH");
2759
3651
  }
2760
- const { data } = await this.httpClient.post("/vectors/cosine-similarity", {
2761
- vector1,
2762
- vector2
3652
+ const { data } = await this.httpClient.post("/vector-algebra/operation", {
3653
+ op: "cosine_similarity",
3654
+ a: vector1,
3655
+ b: vector2
2763
3656
  });
2764
- return {
2765
- similarity: data.similarity,
2766
- function: "cosine",
2767
- tookMs: data.took_ms
2768
- };
3657
+ return { similarity: data.scalar ?? data.similarity ?? 0, function: "cosine", tookMs: data.took_ms };
2769
3658
  }
2770
3659
  /**
2771
3660
  * Calculates L2 (Euclidean) distance between two vectors
2772
- * @param vector1 - First vector
2773
- * @param vector2 - Second vector
2774
- * @returns Promise resolving to L2 distance result
2775
3661
  */
2776
3662
  async l2Distance(vector1, vector2) {
2777
3663
  if (vector1.length !== vector2.length) {
2778
3664
  throw new VectorError("Vector dimensions must match", "DIMENSION_MISMATCH");
2779
3665
  }
2780
- const { data } = await this.httpClient.post("/vectors/l2-distance", {
2781
- vector1,
2782
- vector2
3666
+ const { data } = await this.httpClient.post("/vector-algebra/operation", {
3667
+ op: "l2_distance",
3668
+ a: vector1,
3669
+ b: vector2
2783
3670
  });
2784
- return {
2785
- distance: data.distance,
2786
- similarity: data.distance,
2787
- // Include similarity for compatibility
2788
- function: "l2",
2789
- tookMs: data.took_ms
2790
- };
3671
+ const distance = data.scalar ?? data.distance ?? 0;
3672
+ return { distance, similarity: distance, function: "l2", tookMs: data.took_ms };
2791
3673
  }
2792
3674
  /**
2793
3675
  * Calculates inner product between two vectors
2794
- * @param vector1 - First vector
2795
- * @param vector2 - Second vector
2796
- * @returns Promise resolving to inner product result
2797
3676
  */
2798
3677
  async innerProduct(vector1, vector2) {
2799
3678
  if (vector1.length !== vector2.length) {
2800
3679
  throw new VectorError("Vector dimensions must match", "DIMENSION_MISMATCH");
2801
3680
  }
2802
- const { data } = await this.httpClient.post("/vectors/inner-product", {
2803
- vector1,
2804
- vector2
3681
+ const { data } = await this.httpClient.post("/vector-algebra/operation", {
3682
+ op: "inner_product",
3683
+ a: vector1,
3684
+ b: vector2
2805
3685
  });
2806
- return {
2807
- similarity: data.inner_product,
2808
- function: "inner_product",
2809
- tookMs: data.took_ms
2810
- };
3686
+ return { similarity: data.scalar ?? data.inner_product ?? 0, function: "inner_product", tookMs: data.took_ms };
2811
3687
  }
2812
3688
  /**
2813
- * Performs K-nearest neighbors vector search
2814
- * @param options - KNN search options
2815
- * @returns Promise resolving to KNN search results
3689
+ * Performs K-nearest neighbors vector search.
3690
+ * v0.2.0: routes through /vectors/collections/:c/search with mode discriminator.
2816
3691
  */
2817
3692
  async knnSearch(options) {
2818
- const { data } = await this.httpClient.post("/vectors/knn-search", {
2819
- query_vector: options.queryVector,
2820
- k: options.k,
2821
- table_name: options.tableName,
2822
- vector_column: options.vectorColumn,
2823
- metadata_columns: options.metadataColumns,
3693
+ const collection = options.collectionName ?? options.tableName;
3694
+ const { data } = await this.httpClient.post(`/vectors/collections/${collection}/search`, {
3695
+ mode: "knn",
3696
+ vector: options.queryVector,
3697
+ limit: options.k,
2824
3698
  filter: options.filter
2825
3699
  });
2826
- return data.results.map((result) => ({
2827
- id: result.id,
2828
- vector: result.vector,
2829
- similarity: result.similarity,
2830
- distance: result.distance,
2831
- metadata: result.metadata
3700
+ return (data.matches ?? data.results ?? []).map((r) => ({
3701
+ id: r.id,
3702
+ vector: r.vector,
3703
+ similarity: r.similarity,
3704
+ distance: r.distance,
3705
+ metadata: r.metadata
2832
3706
  }));
2833
3707
  }
2834
3708
  /**
2835
- * Performs range-based vector similarity search
2836
- * @param options - Range search options
2837
- * @returns Promise resolving to range search results
3709
+ * Performs range-based vector similarity search.
2838
3710
  */
2839
3711
  async rangeSearch(options) {
2840
- const { data } = await this.httpClient.post("/vectors/range-search", {
2841
- query_vector: options.queryVector,
3712
+ const collection = options.collectionName ?? options.tableName;
3713
+ const { data } = await this.httpClient.post(`/vectors/collections/${collection}/search`, {
3714
+ mode: "range",
3715
+ vector: options.queryVector,
2842
3716
  threshold: options.threshold,
2843
- table_name: options.tableName,
2844
- vector_column: options.vectorColumn,
2845
- metadata_columns: options.metadataColumns,
2846
- filter: options.filter,
2847
- max_results: options.maxResults
2848
- });
2849
- return data.results.map((result) => ({
2850
- id: result.id,
2851
- vector: result.vector,
2852
- similarity: result.similarity,
2853
- distance: result.distance,
2854
- metadata: result.metadata
3717
+ max_results: options.maxResults,
3718
+ filter: options.filter
3719
+ });
3720
+ return (data.matches ?? data.results ?? []).map((r) => ({
3721
+ id: r.id,
3722
+ vector: r.vector,
3723
+ similarity: r.similarity,
3724
+ distance: r.distance,
3725
+ metadata: r.metadata
2855
3726
  }));
2856
3727
  }
2857
3728
  /**
2858
- * Performs hybrid search combining vector similarity and SQL filtering
2859
- * @param options - Hybrid search options
2860
- * @returns Promise resolving to hybrid search results
3729
+ * Performs hybrid search combining vector similarity and SQL filtering.
2861
3730
  */
2862
3731
  async hybridSearch(options) {
2863
- const { data } = await this.httpClient.post("/vectors/hybrid-search", {
3732
+ const collection = options.collectionName ?? options.tableName;
3733
+ const { data } = await this.httpClient.post(`/vectors/collections/${collection}/search`, {
3734
+ mode: "hybrid",
2864
3735
  vector: options.vector,
2865
3736
  text_query: options.textQuery,
2866
3737
  sql_filter: options.sqlFilter,
2867
- k: options.k,
3738
+ limit: options.k,
2868
3739
  threshold: options.threshold,
2869
3740
  metric: options.metric,
2870
3741
  filter: options.filter,
2871
3742
  weights: options.weights
2872
3743
  });
2873
- return data.results.map((result) => ({
2874
- id: result.id,
2875
- vector: result.vector,
2876
- similarity: result.similarity,
2877
- distance: result.distance,
2878
- metadata: result.metadata
3744
+ return (data.matches ?? data.results ?? []).map((r) => ({
3745
+ id: r.id,
3746
+ vector: r.vector,
3747
+ similarity: r.similarity,
3748
+ distance: r.distance,
3749
+ metadata: r.metadata
2879
3750
  }));
2880
3751
  }
2881
3752
  /**
2882
3753
  * Normalizes a vector to unit length
2883
- * @param vector - Input vector to normalize
2884
- * @returns Promise resolving to normalized vector
2885
3754
  */
2886
3755
  async normalizeVector(vector) {
2887
- const { data } = await this.httpClient.post("/vectors/normalize", {
2888
- vector
3756
+ const { data } = await this.httpClient.post("/vector-algebra/operation", {
3757
+ op: "normalize",
3758
+ a: vector
2889
3759
  });
3760
+ const result = data.result ?? data.vector ?? [];
2890
3761
  return {
2891
- result: { values: data.result, dimensions: data.result.length },
3762
+ result: { values: result, dimensions: result.length },
2892
3763
  operation: "normalization",
2893
3764
  tookMs: data.took_ms
2894
3765
  };
2895
3766
  }
2896
3767
  /**
2897
3768
  * Calculates the magnitude (length) of a vector
2898
- * @param vector - Input vector
2899
- * @returns Promise resolving to vector magnitude
2900
3769
  */
2901
3770
  async vectorMagnitude(vector) {
2902
- const { data } = await this.httpClient.post("/vectors/magnitude", {
2903
- vector
3771
+ const { data } = await this.httpClient.post("/vector-algebra/operation", {
3772
+ op: "magnitude",
3773
+ a: vector
2904
3774
  });
2905
- return {
2906
- magnitude: data.magnitude,
2907
- tookMs: data.took_ms
2908
- };
3775
+ return { magnitude: data.scalar ?? data.magnitude ?? 0, tookMs: data.took_ms };
2909
3776
  }
2910
3777
  // =================================================================
2911
3778
  // AUTHENTICATION & USER MANAGEMENT
@@ -2937,16 +3804,26 @@ var SynapCores = class {
2937
3804
  return data;
2938
3805
  }
2939
3806
  /**
2940
- * Refresh JWT token
3807
+ * Refresh JWT token.
3808
+ *
3809
+ * v0.2.0: the gateway does not currently expose a refresh endpoint —
3810
+ * this method now re-runs login() with the same credentials. Pass
3811
+ * the credentials in the call site (or supply them at SDK construction
3812
+ * time and we'll re-use the cached pair).
2941
3813
  */
2942
- async refreshToken() {
2943
- const { data } = await this.httpClient.post("/auth/refresh");
2944
- if (data.access_token) {
2945
- this.config.jwtToken = data.access_token;
2946
- this.httpClient.defaults.headers["Authorization"] = `Bearer ${data.access_token}`;
2947
- delete this.httpClient.defaults.headers["X-API-Key"];
3814
+ async refreshToken(credentials) {
3815
+ if (credentials?.username && credentials?.password) {
3816
+ const login = await this.login({ username: credentials.username, password: credentials.password });
3817
+ return {
3818
+ access_token: login.access_token,
3819
+ refresh_token: "",
3820
+ token_type: "Bearer",
3821
+ expires_in: login.expires_in
3822
+ };
2948
3823
  }
2949
- return data;
3824
+ throw new ValidationError(
3825
+ "refreshToken now requires credentials \u2014 the gateway has no /auth/refresh endpoint in v1.5.0-ce. Pass {username, password} or call login() again."
3826
+ );
2950
3827
  }
2951
3828
  /**
2952
3829
  * Set JWT token manually (useful after login)
@@ -3077,7 +3954,7 @@ var SynapCores = class {
3077
3954
 
3078
3955
  // src/index.ts
3079
3956
  var import_zod = require("zod");
3080
- var VERSION = "0.1.0";
3957
+ var VERSION = "0.2.0";
3081
3958
  // Annotate the CommonJS export names for ESM import in node:
3082
3959
  0 && (module.exports = {
3083
3960
  AuthenticationError,
@@ -3085,10 +3962,16 @@ var VERSION = "0.1.0";
3085
3962
  AutoMLModel,
3086
3963
  BackupClient,
3087
3964
  BatchOperationError,
3965
+ ChatClient,
3088
3966
  Collection,
3089
3967
  ConnectionError,
3968
+ FilesystemCollectionsClient,
3969
+ GraphClient,
3090
3970
  ImportExportClient,
3091
3971
  IntegrationClient,
3972
+ McpClient,
3973
+ MultimodalClient,
3974
+ NL2SqlClient,
3092
3975
  NLPClient,
3093
3976
  NotFoundError,
3094
3977
  RateLimitError,
@@ -3099,8 +3982,11 @@ var VERSION = "0.1.0";
3099
3982
  Subscription,
3100
3983
  SynapCores,
3101
3984
  SynapCoresError,
3985
+ SystemClient,
3102
3986
  TimeoutError,
3103
3987
  TransactionError,
3988
+ TransactionsClient,
3989
+ Tx,
3104
3990
  VERSION,
3105
3991
  ValidationError,
3106
3992
  VectorError,