@synapcores/sdk 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -30,13 +30,14 @@ var Subscription = class extends EventEmitter {
30
30
  }
31
31
  async createConnection() {
32
32
  const client = this.collection.client;
33
- const protocol = client.config.useHttps ? "wss" : "ws";
34
- const url = `${protocol}://${client.config.host}:${client.config.port}/v1/ws`;
35
- const headers = {};
36
- if (client.config.apiKey) {
37
- headers["Authorization"] = `Bearer ${client.config.apiKey}`;
38
- }
39
- this.ws = new WebSocket(url, { headers });
33
+ const { token } = await client.createWsTicket();
34
+ const wsBase = client._getWsBaseUrl ? client._getWsBaseUrl() : (() => {
35
+ const cfg = client.config ?? client._getConfig();
36
+ const protocol = cfg.useHttps ? "wss" : "ws";
37
+ return `${protocol}://${cfg.host}:${cfg.port}`;
38
+ })();
39
+ const url = `${wsBase}/ws?token=${encodeURIComponent(token)}`;
40
+ this.ws = new WebSocket(url);
40
41
  this.ws.on("open", () => {
41
42
  this.reconnectAttempts = 0;
42
43
  this.subscribe();
@@ -347,19 +348,14 @@ var AutoMLModel = class {
347
348
  const isSingle = !Array.isArray(data);
348
349
  const inputs = isSingle ? [data] : data;
349
350
  const response = await this.client.synapCores._getHttpClient().post(
350
- "/ai/predict",
351
- {
352
- model_id: this.id,
353
- inputs
354
- }
351
+ `/automl/models/${this.id}/predict`,
352
+ { inputs }
355
353
  );
356
- const predictions = response.data.predictions;
354
+ const predictions = response.data.predictions ?? response.data;
357
355
  return isSingle ? predictions[0] : predictions;
358
356
  }
359
357
  async evaluate(testData, target) {
360
- const payload = {
361
- model_id: this.id
362
- };
358
+ const payload = {};
363
359
  if (typeof testData === "string") {
364
360
  payload.collection = testData;
365
361
  } else {
@@ -369,14 +365,14 @@ var AutoMLModel = class {
369
365
  }
370
366
  }
371
367
  const { data } = await this.client.synapCores._getHttpClient().post(
372
- "/ai/evaluate",
368
+ `/automl/models/${this.id}/evaluate`,
373
369
  payload
374
370
  );
375
371
  return data;
376
372
  }
377
373
  async delete() {
378
374
  await this.client.synapCores._getHttpClient().delete(
379
- `/ai/models/${this.id}`
375
+ `/automl/models/${this.id}`
380
376
  );
381
377
  }
382
378
  };
@@ -385,7 +381,7 @@ var AutoMLClient = class {
385
381
  this.synapCores = synapCores;
386
382
  }
387
383
  async train(options) {
388
- const { data } = await this.synapCores._getHttpClient().post("/ai/train", {
384
+ const { data } = await this.synapCores._getHttpClient().post("/automl/train", {
389
385
  collection: options.collection,
390
386
  target: options.target,
391
387
  features: options.features,
@@ -402,15 +398,15 @@ var AutoMLClient = class {
402
398
  task: data.task,
403
399
  status: data.status,
404
400
  accuracy: data.accuracy,
405
- createdAt: new Date(data.created_at),
401
+ createdAt: new Date(data.created_at ?? Date.now()),
406
402
  updatedAt: data.updated_at ? new Date(data.updated_at) : void 0,
407
- config: data.config
403
+ config: data.config ?? {}
408
404
  };
409
405
  return new AutoMLModel(this, modelInfo);
410
406
  }
411
407
  async getModel(modelId) {
412
408
  const { data } = await this.synapCores._getHttpClient().get(
413
- `/ai/models/${modelId}`
409
+ `/automl/models/${modelId}`
414
410
  );
415
411
  const modelInfo = {
416
412
  id: data.id,
@@ -418,32 +414,35 @@ var AutoMLClient = class {
418
414
  task: data.task,
419
415
  status: data.status,
420
416
  accuracy: data.accuracy,
421
- createdAt: new Date(data.created_at),
417
+ createdAt: new Date(data.created_at ?? Date.now()),
422
418
  updatedAt: data.updated_at ? new Date(data.updated_at) : void 0,
423
- config: data.config
419
+ config: data.config ?? {}
424
420
  };
425
421
  return new AutoMLModel(this, modelInfo);
426
422
  }
427
423
  async listModels(filters) {
428
- const { data } = await this.synapCores._getHttpClient().get("/ai/models", {
424
+ const { data } = await this.synapCores._getHttpClient().get("/automl/models", {
429
425
  params: filters
430
426
  });
431
- return data.models.map((model) => ({
427
+ return (data.models ?? data ?? []).map((model) => ({
432
428
  id: model.id,
433
429
  name: model.name,
434
430
  task: model.task,
435
431
  status: model.status,
436
432
  accuracy: model.accuracy,
437
- createdAt: new Date(model.created_at),
433
+ createdAt: new Date(model.created_at ?? Date.now()),
438
434
  updatedAt: model.updated_at ? new Date(model.updated_at) : void 0,
439
- config: model.config
435
+ config: model.config ?? {}
440
436
  }));
441
437
  }
442
438
  /**
443
- * Start async training job
439
+ * Start async training job.
440
+ *
441
+ * In v1.5.0-ce there is no separate /train/async endpoint — /automl/train
442
+ * itself returns a job descriptor when the training is long-running.
444
443
  */
445
444
  async trainAsync(options) {
446
- const { data } = await this.synapCores._getHttpClient().post("/ai/train/async", {
445
+ const { data } = await this.synapCores._getHttpClient().post("/automl/train", {
447
446
  collection: options.collection,
448
447
  target: options.target,
449
448
  features: options.features,
@@ -453,49 +452,20 @@ var AutoMLClient = class {
453
452
  validation_split: options.validationSplit || 0.2,
454
453
  max_trials: options.maxTrials || 10,
455
454
  timeout_minutes: options.timeoutMinutes || 60,
455
+ async: true,
456
456
  callback_url: options.callback_url,
457
457
  webhook_url: options.webhook_url
458
458
  });
459
- return {
460
- id: data.id || data.job_id,
461
- name: data.name,
462
- status: data.status,
463
- progress: data.progress || 0,
464
- phase: data.phase,
465
- task: data.task,
466
- current_trial: data.current_trial,
467
- total_trials: data.total_trials || options.maxTrials || 10,
468
- best_accuracy: data.best_accuracy,
469
- eta_ms: data.eta_ms || data.estimated_time_remaining_ms,
470
- error: data.error,
471
- started_at: new Date(data.started_at || Date.now()),
472
- completed_at: data.completed_at ? new Date(data.completed_at) : void 0,
473
- model_id: data.model_id
474
- };
459
+ return this.mapTrainingJob(data, options.maxTrials || 10);
475
460
  }
476
461
  /**
477
462
  * Get training job status
478
463
  */
479
464
  async getTrainingJob(jobId) {
480
465
  const { data } = await this.synapCores._getHttpClient().get(
481
- `/ai/train/jobs/${jobId}`
466
+ `/automl/jobs/${jobId}`
482
467
  );
483
- return {
484
- id: data.id || jobId,
485
- name: data.name,
486
- status: data.status,
487
- progress: data.progress || 0,
488
- phase: data.phase,
489
- task: data.task,
490
- current_trial: data.current_trial,
491
- total_trials: data.total_trials,
492
- best_accuracy: data.best_accuracy,
493
- eta_ms: data.eta_ms || data.estimated_time_remaining_ms,
494
- error: data.error,
495
- started_at: new Date(data.started_at),
496
- completed_at: data.completed_at ? new Date(data.completed_at) : void 0,
497
- model_id: data.model_id
498
- };
468
+ return this.mapTrainingJob(data);
499
469
  }
500
470
  /**
501
471
  * List training jobs
@@ -505,45 +475,36 @@ var AutoMLClient = class {
505
475
  if (options.status) params.append("status", options.status);
506
476
  if (options.page) params.append("page", options.page.toString());
507
477
  if (options.page_size) params.append("page_size", options.page_size.toString());
478
+ const qs = params.toString();
508
479
  const { data } = await this.synapCores._getHttpClient().get(
509
- `/ai/train/jobs?${params.toString()}`
480
+ `/automl/jobs${qs ? `?${qs}` : ""}`
510
481
  );
511
- return (data.jobs || data).map((job) => ({
512
- id: job.id,
513
- name: job.name,
514
- status: job.status,
515
- progress: job.progress || 0,
516
- phase: job.phase,
517
- task: job.task,
518
- current_trial: job.current_trial,
519
- total_trials: job.total_trials,
520
- best_accuracy: job.best_accuracy,
521
- eta_ms: job.eta_ms || job.estimated_time_remaining_ms,
522
- error: job.error,
523
- started_at: new Date(job.started_at),
524
- completed_at: job.completed_at ? new Date(job.completed_at) : void 0,
525
- model_id: job.model_id
526
- }));
482
+ return (data.jobs ?? data ?? []).map((job) => this.mapTrainingJob(job));
527
483
  }
528
484
  /**
529
- * Cancel a training job
485
+ * Cancel/stop a training job
530
486
  */
531
487
  async cancelTrainingJob(jobId) {
532
- await this.synapCores._getHttpClient().post(`/ai/train/jobs/${jobId}/cancel`);
488
+ await this.synapCores._getHttpClient().post(`/automl/jobs/${jobId}/stop`);
533
489
  }
534
490
  /**
535
- * Get training metrics for a job
491
+ * Get training metrics for a job.
492
+ *
493
+ * v1.5.0-ce: gateway no longer has a dedicated /metrics route — metrics
494
+ * (when available) ship inside the /automl/jobs/:id payload as
495
+ * `metrics` or `trial_metrics`. We just unwrap that field here.
536
496
  */
537
497
  async getTrainingMetrics(jobId) {
538
498
  const { data } = await this.synapCores._getHttpClient().get(
539
- `/ai/train/jobs/${jobId}/metrics`
499
+ `/automl/jobs/${jobId}`
540
500
  );
541
- return (data.metrics || data).map((metric) => ({
501
+ const metrics = data.metrics ?? data.trial_metrics ?? [];
502
+ return metrics.map((metric) => ({
542
503
  trial: metric.trial,
543
504
  accuracy: metric.accuracy,
544
505
  loss: metric.loss,
545
506
  metrics: metric.metrics,
546
- timestamp: new Date(metric.timestamp)
507
+ timestamp: new Date(metric.timestamp ?? Date.now())
547
508
  }));
548
509
  }
549
510
  /**
@@ -576,6 +537,24 @@ var AutoMLClient = class {
576
537
  await new Promise((resolve) => setTimeout(resolve, pollInterval));
577
538
  }
578
539
  }
540
+ mapTrainingJob(data, fallbackMaxTrials) {
541
+ return {
542
+ id: data.id ?? data.job_id,
543
+ name: data.name,
544
+ status: data.status,
545
+ progress: data.progress ?? 0,
546
+ phase: data.phase,
547
+ task: data.task,
548
+ current_trial: data.current_trial,
549
+ total_trials: data.total_trials ?? fallbackMaxTrials,
550
+ best_accuracy: data.best_accuracy,
551
+ eta_ms: data.eta_ms ?? data.estimated_time_remaining_ms,
552
+ error: data.error,
553
+ started_at: new Date(data.started_at ?? Date.now()),
554
+ completed_at: data.completed_at ? new Date(data.completed_at) : void 0,
555
+ model_id: data.model_id
556
+ };
557
+ }
579
558
  };
580
559
 
581
560
  // src/nlp.ts
@@ -583,32 +562,67 @@ var NLPClient = class {
583
562
  constructor(synapCores) {
584
563
  this.synapCores = synapCores;
585
564
  }
565
+ /**
566
+ * Run multiple NLP tasks in parallel and stitch them into a single
567
+ * NLPAnalysis (or array of them, matching the input shape).
568
+ */
586
569
  async analyze(options) {
587
570
  const isBatch = Array.isArray(options.text);
588
571
  const texts = isBatch ? options.text : [options.text];
589
- const { data } = await this.synapCores._getHttpClient().post("/ai/analyze", {
590
- texts,
591
- tasks: options.tasks || ["sentiment", "entities", "keywords"],
592
- language: options.language
593
- });
594
- const results = data.results.map((r) => ({
595
- sentiment: r.sentiment ? {
596
- label: r.sentiment.label,
597
- score: r.sentiment.score,
598
- confidence: r.sentiment.confidence
599
- } : void 0,
600
- entities: r.entities ? r.entities.map((e) => ({
601
- text: e.text,
602
- type: e.type,
603
- start: e.start,
604
- end: e.end,
605
- score: e.score
606
- })) : void 0,
607
- summary: r.summary,
608
- keywords: r.keywords,
609
- language: r.language
610
- }));
611
- return isBatch ? results : results[0];
572
+ const tasks = options.tasks || ["sentiment", "entities", "summarize"];
573
+ const http = this.synapCores._getHttpClient();
574
+ const wantSentiment = tasks.includes("sentiment");
575
+ const wantEntities = tasks.includes("entities");
576
+ const wantSummarize = tasks.includes("summarize") || tasks.includes("summary");
577
+ const wantKeywords = tasks.includes("keywords");
578
+ const results = await Promise.all(
579
+ texts.map(async (text) => {
580
+ const out = {};
581
+ const calls = [];
582
+ if (wantSentiment) {
583
+ calls.push(
584
+ http.post("/ai/sentiment", { texts: [text], language: options.language }).then(({ data }) => {
585
+ const s = (data.sentiments ?? [])[0] ?? data.sentiment ?? data;
586
+ if (s) {
587
+ out.sentiment = {
588
+ label: s.label,
589
+ score: s.score,
590
+ confidence: s.confidence
591
+ };
592
+ }
593
+ }).catch(() => void 0)
594
+ );
595
+ }
596
+ if (wantEntities) {
597
+ calls.push(
598
+ http.post("/ai/entities", { text, language: options.language }).then(({ data }) => {
599
+ const arr = data.entities ?? [];
600
+ out.entities = arr.map((e) => ({
601
+ text: e.text,
602
+ type: e.type,
603
+ start: e.start,
604
+ end: e.end,
605
+ score: e.score
606
+ }));
607
+ }).catch(() => void 0)
608
+ );
609
+ }
610
+ if (wantSummarize) {
611
+ calls.push(
612
+ http.post("/ai/summarize", { text }).then(({ data }) => {
613
+ out.summary = data.summary;
614
+ }).catch(() => void 0)
615
+ );
616
+ }
617
+ if (wantKeywords) {
618
+ out.keywords = void 0;
619
+ }
620
+ await Promise.all(calls);
621
+ return out;
622
+ })
623
+ );
624
+ if (isBatch) return results;
625
+ return results[0] ?? {};
612
626
  }
613
627
  async summarize(options) {
614
628
  const { data } = await this.synapCores._getHttpClient().post("/ai/summarize", {
@@ -623,7 +637,7 @@ var NLPClient = class {
623
637
  text,
624
638
  entity_types: entityTypes
625
639
  });
626
- return data.entities.map((e) => ({
640
+ return (data.entities ?? []).map((e) => ({
627
641
  text: e.text,
628
642
  type: e.type,
629
643
  start: e.start,
@@ -637,7 +651,7 @@ var NLPClient = class {
637
651
  const { data } = await this.synapCores._getHttpClient().post("/ai/sentiment", {
638
652
  texts
639
653
  });
640
- const results = data.sentiments.map((s) => ({
654
+ const results = (data.sentiments ?? []).map((s) => ({
641
655
  label: s.label,
642
656
  score: s.score,
643
657
  confidence: s.confidence
@@ -654,6 +668,22 @@ var NLPClient = class {
654
668
  });
655
669
  return isBatch ? data.classifications : data.classifications[0];
656
670
  }
671
+ /**
672
+ * Question-answering against an optional context window.
673
+ */
674
+ async qa(question, context, opts = {}) {
675
+ const { data } = await this.synapCores._getHttpClient().post("/ai/qa", {
676
+ question,
677
+ context,
678
+ max_answer_tokens: opts.maxAnswerTokens
679
+ });
680
+ return {
681
+ answer: data.answer ?? data.text ?? "",
682
+ score: data.score ?? data.confidence,
683
+ start: data.start,
684
+ end: data.end
685
+ };
686
+ }
657
687
  };
658
688
 
659
689
  // src/recipes.ts
@@ -797,11 +827,142 @@ var RecipeClient = class {
797
827
  };
798
828
  }
799
829
  /**
800
- * List available recipe categories
830
+ * List available recipe categories with counts.
831
+ *
832
+ * v0.2.0: gateway path is /recipes/categories/counts.
833
+ * Returns the array of category names; for the {category, count}
834
+ * payload use `listCategoriesWithCounts`.
801
835
  */
802
836
  async listCategories() {
803
- const { data } = await this.synapCores._getHttpClient().get("/recipes/categories");
804
- return data.categories || [];
837
+ const data = await this.listCategoriesWithCounts();
838
+ return data.map((c) => c.category);
839
+ }
840
+ async listCategoriesWithCounts() {
841
+ const { data } = await this.synapCores._getHttpClient().get(
842
+ "/recipes/categories/counts"
843
+ );
844
+ const arr = data.categories ?? data ?? [];
845
+ return arr.map((c) => ({
846
+ category: c.category ?? c.name ?? c,
847
+ count: c.count ?? c.recipe_count ?? 0
848
+ }));
849
+ }
850
+ /**
851
+ * Validate a recipe payload before saving/executing.
852
+ */
853
+ async validate(body) {
854
+ const { data } = await this.synapCores._getHttpClient().post("/recipes/validate", body);
855
+ return {
856
+ is_valid: data.is_valid ?? data.valid ?? false,
857
+ errors: data.errors ?? [],
858
+ warnings: data.warnings ?? []
859
+ };
860
+ }
861
+ /**
862
+ * Get execution history for a specific recipe.
863
+ */
864
+ async getHistory(id) {
865
+ const { data } = await this.synapCores._getHttpClient().get(`/recipes/${id}/history`);
866
+ const arr = data.history ?? data.executions ?? data ?? [];
867
+ return arr.map((row) => ({
868
+ id: row.id ?? row.execution_id ?? "",
869
+ success: row.success ?? row.status === "completed",
870
+ results: row.results,
871
+ error: row.error,
872
+ execution_time_ms: row.execution_time_ms ?? row.took_ms ?? 0,
873
+ statements_executed: row.statements_executed ?? 0
874
+ }));
875
+ }
876
+ /**
877
+ * List built-in / shared recipe templates.
878
+ */
879
+ async listTemplates() {
880
+ const { data } = await this.synapCores._getHttpClient().get("/recipes/templates");
881
+ return (data.templates ?? data ?? []).map((t) => ({
882
+ id: t.id,
883
+ name: t.name,
884
+ description: t.description ?? "",
885
+ category: t.category ?? "template",
886
+ tags: t.tags ?? [],
887
+ created_at: new Date(t.created_at ?? Date.now()),
888
+ updated_at: new Date(t.updated_at ?? t.created_at ?? Date.now()),
889
+ author: t.author,
890
+ execution_count: t.execution_count
891
+ }));
892
+ }
893
+ /**
894
+ * Get a specific recipe template.
895
+ */
896
+ async getTemplate(id) {
897
+ const { data } = await this.synapCores._getHttpClient().get(`/recipes/templates/${id}`);
898
+ return {
899
+ id: data.id,
900
+ name: data.name,
901
+ description: data.description ?? "",
902
+ category: data.category ?? "template",
903
+ content: data.content ?? "",
904
+ tags: data.tags ?? [],
905
+ parameters: data.parameters ?? [],
906
+ created_at: new Date(data.created_at ?? Date.now()),
907
+ updated_at: new Date(data.updated_at ?? data.created_at ?? Date.now()),
908
+ author: data.author,
909
+ execution_count: data.execution_count,
910
+ version: data.version
911
+ };
912
+ }
913
+ /**
914
+ * Execute a recipe template with a parameter set.
915
+ */
916
+ async executeTemplate(id, params = {}) {
917
+ const { data } = await this.synapCores._getHttpClient().post(
918
+ `/recipes/templates/${id}/execute`,
919
+ { parameters: params }
920
+ );
921
+ return {
922
+ id: data.id ?? data.execution_id ?? "",
923
+ success: data.success ?? false,
924
+ results: data.results,
925
+ error: data.error,
926
+ execution_time_ms: data.execution_time_ms ?? data.took_ms ?? 0,
927
+ statements_executed: data.statements_executed ?? 0
928
+ };
929
+ }
930
+ /**
931
+ * List all recipe executions across recipes.
932
+ */
933
+ async listExecutions(options = {}) {
934
+ const params = new URLSearchParams();
935
+ if (options.limit) params.append("limit", options.limit.toString());
936
+ if (options.status) params.append("status", options.status);
937
+ const qs = params.toString();
938
+ const { data } = await this.synapCores._getHttpClient().get(
939
+ `/recipes/executions${qs ? `?${qs}` : ""}`
940
+ );
941
+ const arr = data.executions ?? data ?? [];
942
+ return arr.map((row) => ({
943
+ id: row.id ?? row.execution_id ?? "",
944
+ success: row.success ?? row.status === "completed",
945
+ results: row.results,
946
+ error: row.error,
947
+ execution_time_ms: row.execution_time_ms ?? row.took_ms ?? 0,
948
+ statements_executed: row.statements_executed ?? 0
949
+ }));
950
+ }
951
+ /**
952
+ * Get a single execution by ID.
953
+ */
954
+ async getExecution(id) {
955
+ const { data } = await this.synapCores._getHttpClient().get(
956
+ `/recipes/executions/${id}`
957
+ );
958
+ return {
959
+ id: data.id ?? id,
960
+ success: data.success ?? data.status === "completed",
961
+ results: data.results,
962
+ error: data.error,
963
+ execution_time_ms: data.execution_time_ms ?? data.took_ms ?? 0,
964
+ statements_executed: data.statements_executed ?? 0
965
+ };
805
966
  }
806
967
  };
807
968
 
@@ -811,17 +972,30 @@ var SchemaClient = class {
811
972
  this.synapCores = synapCores;
812
973
  }
813
974
  /**
814
- * List all tables in the database
975
+ * List all databases visible to the current authentication context.
976
+ */
977
+ async listDatabases() {
978
+ const { data } = await this.synapCores._getHttpClient().get("/schema/databases");
979
+ return (data.databases ?? data ?? []).map((db) => ({
980
+ name: db.name,
981
+ table_count: db.table_count,
982
+ size_bytes: db.size_bytes,
983
+ is_default: db.is_default
984
+ }));
985
+ }
986
+ /**
987
+ * List all tables in the current database.
815
988
  */
816
989
  async listTables(options = {}) {
817
990
  const params = new URLSearchParams();
818
991
  if (options.includeSystem) {
819
992
  params.append("include_system", "true");
820
993
  }
994
+ const qs = params.toString();
821
995
  const { data } = await this.synapCores._getHttpClient().get(
822
- `/schema/tables?${params.toString()}`
996
+ `/schema/tables${qs ? `?${qs}` : ""}`
823
997
  );
824
- return (data.tables || data).map((table) => ({
998
+ return (data.tables || data || []).map((table) => ({
825
999
  name: table.name,
826
1000
  type: table.type || "table",
827
1001
  column_count: table.column_count || 0,
@@ -833,24 +1007,33 @@ var SchemaClient = class {
833
1007
  }));
834
1008
  }
835
1009
  /**
836
- * Get complete schema for a specific table
1010
+ * Get complete schema for a specific table.
1011
+ *
1012
+ * Combines /schema/tables/:t with /schema/tables/:t/columns and
1013
+ * /schema/tables/:t/indexes side-channels because the table-only payload
1014
+ * does not always include columns and indexes inline.
837
1015
  */
838
1016
  async getTable(tableName) {
839
- const { data } = await this.synapCores._getHttpClient().get(
840
- `/schema/tables/${tableName}`
841
- );
1017
+ const [tableRes, colsRes, idxRes] = await Promise.all([
1018
+ this.synapCores._getHttpClient().get(`/schema/tables/${tableName}`),
1019
+ this.synapCores._getHttpClient().get(`/schema/tables/${tableName}/columns`),
1020
+ this.synapCores._getHttpClient().get(`/schema/tables/${tableName}/indexes`)
1021
+ ]);
1022
+ const table = tableRes.data ?? {};
1023
+ const columns = colsRes.data?.columns ?? colsRes.data ?? [];
1024
+ const indexes = idxRes.data?.indexes ?? idxRes.data ?? [];
842
1025
  return {
843
1026
  table: {
844
- name: data.name,
845
- type: data.type || "table",
846
- column_count: data.columns?.length || 0,
847
- row_count: data.row_count,
848
- size_bytes: data.size_bytes,
849
- created_at: data.created_at ? new Date(data.created_at) : void 0,
850
- updated_at: data.updated_at ? new Date(data.updated_at) : void 0,
851
- comment: data.comment
1027
+ name: table.name ?? tableName,
1028
+ type: table.type || "table",
1029
+ column_count: columns.length,
1030
+ row_count: table.row_count,
1031
+ size_bytes: table.size_bytes,
1032
+ created_at: table.created_at ? new Date(table.created_at) : void 0,
1033
+ updated_at: table.updated_at ? new Date(table.updated_at) : void 0,
1034
+ comment: table.comment
852
1035
  },
853
- columns: (data.columns || []).map((col) => ({
1036
+ columns: columns.map((col) => ({
854
1037
  name: col.name,
855
1038
  data_type: col.data_type || col.type,
856
1039
  nullable: col.nullable !== false,
@@ -862,7 +1045,7 @@ var SchemaClient = class {
862
1045
  comment: col.comment,
863
1046
  ordinal_position: col.ordinal_position || col.position
864
1047
  })),
865
- indexes: (data.indexes || []).map((idx) => ({
1048
+ indexes: indexes.map((idx) => ({
866
1049
  name: idx.name,
867
1050
  table: idx.table || tableName,
868
1051
  type: idx.type || "btree",
@@ -872,8 +1055,8 @@ var SchemaClient = class {
872
1055
  size_bytes: idx.size_bytes,
873
1056
  created_at: idx.created_at ? new Date(idx.created_at) : void 0
874
1057
  })),
875
- constraints: data.constraints || [],
876
- relationships: (data.relationships || []).map((rel) => ({
1058
+ constraints: table.constraints || [],
1059
+ relationships: (table.relationships || []).map((rel) => ({
877
1060
  type: rel.type,
878
1061
  from_table: rel.from_table || rel.source_table,
879
1062
  from_column: rel.from_column || rel.source_column,
@@ -884,106 +1067,186 @@ var SchemaClient = class {
884
1067
  };
885
1068
  }
886
1069
  /**
887
- * Get columns for a specific table
1070
+ * Get columns for a specific table.
888
1071
  */
889
1072
  async getColumns(tableName) {
890
- const schema = await this.getTable(tableName);
891
- return schema.columns;
1073
+ const { data } = await this.synapCores._getHttpClient().get(
1074
+ `/schema/tables/${tableName}/columns`
1075
+ );
1076
+ const cols = data.columns ?? data ?? [];
1077
+ return cols.map((col) => ({
1078
+ name: col.name,
1079
+ data_type: col.data_type || col.type,
1080
+ nullable: col.nullable !== false,
1081
+ default_value: col.default_value || col.default,
1082
+ is_primary_key: col.is_primary_key || col.primary_key,
1083
+ is_unique: col.is_unique || col.unique,
1084
+ is_indexed: col.is_indexed || col.indexed,
1085
+ foreign_key: col.foreign_key,
1086
+ comment: col.comment,
1087
+ ordinal_position: col.ordinal_position || col.position
1088
+ }));
892
1089
  }
893
1090
  /**
894
- * Get indexes for a specific table
1091
+ * Get indexes for a specific table.
895
1092
  */
896
1093
  async getIndexes(tableName) {
897
- const schema = await this.getTable(tableName);
898
- return schema.indexes;
899
- }
900
- /**
901
- * Get all relationships in the database
902
- */
903
- async getRelationships() {
904
- const { data } = await this.synapCores._getHttpClient().get("/schema/relationships");
905
- return (data.relationships || data).map((rel) => ({
906
- type: rel.type,
907
- from_table: rel.from_table || rel.source_table,
908
- from_column: rel.from_column || rel.source_column,
909
- to_table: rel.to_table || rel.target_table,
910
- to_column: rel.to_column || rel.target_column,
911
- name: rel.name
1094
+ const { data } = await this.synapCores._getHttpClient().get(
1095
+ `/schema/tables/${tableName}/indexes`
1096
+ );
1097
+ const idxs = data.indexes ?? data ?? [];
1098
+ return idxs.map((idx) => ({
1099
+ name: idx.name,
1100
+ table: idx.table || tableName,
1101
+ type: idx.type || "btree",
1102
+ columns: idx.columns || [],
1103
+ is_unique: idx.is_unique || idx.unique || false,
1104
+ is_primary: idx.is_primary || idx.primary || false,
1105
+ size_bytes: idx.size_bytes,
1106
+ created_at: idx.created_at ? new Date(idx.created_at) : void 0
912
1107
  }));
913
1108
  }
914
1109
  /**
915
- * Get schema statistics
1110
+ * Preview rows from a table without writing SQL.
1111
+ *
1112
+ * GET /schema/tables/:t/data?limit=&offset=
916
1113
  */
917
- async getStatistics() {
918
- const { data } = await this.synapCores._getHttpClient().get("/schema/statistics");
1114
+ async previewTable(tableName, opts = {}) {
1115
+ const params = new URLSearchParams();
1116
+ if (opts.limit !== void 0) params.append("limit", String(opts.limit));
1117
+ if (opts.offset !== void 0) params.append("offset", String(opts.offset));
1118
+ const qs = params.toString();
1119
+ const { data } = await this.synapCores._getHttpClient().get(
1120
+ `/schema/tables/${tableName}/data${qs ? `?${qs}` : ""}`
1121
+ );
919
1122
  return {
920
- table_count: data.table_count || 0,
921
- view_count: data.view_count || 0,
922
- index_count: data.index_count || 0,
923
- relationship_count: data.relationship_count || 0,
924
- total_size_bytes: data.total_size_bytes || 0,
925
- total_rows: data.total_rows || 0,
926
- version: data.version,
927
- analyzed_at: data.analyzed_at ? new Date(data.analyzed_at) : void 0
1123
+ columns: data.columns ?? [],
1124
+ rows: data.rows ?? data.data ?? [],
1125
+ total_rows: data.total_rows ?? data.total
928
1126
  };
929
1127
  }
930
- /**
931
- * Validate a schema definition
932
- */
933
- async validateSchema(schema) {
934
- const { data } = await this.synapCores._getHttpClient().post("/schema/validate", {
935
- schema
936
- });
937
- return {
938
- is_valid: data.is_valid || data.valid,
939
- errors: data.errors || [],
940
- warnings: data.warnings || []
941
- };
1128
+ };
1129
+
1130
+ // src/errors.ts
1131
+ var SynapCoresError = class _SynapCoresError extends Error {
1132
+ constructor(message, code, details) {
1133
+ super(message);
1134
+ this.name = "SynapCoresError";
1135
+ this.code = code;
1136
+ this.details = details;
1137
+ if (Error.captureStackTrace) {
1138
+ Error.captureStackTrace(this, _SynapCoresError);
1139
+ }
942
1140
  }
943
- /**
944
- * Compare two schemas
945
- */
946
- async compareSchemas(schema1, schema2) {
947
- const { data } = await this.synapCores._getHttpClient().post("/schema/compare", {
948
- schema1,
949
- schema2
950
- });
951
- return {
952
- differences: data.differences || [],
953
- added: data.added || [],
954
- removed: data.removed || [],
955
- modified: data.modified || []
956
- };
1141
+ };
1142
+ var ConnectionError = class extends SynapCoresError {
1143
+ constructor(message, details) {
1144
+ super(message, "CONNECTION_ERROR", details);
1145
+ this.name = "ConnectionError";
957
1146
  }
958
- /**
959
- * Generate SQL DDL for a table
960
- */
961
- async generateDDL(tableName) {
962
- const { data } = await this.synapCores._getHttpClient().get(
963
- `/schema/tables/${tableName}/ddl`
964
- );
965
- return data.ddl || data.sql;
1147
+ };
1148
+ var AuthenticationError = class extends SynapCoresError {
1149
+ constructor(message, details) {
1150
+ super(message, "AUTH_ERROR", details);
1151
+ this.name = "AuthenticationError";
966
1152
  }
967
- /**
968
- * Analyze table and update statistics
969
- */
970
- async analyzeTable(tableName) {
971
- await this.synapCores._getHttpClient().post(`/schema/tables/${tableName}/analyze`);
1153
+ };
1154
+ var ValidationError = class extends SynapCoresError {
1155
+ constructor(message, details) {
1156
+ super(message, "VALIDATION_ERROR", details);
1157
+ this.name = "ValidationError";
1158
+ }
1159
+ };
1160
+ var NotFoundError = class extends SynapCoresError {
1161
+ constructor(message, details) {
1162
+ super(message, "NOT_FOUND", details);
1163
+ this.name = "NotFoundError";
1164
+ }
1165
+ };
1166
+ var ServerError = class extends SynapCoresError {
1167
+ constructor(message, details) {
1168
+ super(message, "SERVER_ERROR", details);
1169
+ this.name = "ServerError";
1170
+ }
1171
+ };
1172
+ var TimeoutError = class extends SynapCoresError {
1173
+ constructor(message, details) {
1174
+ super(message, "TIMEOUT_ERROR", details);
1175
+ this.name = "TimeoutError";
1176
+ }
1177
+ };
1178
+ var RateLimitError = class extends SynapCoresError {
1179
+ constructor(message, retryAfter, details) {
1180
+ super(message, "RATE_LIMIT_ERROR", details);
1181
+ this.name = "RateLimitError";
1182
+ this.retryAfter = retryAfter;
1183
+ }
1184
+ };
1185
+ var SQLError = class extends SynapCoresError {
1186
+ constructor(message, code, severity = "ERROR", position, hint, detail, details) {
1187
+ super(message, code, details);
1188
+ this.name = "SQLError";
1189
+ this.severity = severity;
1190
+ this.position = position;
1191
+ this.hint = hint;
1192
+ this.detail = detail;
1193
+ }
1194
+ };
1195
+ var VectorError = class extends SynapCoresError {
1196
+ constructor(message, code, vectorDimensions, expectedDimensions, operation, details) {
1197
+ super(message, code, details);
1198
+ this.name = "VectorError";
1199
+ this.vectorDimensions = vectorDimensions;
1200
+ this.expectedDimensions = expectedDimensions;
1201
+ this.operation = operation;
1202
+ }
1203
+ };
1204
+ var TransactionError = class extends SynapCoresError {
1205
+ constructor(message, code, transactionId, transactionState, details) {
1206
+ super(message, code, details);
1207
+ this.name = "TransactionError";
1208
+ this.transactionId = transactionId;
1209
+ this.transactionState = transactionState;
1210
+ }
1211
+ };
1212
+ var BatchOperationError = class extends SynapCoresError {
1213
+ constructor(message, code, failedItems, totalProcessed, successfulCount, details) {
1214
+ super(message, code, details);
1215
+ this.name = "BatchOperationError";
1216
+ this.failedItems = failedItems;
1217
+ this.totalProcessed = totalProcessed;
1218
+ this.successfulCount = successfulCount;
972
1219
  }
973
1220
  };
974
1221
 
975
1222
  // src/import.ts
1223
+ var NOT_SUPPORTED_MSG = "not supported in v1.5.0-ce \u2014 use SynapCores.executeQuery with COPY ... or process locally";
976
1224
  var ImportExportClient = class {
977
1225
  constructor(synapCores) {
978
1226
  this.synapCores = synapCores;
979
1227
  }
980
1228
  /**
981
- * Import data into a table
1229
+ * Import data into a table.
1230
+ *
1231
+ * Routes to /v1/data/import/csv or /v1/data/import/json based on
1232
+ * `options.format`. NDJSON falls under the JSON endpoint.
982
1233
  */
983
1234
  async import(options) {
984
- const formData = new FormData();
1235
+ const fmt = options.format;
1236
+ if (fmt !== "csv" && fmt !== "json" && fmt !== "ndjson") {
1237
+ throw new ValidationError(
1238
+ `Unsupported import format '${fmt}' \u2014 gateway v1.5.0-ce only accepts csv or json`
1239
+ );
1240
+ }
1241
+ const path = fmt === "csv" ? "/data/import/csv" : "/data/import/json";
1242
+ let FormDataClass;
1243
+ try {
1244
+ FormDataClass = __require("form-data");
1245
+ } catch {
1246
+ FormDataClass = globalThis.FormData;
1247
+ }
1248
+ const formData = new FormDataClass();
985
1249
  formData.append("table", options.table);
986
- formData.append("format", options.format);
987
1250
  if (options.mode) formData.append("mode", options.mode);
988
1251
  if (options.column_mapping) {
989
1252
  formData.append("column_mapping", JSON.stringify(options.column_mapping));
@@ -992,7 +1255,9 @@ var ImportExportClient = class {
992
1255
  formData.append("skip_header", options.skip_header.toString());
993
1256
  }
994
1257
  if (options.delimiter) formData.append("delimiter", options.delimiter);
995
- if (options.batch_size) formData.append("batch_size", options.batch_size.toString());
1258
+ if (options.batch_size) {
1259
+ formData.append("batch_size", options.batch_size.toString());
1260
+ }
996
1261
  if (options.continue_on_error !== void 0) {
997
1262
  formData.append("continue_on_error", options.continue_on_error.toString());
998
1263
  }
@@ -1000,228 +1265,88 @@ var ImportExportClient = class {
1000
1265
  formData.append("primary_keys", JSON.stringify(options.primary_keys));
1001
1266
  }
1002
1267
  if (Buffer.isBuffer(options.data)) {
1003
- formData.append("file", new Blob([options.data]), "data");
1268
+ formData.append("file", options.data, { filename: `data.${fmt}` });
1004
1269
  } else {
1005
- formData.append("data", options.data);
1270
+ formData.append("file", Buffer.from(String(options.data)), {
1271
+ filename: `data.${fmt}`
1272
+ });
1006
1273
  }
1007
- const { data } = await this.synapCores._getHttpClient().post("/import", formData, {
1008
- headers: {
1009
- "Content-Type": "multipart/form-data"
1010
- }
1274
+ const headers = {};
1275
+ if (typeof formData.getHeaders === "function") {
1276
+ Object.assign(headers, formData.getHeaders());
1277
+ } else {
1278
+ headers["Content-Type"] = "multipart/form-data";
1279
+ }
1280
+ const { data } = await this.synapCores._getHttpClient().post(path, formData, {
1281
+ headers,
1282
+ maxBodyLength: Infinity,
1283
+ maxContentLength: Infinity
1011
1284
  });
1012
1285
  return {
1013
- id: data.id || data.job_id,
1014
- success: data.success,
1015
- rows_processed: data.rows_processed || 0,
1016
- rows_imported: data.rows_imported || 0,
1017
- rows_failed: data.rows_failed || 0,
1018
- duration_ms: data.duration_ms || data.took_ms || 0,
1019
- errors: data.errors || [],
1020
- warnings: data.warnings || []
1286
+ id: data.id ?? data.job_id ?? "",
1287
+ success: data.success ?? true,
1288
+ rows_processed: data.rows_processed ?? 0,
1289
+ rows_imported: data.rows_imported ?? data.rows_processed ?? 0,
1290
+ rows_failed: data.rows_failed ?? 0,
1291
+ duration_ms: data.duration_ms ?? data.took_ms ?? 0,
1292
+ errors: data.errors ?? [],
1293
+ warnings: data.warnings ?? []
1021
1294
  };
1022
1295
  }
1023
- /**
1024
- * Export data from a table or query
1025
- */
1026
- async export(options) {
1027
- const { data } = await this.synapCores._getHttpClient().post("/export", {
1028
- source: options.source,
1029
- format: options.format,
1030
- destination: options.destination || "response",
1031
- columns: options.columns,
1032
- filter: options.filter,
1033
- order_by: options.order_by,
1034
- limit: options.limit,
1035
- include_header: options.include_header,
1036
- delimiter: options.delimiter,
1037
- compress: options.compress
1038
- });
1039
- return {
1040
- id: data.id || data.job_id,
1041
- success: data.success,
1042
- rows_exported: data.rows_exported || 0,
1043
- duration_ms: data.duration_ms || data.took_ms || 0,
1044
- file_path: data.file_path,
1045
- data: data.data,
1046
- size_bytes: data.size_bytes,
1047
- download_url: data.download_url,
1048
- expires_at: data.expires_at ? new Date(data.expires_at) : void 0
1049
- };
1296
+ // ---------------------------------------------------------------------
1297
+ // Removed methods: every export route, every job-tracking route, bulk
1298
+ // import, validate, template — none of those endpoints exist in the
1299
+ // v1.5.0-ce gateway. We keep the shape so old callers get a clear error
1300
+ // instead of a silent 404.
1301
+ // ---------------------------------------------------------------------
1302
+ async export(_options) {
1303
+ throw new ValidationError(`export() ${NOT_SUPPORTED_MSG}`);
1050
1304
  }
1051
- /**
1052
- * Get import job status
1053
- */
1054
- async getImportStatus(jobId) {
1055
- const { data } = await this.synapCores._getHttpClient().get(`/import/${jobId}/status`);
1056
- return {
1057
- id: data.id || jobId,
1058
- status: data.status,
1059
- progress: data.progress || 0,
1060
- phase: data.phase,
1061
- rows_processed: data.rows_processed,
1062
- eta_ms: data.eta_ms || data.estimated_time_remaining_ms,
1063
- error: data.error,
1064
- started_at: data.started_at ? new Date(data.started_at) : void 0,
1065
- completed_at: data.completed_at ? new Date(data.completed_at) : void 0
1066
- };
1305
+ async getImportStatus(_jobId) {
1306
+ throw new ValidationError(`getImportStatus() ${NOT_SUPPORTED_MSG}`);
1067
1307
  }
1068
- /**
1069
- * Get export job status
1070
- */
1071
- async getExportStatus(jobId) {
1072
- const { data } = await this.synapCores._getHttpClient().get(`/export/${jobId}/status`);
1073
- return {
1074
- id: data.id || jobId,
1075
- status: data.status,
1076
- progress: data.progress || 0,
1077
- phase: data.phase,
1078
- rows_exported: data.rows_exported,
1079
- eta_ms: data.eta_ms || data.estimated_time_remaining_ms,
1080
- error: data.error,
1081
- started_at: data.started_at ? new Date(data.started_at) : void 0,
1082
- completed_at: data.completed_at ? new Date(data.completed_at) : void 0
1083
- };
1308
+ async getExportStatus(_jobId) {
1309
+ throw new ValidationError(`getExportStatus() ${NOT_SUPPORTED_MSG}`);
1084
1310
  }
1085
- /**
1086
- * Cancel an import job
1087
- */
1088
- async cancelImport(jobId) {
1089
- await this.synapCores._getHttpClient().post(`/import/${jobId}/cancel`);
1311
+ async cancelImport(_jobId) {
1312
+ throw new ValidationError(`cancelImport() ${NOT_SUPPORTED_MSG}`);
1090
1313
  }
1091
- /**
1092
- * Cancel an export job
1093
- */
1094
- async cancelExport(jobId) {
1095
- await this.synapCores._getHttpClient().post(`/export/${jobId}/cancel`);
1314
+ async cancelExport(_jobId) {
1315
+ throw new ValidationError(`cancelExport() ${NOT_SUPPORTED_MSG}`);
1096
1316
  }
1097
- /**
1098
- * Import data from multiple sources in bulk
1099
- */
1100
- async bulkImport(options) {
1101
- const { data } = await this.synapCores._getHttpClient().post("/import/bulk", {
1102
- jobs: options.jobs,
1103
- parallel: options.parallel || false,
1104
- stop_on_error: options.stop_on_error || false
1105
- });
1106
- return {
1107
- id: data.id || data.bulk_id,
1108
- success: data.success,
1109
- results: data.results || [],
1110
- total_rows_imported: data.total_rows_imported || 0,
1111
- total_duration_ms: data.total_duration_ms || data.took_ms || 0
1112
- };
1317
+ async bulkImport(_options) {
1318
+ throw new ValidationError(`bulkImport() ${NOT_SUPPORTED_MSG}`);
1113
1319
  }
1114
- /**
1115
- * Validate data before import
1116
- */
1117
- async validateData(options) {
1118
- const { data } = await this.synapCores._getHttpClient().post("/import/validate", {
1119
- table: options.table,
1120
- data: options.data,
1121
- mode: options.mode || "strict",
1122
- check_foreign_keys: options.check_foreign_keys,
1123
- check_unique: options.check_unique
1124
- });
1125
- return {
1126
- is_valid: data.is_valid || data.valid,
1127
- errors: data.errors || [],
1128
- warnings: data.warnings || [],
1129
- rows_validated: data.rows_validated || options.data.length
1130
- };
1320
+ async validateData(_options) {
1321
+ throw new ValidationError(`validateData() ${NOT_SUPPORTED_MSG}`);
1131
1322
  }
1132
- /**
1133
- * Get import template for a table
1134
- */
1135
- async getImportTemplate(tableName, format = "csv") {
1136
- const { data } = await this.synapCores._getHttpClient().get(
1137
- `/import/template/${tableName}?format=${format}`
1138
- );
1139
- return data.template || data.content || data;
1323
+ async getImportTemplate(_tableName, _format = "csv") {
1324
+ throw new ValidationError(`getImportTemplate() ${NOT_SUPPORTED_MSG}`);
1140
1325
  }
1141
- /**
1142
- * List import/export jobs
1143
- */
1144
- async listJobs(options = {}) {
1145
- const params = new URLSearchParams();
1146
- if (options.type) params.append("type", options.type);
1147
- if (options.status) params.append("status", options.status);
1148
- if (options.limit) params.append("limit", options.limit.toString());
1149
- const { data } = await this.synapCores._getHttpClient().get(
1150
- `/import/jobs?${params.toString()}`
1151
- );
1152
- return (data.jobs || data).map((job) => ({
1153
- id: job.id,
1154
- status: job.status,
1155
- progress: job.progress || 0,
1156
- phase: job.phase,
1157
- rows_processed: job.rows_processed,
1158
- rows_exported: job.rows_exported,
1159
- eta_ms: job.eta_ms,
1160
- error: job.error,
1161
- started_at: job.started_at ? new Date(job.started_at) : void 0,
1162
- completed_at: job.completed_at ? new Date(job.completed_at) : void 0
1163
- }));
1326
+ async listJobs(_options = {}) {
1327
+ throw new ValidationError(`listJobs() ${NOT_SUPPORTED_MSG}`);
1164
1328
  }
1165
- /**
1166
- * Download exported data
1167
- */
1168
- async downloadExport(jobId) {
1169
- const { data } = await this.synapCores._getHttpClient().get(`/export/${jobId}/download`, {
1170
- responseType: "arraybuffer"
1171
- });
1172
- return Buffer.from(data);
1329
+ async downloadExport(_jobId) {
1330
+ throw new ValidationError(`downloadExport() ${NOT_SUPPORTED_MSG}`);
1173
1331
  }
1174
- /**
1175
- * Stream import data (for large files)
1176
- */
1177
- async streamImport(options, onProgress) {
1178
- const result = await this.import(options);
1179
- const jobId = result.id;
1180
- if (onProgress) {
1181
- const pollInterval = setInterval(async () => {
1182
- try {
1183
- const status = await this.getImportStatus(jobId);
1184
- onProgress(status);
1185
- if (status.status === "completed" || status.status === "failed" || status.status === "cancelled") {
1186
- clearInterval(pollInterval);
1187
- }
1188
- } catch (error) {
1189
- clearInterval(pollInterval);
1190
- }
1191
- }, 1e3);
1192
- }
1193
- return result;
1332
+ async streamImport(options, _onProgress) {
1333
+ return this.import(options);
1194
1334
  }
1195
- /**
1196
- * Stream export data (for large datasets)
1197
- */
1198
- async streamExport(options, onProgress) {
1199
- const result = await this.export(options);
1200
- const jobId = result.id;
1201
- if (onProgress) {
1202
- const pollInterval = setInterval(async () => {
1203
- try {
1204
- const status = await this.getExportStatus(jobId);
1205
- onProgress(status);
1206
- if (status.status === "completed" || status.status === "failed" || status.status === "cancelled") {
1207
- clearInterval(pollInterval);
1208
- }
1209
- } catch (error) {
1210
- clearInterval(pollInterval);
1211
- }
1212
- }, 1e3);
1213
- }
1214
- return result;
1335
+ async streamExport(_options, _onProgress) {
1336
+ throw new ValidationError(`streamExport() ${NOT_SUPPORTED_MSG}`);
1215
1337
  }
1216
1338
  };
1217
1339
 
1218
1340
  // src/integrations.ts
1341
+ var NOT_SUPPORTED = "not supported in v1.5.0-ce \u2014 see SynapCores integrations API";
1219
1342
  var IntegrationClient = class {
1220
1343
  constructor(synapCores) {
1221
1344
  this.synapCores = synapCores;
1222
1345
  }
1223
1346
  /**
1224
- * Create a new integration
1347
+ * Create a new integration. Gateway v1.5.0-ce keys integrations by
1348
+ * `type` (slug). The body still carries the type so old call sites
1349
+ * remain backwards compatible.
1225
1350
  */
1226
1351
  async create(options) {
1227
1352
  const { data } = await this.synapCores._getHttpClient().post("/integrations", {
@@ -1235,7 +1360,7 @@ var IntegrationClient = class {
1235
1360
  return this.mapIntegration(data);
1236
1361
  }
1237
1362
  /**
1238
- * List integrations with optional filters
1363
+ * List integrations (optional filters).
1239
1364
  */
1240
1365
  async list(options = {}) {
1241
1366
  const params = new URLSearchParams();
@@ -1247,79 +1372,41 @@ var IntegrationClient = class {
1247
1372
  if (options.tags && options.tags.length > 0) {
1248
1373
  params.append("tags", options.tags.join(","));
1249
1374
  }
1375
+ const qs = params.toString();
1250
1376
  const { data } = await this.synapCores._getHttpClient().get(
1251
- `/integrations?${params.toString()}`
1377
+ `/integrations${qs ? `?${qs}` : ""}`
1252
1378
  );
1253
- return (data.integrations || data).map(
1379
+ return (data.integrations || data || []).map(
1254
1380
  (integration) => this.mapIntegration(integration)
1255
1381
  );
1256
1382
  }
1257
1383
  /**
1258
- * Get a specific integration by ID
1384
+ * Get a specific integration by type-slug.
1259
1385
  */
1260
- async get(id) {
1261
- const { data } = await this.synapCores._getHttpClient().get(`/integrations/${id}`);
1386
+ async get(type) {
1387
+ const { data } = await this.synapCores._getHttpClient().get(
1388
+ `/integrations/${type}`
1389
+ );
1262
1390
  return this.mapIntegration(data);
1263
1391
  }
1264
1392
  /**
1265
- * Update an existing integration
1393
+ * Update an existing integration by type-slug.
1266
1394
  */
1267
- async update(id, updates) {
1395
+ async update(type, updates) {
1268
1396
  const { data } = await this.synapCores._getHttpClient().put(
1269
- `/integrations/${id}`,
1397
+ `/integrations/${type}`,
1270
1398
  updates
1271
1399
  );
1272
1400
  return this.mapIntegration(data);
1273
1401
  }
1274
1402
  /**
1275
- * Delete an integration
1276
- */
1277
- async delete(id) {
1278
- await this.synapCores._getHttpClient().delete(`/integrations/${id}`);
1279
- }
1280
- /**
1281
- * Activate an integration
1282
- */
1283
- async activate(id) {
1284
- const { data } = await this.synapCores._getHttpClient().post(
1285
- `/integrations/${id}/activate`
1286
- );
1287
- return this.mapIntegration(data);
1288
- }
1289
- /**
1290
- * Deactivate an integration
1291
- */
1292
- async deactivate(id) {
1293
- const { data } = await this.synapCores._getHttpClient().post(
1294
- `/integrations/${id}/deactivate`
1295
- );
1296
- return this.mapIntegration(data);
1297
- }
1298
- /**
1299
- * Execute an integration
1403
+ * Delete an integration by type-slug.
1300
1404
  */
1301
- async execute(options) {
1302
- const { data } = await this.synapCores._getHttpClient().post(
1303
- `/integrations/${options.integration}/execute`,
1304
- {
1305
- payload: options.payload,
1306
- config_override: options.config_override,
1307
- sync: options.sync !== false
1308
- }
1309
- );
1310
- return {
1311
- id: data.id || data.execution_id,
1312
- success: data.success,
1313
- response: data.response,
1314
- status_code: data.status_code,
1315
- error: data.error,
1316
- execution_time_ms: data.execution_time_ms || data.took_ms || 0,
1317
- retry_count: data.retry_count || 0,
1318
- executed_at: data.executed_at ? new Date(data.executed_at) : /* @__PURE__ */ new Date()
1319
- };
1405
+ async delete(type) {
1406
+ await this.synapCores._getHttpClient().delete(`/integrations/${type}`);
1320
1407
  }
1321
1408
  /**
1322
- * Test an integration without executing
1409
+ * Test an integration connection.
1323
1410
  */
1324
1411
  async test(options) {
1325
1412
  const { data } = await this.synapCores._getHttpClient().post(
@@ -1338,160 +1425,88 @@ var IntegrationClient = class {
1338
1425
  };
1339
1426
  }
1340
1427
  /**
1341
- * Get integration execution history
1428
+ * List supported integration types and their config schemas.
1342
1429
  */
1343
- async getExecutionHistory(integrationId, options = {}) {
1344
- const params = new URLSearchParams();
1345
- if (options.limit) params.append("limit", options.limit.toString());
1346
- if (options.offset) params.append("offset", options.offset.toString());
1347
- const { data } = await this.synapCores._getHttpClient().get(
1348
- `/integrations/${integrationId}/executions?${params.toString()}`
1349
- );
1350
- return (data.executions || data).map((exec) => ({
1351
- id: exec.id || exec.execution_id,
1352
- success: exec.success,
1353
- response: exec.response,
1354
- status_code: exec.status_code,
1355
- error: exec.error,
1356
- execution_time_ms: exec.execution_time_ms || exec.took_ms || 0,
1357
- retry_count: exec.retry_count || 0,
1358
- executed_at: exec.executed_at ? new Date(exec.executed_at) : /* @__PURE__ */ new Date()
1430
+ async listTypes() {
1431
+ const { data } = await this.synapCores._getHttpClient().get("/integrations/types");
1432
+ return (data.types ?? data ?? []).map((t) => ({
1433
+ type: t.type ?? t.name,
1434
+ display_name: t.display_name ?? t.label,
1435
+ description: t.description,
1436
+ config_schema: t.config_schema ?? t.schema
1359
1437
  }));
1360
1438
  }
1361
1439
  /**
1362
- * Get integration statistics
1440
+ * Get the integrations audit trail.
1363
1441
  */
1364
- async getStats(integrationId) {
1442
+ async audit(options = {}) {
1443
+ const params = new URLSearchParams();
1444
+ if (options.limit) params.append("limit", options.limit.toString());
1445
+ if (options.type) params.append("type", options.type);
1446
+ const qs = params.toString();
1365
1447
  const { data } = await this.synapCores._getHttpClient().get(
1366
- `/integrations/${integrationId}/stats`
1448
+ `/integrations/audit${qs ? `?${qs}` : ""}`
1367
1449
  );
1368
- return {
1369
- integration_id: integrationId,
1370
- total_executions: data.total_executions || 0,
1371
- successful_executions: data.successful_executions || 0,
1372
- failed_executions: data.failed_executions || 0,
1373
- avg_execution_time_ms: data.avg_execution_time_ms || 0,
1374
- executions_24h: data.executions_24h || 0,
1375
- uptime_percentage: data.uptime_percentage || 0,
1376
- last_success_at: data.last_success_at ? new Date(data.last_success_at) : void 0,
1377
- last_error_at: data.last_error_at ? new Date(data.last_error_at) : void 0
1378
- };
1450
+ return (data.entries ?? data.audit ?? data ?? []).map((row) => ({
1451
+ id: row.id,
1452
+ type: row.type ?? row.integration_type,
1453
+ action: row.action ?? row.event,
1454
+ user: row.user ?? row.actor,
1455
+ timestamp: new Date(row.timestamp ?? row.created_at ?? Date.now()),
1456
+ details: row.details ?? row.data
1457
+ }));
1379
1458
  }
1380
- /**
1381
- * Create a webhook for an integration
1382
- */
1383
- async createWebhook(options) {
1384
- const { data } = await this.synapCores._getHttpClient().post("/integrations/webhooks", {
1385
- integration_id: options.integration_id,
1386
- event: options.event,
1387
- url: options.url,
1388
- secret: options.secret,
1389
- activate: options.activate !== false
1390
- });
1391
- return {
1392
- id: data.id,
1393
- integration_id: data.integration_id,
1394
- event: data.event,
1395
- url: data.url,
1396
- active: data.active,
1397
- secret: data.secret,
1398
- created_at: new Date(data.created_at)
1399
- };
1459
+ // -------------------------------------------------------------------
1460
+ // Methods removed from v1.5.0-ce (gateway has no matching route).
1461
+ // We keep the names for backwards-compat but throw a clear error.
1462
+ // -------------------------------------------------------------------
1463
+ async activate(_type) {
1464
+ throw new ValidationError(`integrations.activate() ${NOT_SUPPORTED} \u2014 use update() with {activate:true}`);
1400
1465
  }
1401
- /**
1402
- * List webhooks for an integration
1403
- */
1404
- async listWebhooks(integrationId) {
1405
- const { data } = await this.synapCores._getHttpClient().get(
1406
- `/integrations/${integrationId}/webhooks`
1407
- );
1408
- return (data.webhooks || data).map((webhook) => ({
1409
- id: webhook.id,
1410
- integration_id: webhook.integration_id,
1411
- event: webhook.event,
1412
- url: webhook.url,
1413
- active: webhook.active,
1414
- secret: webhook.secret,
1415
- created_at: new Date(webhook.created_at)
1416
- }));
1466
+ async deactivate(_type) {
1467
+ throw new ValidationError(`integrations.deactivate() ${NOT_SUPPORTED} \u2014 use update() with {activate:false}`);
1417
1468
  }
1418
- /**
1419
- * Delete a webhook
1420
- */
1421
- async deleteWebhook(webhookId) {
1422
- await this.synapCores._getHttpClient().delete(`/integrations/webhooks/${webhookId}`);
1469
+ async execute(_options) {
1470
+ throw new ValidationError(`integrations.execute() ${NOT_SUPPORTED}`);
1423
1471
  }
1424
- /**
1425
- * Get integration events
1426
- */
1427
- async getEvents(integrationId, options = {}) {
1428
- const params = new URLSearchParams();
1429
- if (options.limit) params.append("limit", options.limit.toString());
1430
- if (options.status) params.append("status", options.status);
1431
- const { data } = await this.synapCores._getHttpClient().get(
1432
- `/integrations/${integrationId}/events?${params.toString()}`
1433
- );
1434
- return (data.events || data).map((event) => ({
1435
- id: event.id,
1436
- integration_id: event.integration_id,
1437
- event: event.event,
1438
- data: event.data,
1439
- timestamp: new Date(event.timestamp),
1440
- status: event.status,
1441
- error: event.error
1442
- }));
1472
+ async getExecutionHistory(_type, _options = {}) {
1473
+ throw new ValidationError(`integrations.getExecutionHistory() ${NOT_SUPPORTED}`);
1443
1474
  }
1444
- /**
1445
- * Get integration logs
1446
- */
1447
- async getLogs(integrationId, options = {}) {
1448
- const params = new URLSearchParams();
1449
- if (options.limit) params.append("limit", options.limit.toString());
1450
- if (options.level) params.append("level", options.level);
1451
- const { data } = await this.synapCores._getHttpClient().get(
1452
- `/integrations/${integrationId}/logs?${params.toString()}`
1453
- );
1454
- return (data.logs || data).map((log) => ({
1455
- id: log.id,
1456
- integration_id: log.integration_id,
1457
- level: log.level,
1458
- message: log.message,
1459
- data: log.data,
1460
- timestamp: new Date(log.timestamp)
1461
- }));
1475
+ async getStats(_type) {
1476
+ throw new ValidationError(`integrations.getStats() ${NOT_SUPPORTED}`);
1462
1477
  }
1463
- /**
1464
- * Retry a failed execution
1465
- */
1466
- async retryExecution(executionId) {
1467
- const { data } = await this.synapCores._getHttpClient().post(
1468
- `/integrations/executions/${executionId}/retry`
1469
- );
1470
- return {
1471
- id: data.id || data.execution_id,
1472
- success: data.success,
1473
- response: data.response,
1474
- status_code: data.status_code,
1475
- error: data.error,
1476
- execution_time_ms: data.execution_time_ms || data.took_ms || 0,
1477
- retry_count: data.retry_count || 0,
1478
- executed_at: data.executed_at ? new Date(data.executed_at) : /* @__PURE__ */ new Date()
1479
- };
1478
+ async createWebhook(_options) {
1479
+ throw new ValidationError(`integrations.createWebhook() ${NOT_SUPPORTED}`);
1480
+ }
1481
+ async listWebhooks(_type) {
1482
+ throw new ValidationError(`integrations.listWebhooks() ${NOT_SUPPORTED}`);
1483
+ }
1484
+ async deleteWebhook(_webhookId) {
1485
+ throw new ValidationError(`integrations.deleteWebhook() ${NOT_SUPPORTED}`);
1486
+ }
1487
+ async getEvents(_type, _options = {}) {
1488
+ throw new ValidationError(`integrations.getEvents() ${NOT_SUPPORTED}`);
1489
+ }
1490
+ async getLogs(_type, _options = {}) {
1491
+ throw new ValidationError(`integrations.getLogs() ${NOT_SUPPORTED}`);
1492
+ }
1493
+ async retryExecution(_executionId) {
1494
+ throw new ValidationError(`integrations.retryExecution() ${NOT_SUPPORTED}`);
1480
1495
  }
1481
1496
  /**
1482
- * Map raw integration data to Integration type
1497
+ * Map raw integration data to Integration type.
1483
1498
  */
1484
1499
  mapIntegration(data) {
1485
1500
  return {
1486
- id: data.id,
1487
- name: data.name,
1501
+ id: data.id ?? data.type,
1502
+ name: data.name ?? data.type,
1488
1503
  type: data.type,
1489
- status: data.status,
1490
- config: data.config,
1504
+ status: data.status ?? (data.active ? "active" : "inactive"),
1505
+ config: data.config ?? {},
1491
1506
  description: data.description,
1492
1507
  tags: data.tags || [],
1493
- created_at: new Date(data.created_at),
1494
- updated_at: new Date(data.updated_at),
1508
+ created_at: new Date(data.created_at ?? Date.now()),
1509
+ updated_at: new Date(data.updated_at ?? data.created_at ?? Date.now()),
1495
1510
  last_success_at: data.last_success_at ? new Date(data.last_success_at) : void 0,
1496
1511
  last_error: data.last_error,
1497
1512
  execution_count: data.execution_count
@@ -1624,18 +1639,9 @@ var BackupClient = class {
1624
1639
  completed_at: data.completed_at ? new Date(data.completed_at) : void 0
1625
1640
  };
1626
1641
  }
1627
- /**
1628
- * Cancel a backup in progress
1629
- */
1630
- async cancelBackup(backupId) {
1631
- await this.synapCores._getHttpClient().post(`/backups/${backupId}/cancel`);
1632
- }
1633
- /**
1634
- * Cancel a restore in progress
1635
- */
1636
- async cancelRestore(restoreId) {
1637
- await this.synapCores._getHttpClient().post(`/backups/restore/${restoreId}/cancel`);
1638
- }
1642
+ // cancelBackup() / cancelRestore() removed — gateway v1.5.0-ce has no
1643
+ // /backups/:id/cancel or /backups/restore/:id/cancel routes. Use
1644
+ // delete() to clean up an aborted backup record.
1639
1645
  /**
1640
1646
  * Download a backup file
1641
1647
  */
@@ -1770,155 +1776,967 @@ var BackupClient = class {
1770
1776
  };
1771
1777
  }
1772
1778
  /**
1773
- * Deactivate a schedule
1779
+ * Deactivate a schedule
1780
+ */
1781
+ async deactivateSchedule(scheduleId) {
1782
+ const { data } = await this.synapCores._getHttpClient().post(
1783
+ `/backups/schedules/${scheduleId}/deactivate`
1784
+ );
1785
+ return {
1786
+ id: data.id,
1787
+ name: data.name,
1788
+ cron: data.cron,
1789
+ backup_options: data.backup_options,
1790
+ active: data.active,
1791
+ last_run_at: data.last_run_at ? new Date(data.last_run_at) : void 0,
1792
+ next_run_at: data.next_run_at ? new Date(data.next_run_at) : void 0,
1793
+ created_at: new Date(data.created_at),
1794
+ tags: data.tags || []
1795
+ };
1796
+ }
1797
+ // getMetrics() removed — gateway v1.5.0-ce has no /backups/metrics route.
1798
+ // Aggregate metrics can be derived client-side from list().
1799
+ /**
1800
+ * Map raw backup data to Backup type
1801
+ */
1802
+ mapBackup(data) {
1803
+ return {
1804
+ id: data.id,
1805
+ name: data.name,
1806
+ description: data.description,
1807
+ type: data.type,
1808
+ status: data.status,
1809
+ size_bytes: data.size_bytes,
1810
+ compressed_size_bytes: data.compressed_size_bytes,
1811
+ table_count: data.table_count,
1812
+ created_at: new Date(data.created_at),
1813
+ completed_at: data.completed_at ? new Date(data.completed_at) : void 0,
1814
+ duration_ms: data.duration_ms || data.took_ms,
1815
+ storage: data.storage,
1816
+ storage_path: data.storage_path,
1817
+ encrypted: data.encrypted || false,
1818
+ tags: data.tags || [],
1819
+ parent_backup_id: data.parent_backup_id,
1820
+ error: data.error
1821
+ };
1822
+ }
1823
+ };
1824
+
1825
+ // src/graph.ts
1826
+ var GraphNodeApi = class {
1827
+ constructor(synapCores) {
1828
+ this.synapCores = synapCores;
1829
+ }
1830
+ async create(label, props = {}) {
1831
+ const { data } = await this.synapCores._getHttpClient().post("/graph/nodes", {
1832
+ label,
1833
+ properties: props
1834
+ });
1835
+ return this.normalize(data);
1836
+ }
1837
+ async get(id) {
1838
+ const { data } = await this.synapCores._getHttpClient().get(`/graph/nodes/${id}`);
1839
+ return this.normalize(data);
1840
+ }
1841
+ async update(id, patch) {
1842
+ const { data } = await this.synapCores._getHttpClient().patch(
1843
+ `/graph/nodes/${id}`,
1844
+ { properties: patch }
1845
+ );
1846
+ return this.normalize(data);
1847
+ }
1848
+ async delete(id) {
1849
+ await this.synapCores._getHttpClient().delete(`/graph/nodes/${id}`);
1850
+ }
1851
+ async neighbors(id, opts = {}) {
1852
+ const params = new URLSearchParams();
1853
+ if (opts.direction) params.append("direction", opts.direction);
1854
+ if (opts.limit !== void 0) params.append("limit", String(opts.limit));
1855
+ if (opts.type) params.append("type", opts.type);
1856
+ const qs = params.toString();
1857
+ const { data } = await this.synapCores._getHttpClient().get(
1858
+ `/graph/nodes/${id}/neighbors${qs ? `?${qs}` : ""}`
1859
+ );
1860
+ return {
1861
+ nodes: (data.nodes ?? []).map((n) => this.normalize(n)),
1862
+ edges: (data.edges ?? []).map((e) => this.normalizeEdge(e))
1863
+ };
1864
+ }
1865
+ normalize(data) {
1866
+ return {
1867
+ id: String(data.id ?? data.node_id ?? ""),
1868
+ label: data.label,
1869
+ labels: data.labels,
1870
+ properties: data.properties ?? data.props ?? {}
1871
+ };
1872
+ }
1873
+ normalizeEdge(data) {
1874
+ return {
1875
+ id: data.id !== void 0 ? String(data.id) : void 0,
1876
+ from: String(data.from ?? data.source ?? ""),
1877
+ to: String(data.to ?? data.target ?? ""),
1878
+ type: data.type ?? data.label ?? "",
1879
+ properties: data.properties ?? data.props ?? {}
1880
+ };
1881
+ }
1882
+ };
1883
+ var GraphEdgeApi = class {
1884
+ constructor(synapCores) {
1885
+ this.synapCores = synapCores;
1886
+ }
1887
+ async create(from, to, type, props = {}) {
1888
+ const { data } = await this.synapCores._getHttpClient().post("/graph/edges", {
1889
+ from,
1890
+ to,
1891
+ type,
1892
+ properties: props
1893
+ });
1894
+ return {
1895
+ id: data.id !== void 0 ? String(data.id) : void 0,
1896
+ from: String(data.from ?? from),
1897
+ to: String(data.to ?? to),
1898
+ type: data.type ?? type,
1899
+ properties: data.properties ?? props
1900
+ };
1901
+ }
1902
+ };
1903
+ var GraphIndexesApi = class {
1904
+ constructor(synapCores) {
1905
+ this.synapCores = synapCores;
1906
+ }
1907
+ /**
1908
+ * Create a graph index (label/property index, fulltext, or vector
1909
+ * depending on the gateway's accepted DDL strings).
1910
+ */
1911
+ async create(stmt) {
1912
+ const { data } = await this.synapCores._getHttpClient().post("/graph/indexes", {
1913
+ statement: stmt
1914
+ });
1915
+ return { name: data.name ?? data.index_name, raw: data };
1916
+ }
1917
+ };
1918
+ var GraphAlgorithmsApi = class {
1919
+ constructor(synapCores) {
1920
+ this.synapCores = synapCores;
1921
+ }
1922
+ async run(name, opts = {}) {
1923
+ const { data } = await this.synapCores._getHttpClient().post("/graph/algorithms", {
1924
+ algorithm: name,
1925
+ ...opts
1926
+ });
1927
+ return {
1928
+ algorithm: name,
1929
+ results: data.results ?? data.result ?? data,
1930
+ stats: data.stats,
1931
+ execution_time_ms: data.execution_time_ms ?? data.took_ms
1932
+ };
1933
+ }
1934
+ };
1935
+ var GraphsApi = class {
1936
+ constructor(synapCores) {
1937
+ this.synapCores = synapCores;
1938
+ }
1939
+ async list() {
1940
+ const { data } = await this.synapCores._getHttpClient().get("/graphs");
1941
+ return (data.graphs ?? data ?? []).map((g) => this.normalize(g));
1942
+ }
1943
+ async create(name, opts = {}) {
1944
+ const { data } = await this.synapCores._getHttpClient().post("/graphs", {
1945
+ name,
1946
+ description: opts.description
1947
+ });
1948
+ return this.normalize(data);
1949
+ }
1950
+ async get(name) {
1951
+ const { data } = await this.synapCores._getHttpClient().get(`/graphs/${name}`);
1952
+ return this.normalize(data);
1953
+ }
1954
+ async delete(name) {
1955
+ await this.synapCores._getHttpClient().delete(`/graphs/${name}`);
1956
+ }
1957
+ normalize(data) {
1958
+ return {
1959
+ name: data.name,
1960
+ node_count: data.node_count ?? data.nodes,
1961
+ edge_count: data.edge_count ?? data.edges,
1962
+ created_at: data.created_at ? new Date(data.created_at) : void 0,
1963
+ description: data.description
1964
+ };
1965
+ }
1966
+ };
1967
+ var GraphClient = class {
1968
+ constructor(synapCores) {
1969
+ this.synapCores = synapCores;
1970
+ this.nodes = new GraphNodeApi(synapCores);
1971
+ this.edges = new GraphEdgeApi(synapCores);
1972
+ this.indexes = new GraphIndexesApi(synapCores);
1973
+ this.algorithms = new GraphAlgorithmsApi(synapCores);
1974
+ this.graphs = new GraphsApi(synapCores);
1975
+ }
1976
+ /**
1977
+ * Run a Cypher / MATCH query.
1978
+ */
1979
+ async cypher(query, params = {}, graph) {
1980
+ const { data } = await this.synapCores._getHttpClient().post("/graph/match", {
1981
+ query,
1982
+ params,
1983
+ graph
1984
+ });
1985
+ return this.normalizeCypher(data);
1986
+ }
1987
+ /**
1988
+ * Profile a Cypher / MATCH query (returns plan/profile metadata).
1989
+ */
1990
+ async cypherProfile(query, params = {}, graph) {
1991
+ const { data } = await this.synapCores._getHttpClient().post("/graph/match/profile", {
1992
+ query,
1993
+ params,
1994
+ graph
1995
+ });
1996
+ return {
1997
+ ...this.normalizeCypher(data),
1998
+ plan: data.plan,
1999
+ profile: data.profile ?? data.profile_data
2000
+ };
2001
+ }
2002
+ /**
2003
+ * Run LLM-based extraction over text into the given graph.
2004
+ */
2005
+ async extract(req, graphName) {
2006
+ const body = typeof req === "string" ? { text: req, graph: graphName } : req;
2007
+ const { data } = await this.synapCores._getHttpClient().post("/graph/extract", body);
2008
+ return {
2009
+ nodes: (data.nodes ?? []).map((n) => ({
2010
+ id: String(n.id ?? ""),
2011
+ label: n.label,
2012
+ labels: n.labels,
2013
+ properties: n.properties ?? n.props ?? {}
2014
+ })),
2015
+ edges: (data.edges ?? []).map((e) => ({
2016
+ id: e.id !== void 0 ? String(e.id) : void 0,
2017
+ from: String(e.from ?? e.source ?? ""),
2018
+ to: String(e.to ?? e.target ?? ""),
2019
+ type: e.type ?? e.label ?? "",
2020
+ properties: e.properties ?? e.props ?? {}
2021
+ })),
2022
+ spans: data.spans
2023
+ };
2024
+ }
2025
+ normalizeCypher(data) {
2026
+ return {
2027
+ columns: data.columns ?? data.fields,
2028
+ rows: data.rows ?? data.values ?? [],
2029
+ records: data.records ?? data.results,
2030
+ stats: data.stats,
2031
+ execution_time_ms: data.execution_time_ms ?? data.took_ms
2032
+ };
2033
+ }
2034
+ };
2035
+
2036
+ // src/nl2sql.ts
2037
+ var NL2SqlClient = class {
2038
+ constructor(synapCores) {
2039
+ this.synapCores = synapCores;
2040
+ }
2041
+ /**
2042
+ * Ask a question in natural language. The gateway returns the
2043
+ * generated SQL and optionally the executed result set when
2044
+ * `execute=true`.
2045
+ */
2046
+ async ask(question, opts = {}) {
2047
+ const { data } = await this.synapCores._getHttpClient().post("/nl2sql/query", {
2048
+ question,
2049
+ ...opts
2050
+ });
2051
+ return {
2052
+ sql: data.sql ?? data.generated_sql ?? "",
2053
+ confidence: data.confidence,
2054
+ rows: data.rows ?? data.data,
2055
+ columns: data.columns,
2056
+ execution_time_ms: data.execution_time_ms ?? data.took_ms,
2057
+ trace: data.trace ?? data.plan,
2058
+ question
2059
+ };
2060
+ }
2061
+ /**
2062
+ * Push schema context the model should use for subsequent ask() calls.
2063
+ */
2064
+ async updateSchemaContext(payload) {
2065
+ const { data } = await this.synapCores._getHttpClient().post(
2066
+ "/nl2sql/schema/context",
2067
+ payload
2068
+ );
2069
+ return { accepted: data.accepted ?? data.success ?? true, raw: data };
2070
+ }
2071
+ /**
2072
+ * Retrieve recent NL2SQL history for the current authenticated user.
2073
+ */
2074
+ async history(opts = {}) {
2075
+ const params = new URLSearchParams();
2076
+ if (opts.limit) params.append("limit", String(opts.limit));
2077
+ if (opts.session_id) params.append("session_id", opts.session_id);
2078
+ const qs = params.toString();
2079
+ const { data } = await this.synapCores._getHttpClient().get(
2080
+ `/nl2sql/history${qs ? `?${qs}` : ""}`
2081
+ );
2082
+ return (data.history ?? data.entries ?? data ?? []).map((row) => ({
2083
+ id: String(row.id ?? row.entry_id ?? ""),
2084
+ question: row.question ?? row.prompt ?? "",
2085
+ sql: row.sql ?? row.generated_sql ?? "",
2086
+ created_at: new Date(row.created_at ?? row.timestamp ?? Date.now()),
2087
+ executed: row.executed,
2088
+ success: row.success
2089
+ }));
2090
+ }
2091
+ /**
2092
+ * Validate a SQL string against the current schema and policies.
2093
+ */
2094
+ async validate(sql) {
2095
+ const { data } = await this.synapCores._getHttpClient().post("/nl2sql/validate", {
2096
+ sql
2097
+ });
2098
+ return {
2099
+ is_valid: data.is_valid ?? data.valid ?? false,
2100
+ errors: data.errors ?? [],
2101
+ warnings: data.warnings ?? [],
2102
+ rewritten_sql: data.rewritten_sql ?? data.sql
2103
+ };
2104
+ }
2105
+ };
2106
+
2107
+ // src/filesystem.ts
2108
+ import WebSocket2 from "ws";
2109
+ var FsCollectionsApi = class {
2110
+ constructor(synapCores) {
2111
+ this.synapCores = synapCores;
2112
+ }
2113
+ async create(opts) {
2114
+ const { data } = await this.synapCores._getHttpClient().post(
2115
+ "/filesystem-collections",
2116
+ opts
2117
+ );
2118
+ return this.normalize(data);
2119
+ }
2120
+ async list() {
2121
+ const { data } = await this.synapCores._getHttpClient().get("/filesystem-collections");
2122
+ return (data.collections ?? data ?? []).map((c) => this.normalize(c));
2123
+ }
2124
+ async get(id) {
2125
+ const { data } = await this.synapCores._getHttpClient().get(
2126
+ `/filesystem-collections/${id}`
2127
+ );
2128
+ return this.normalize(data);
2129
+ }
2130
+ async patch(id, p) {
2131
+ const { data } = await this.synapCores._getHttpClient().patch(
2132
+ `/filesystem-collections/${id}`,
2133
+ p
2134
+ );
2135
+ return this.normalize(data);
2136
+ }
2137
+ async delete(id) {
2138
+ await this.synapCores._getHttpClient().delete(`/filesystem-collections/${id}`);
2139
+ }
2140
+ async documents(id, opts = {}) {
2141
+ const params = new URLSearchParams();
2142
+ if (opts.page) params.append("page", String(opts.page));
2143
+ if (opts.page_size) params.append("page_size", String(opts.page_size));
2144
+ const qs = params.toString();
2145
+ const { data } = await this.synapCores._getHttpClient().get(
2146
+ `/filesystem-collections/${id}/documents${qs ? `?${qs}` : ""}`
2147
+ );
2148
+ return (data.documents ?? data ?? []).map((d) => ({
2149
+ id: String(d.id ?? d.document_id ?? ""),
2150
+ collection_id: d.collection_id !== void 0 ? String(d.collection_id) : id,
2151
+ filename: d.filename ?? d.name,
2152
+ path: d.path,
2153
+ status: d.status,
2154
+ size_bytes: d.size_bytes,
2155
+ created_at: d.created_at ? new Date(d.created_at) : void 0,
2156
+ updated_at: d.updated_at ? new Date(d.updated_at) : void 0
2157
+ }));
2158
+ }
2159
+ async reprocess(id, fileId) {
2160
+ const body = fileId ? { document_id: fileId } : {};
2161
+ const { data } = await this.synapCores._getHttpClient().post(
2162
+ `/filesystem-collections/${id}/reprocess`,
2163
+ body
2164
+ );
2165
+ return { accepted: data.accepted ?? data.success ?? true, raw: data };
2166
+ }
2167
+ /**
2168
+ * Stream progress events for an in-flight ingestion. Each tick maps to
2169
+ * a JSON payload broadcast by the gateway over the WS channel. The
2170
+ * iterator ends when the server closes the socket or the consumer
2171
+ * breaks out of the for-await loop.
2172
+ */
2173
+ async *subscribeProgress(id, opts = {}) {
2174
+ const { token } = await this.synapCores.createWsTicket();
2175
+ const wsBase = this.synapCores._getWsBaseUrl();
2176
+ const url = `${wsBase}/ws/filesystem-collections/${id}/progress?token=${encodeURIComponent(token)}`;
2177
+ const ws = new WebSocket2(url);
2178
+ const queue = [];
2179
+ let resolver = null;
2180
+ const push = (p) => {
2181
+ if (resolver) {
2182
+ const r = resolver;
2183
+ resolver = null;
2184
+ r(p);
2185
+ } else {
2186
+ queue.push(p);
2187
+ }
2188
+ };
2189
+ ws.on("message", (raw) => {
2190
+ try {
2191
+ const obj = JSON.parse(raw.toString());
2192
+ push({
2193
+ kind: "value",
2194
+ value: {
2195
+ type: obj.type ?? obj.event ?? "progress",
2196
+ collection_id: obj.collection_id !== void 0 ? String(obj.collection_id) : id,
2197
+ document_id: obj.document_id !== void 0 ? String(obj.document_id) : void 0,
2198
+ filename: obj.filename ?? obj.path,
2199
+ status: obj.status,
2200
+ progress: obj.progress,
2201
+ message: obj.message,
2202
+ error: obj.error,
2203
+ timestamp: obj.timestamp ? new Date(obj.timestamp) : void 0,
2204
+ raw: obj
2205
+ }
2206
+ });
2207
+ } catch (e) {
2208
+ push({ kind: "error", error: e });
2209
+ }
2210
+ });
2211
+ ws.on("error", (err) => push({ kind: "error", error: err }));
2212
+ ws.on("close", () => push({ kind: "done" }));
2213
+ const onAbort = () => {
2214
+ try {
2215
+ ws.close();
2216
+ } catch {
2217
+ }
2218
+ };
2219
+ if (opts.signal) {
2220
+ if (opts.signal.aborted) onAbort();
2221
+ else opts.signal.addEventListener("abort", onAbort);
2222
+ }
2223
+ try {
2224
+ while (true) {
2225
+ const next = await new Promise((resolve) => {
2226
+ if (queue.length > 0) {
2227
+ resolve(queue.shift());
2228
+ } else {
2229
+ resolver = resolve;
2230
+ }
2231
+ });
2232
+ if (next.kind === "value") yield next.value;
2233
+ else if (next.kind === "error") throw next.error;
2234
+ else return;
2235
+ }
2236
+ } finally {
2237
+ try {
2238
+ ws.close();
2239
+ } catch {
2240
+ }
2241
+ if (opts.signal) opts.signal.removeEventListener("abort", onAbort);
2242
+ }
2243
+ }
2244
+ normalize(data) {
2245
+ return {
2246
+ id: String(data.id ?? data.collection_id ?? ""),
2247
+ name: data.name,
2248
+ description: data.description,
2249
+ path: data.path,
2250
+ status: data.status,
2251
+ document_count: data.document_count ?? data.documents,
2252
+ created_at: data.created_at ? new Date(data.created_at) : void 0,
2253
+ updated_at: data.updated_at ? new Date(data.updated_at) : void 0,
2254
+ config: data.config
2255
+ };
2256
+ }
2257
+ };
2258
+ var FilesystemCollectionsClient = class {
2259
+ constructor(synapCores) {
2260
+ this.collections = new FsCollectionsApi(synapCores);
2261
+ }
2262
+ };
2263
+
2264
+ // src/chat.ts
2265
+ var ChatSessionsApi = class {
2266
+ constructor(synapCores) {
2267
+ this.synapCores = synapCores;
2268
+ }
2269
+ async create(opts = {}) {
2270
+ const { data } = await this.synapCores._getHttpClient().post("/ai/sessions", opts);
2271
+ return this.normalize(data);
2272
+ }
2273
+ async list(opts = {}) {
2274
+ const params = new URLSearchParams();
2275
+ if (opts.limit) params.append("limit", String(opts.limit));
2276
+ if (opts.offset) params.append("offset", String(opts.offset));
2277
+ const qs = params.toString();
2278
+ const { data } = await this.synapCores._getHttpClient().get(
2279
+ `/ai/sessions${qs ? `?${qs}` : ""}`
2280
+ );
2281
+ return (data.sessions ?? data ?? []).map((s) => this.normalize(s));
2282
+ }
2283
+ async get(id) {
2284
+ const { data } = await this.synapCores._getHttpClient().get(`/ai/sessions/${id}`);
2285
+ return this.normalize(data);
2286
+ }
2287
+ async delete(id) {
2288
+ await this.synapCores._getHttpClient().delete(`/ai/sessions/${id}`);
2289
+ }
2290
+ async messages(id, opts = {}) {
2291
+ const params = new URLSearchParams();
2292
+ if (opts.limit) params.append("limit", String(opts.limit));
2293
+ if (opts.offset) params.append("offset", String(opts.offset));
2294
+ const qs = params.toString();
2295
+ const { data } = await this.synapCores._getHttpClient().get(
2296
+ `/ai/sessions/${id}/messages${qs ? `?${qs}` : ""}`
2297
+ );
2298
+ return (data.messages ?? data ?? []).map((m) => this.normalizeMessage(m, id));
2299
+ }
2300
+ normalize(data) {
2301
+ return {
2302
+ id: String(data.id ?? data.session_id ?? ""),
2303
+ title: data.title,
2304
+ model: data.model,
2305
+ system_prompt: data.system_prompt,
2306
+ created_at: new Date(data.created_at ?? Date.now()),
2307
+ updated_at: data.updated_at ? new Date(data.updated_at) : void 0,
2308
+ message_count: data.message_count ?? data.messages,
2309
+ metadata: data.metadata
2310
+ };
2311
+ }
2312
+ normalizeMessage(m, sessionId) {
2313
+ return {
2314
+ id: String(m.id ?? m.message_id ?? ""),
2315
+ session_id: m.session_id !== void 0 ? String(m.session_id) : sessionId,
2316
+ role: m.role,
2317
+ content: m.content ?? m.text ?? "",
2318
+ created_at: new Date(m.created_at ?? Date.now()),
2319
+ metadata: m.metadata
2320
+ };
2321
+ }
2322
+ };
2323
+ var ChatToolsApi = class {
2324
+ constructor(synapCores) {
2325
+ this.synapCores = synapCores;
2326
+ }
2327
+ async list() {
2328
+ const { data } = await this.synapCores._getHttpClient().get("/ai/tools");
2329
+ return (data.tools ?? data ?? []).map((t) => ({
2330
+ name: t.name,
2331
+ description: t.description,
2332
+ parameters: t.parameters ?? t.schema
2333
+ }));
2334
+ }
2335
+ async execute(name, args = {}) {
2336
+ const { data } = await this.synapCores._getHttpClient().post("/ai/tools/execute", {
2337
+ tool: name,
2338
+ arguments: args
2339
+ });
2340
+ return data;
2341
+ }
2342
+ async sql(sql, params = []) {
2343
+ const { data } = await this.synapCores._getHttpClient().post("/ai/tools/sql", {
2344
+ sql,
2345
+ parameters: params
2346
+ });
2347
+ return data;
2348
+ }
2349
+ };
2350
+ var ChatCacheApi = class {
2351
+ constructor(synapCores) {
2352
+ this.synapCores = synapCores;
2353
+ }
2354
+ async stats() {
2355
+ const { data } = await this.synapCores._getHttpClient().get("/ai/cache/stats");
2356
+ return {
2357
+ size_bytes: data.size_bytes ?? data.bytes,
2358
+ hit_count: data.hit_count ?? data.hits,
2359
+ miss_count: data.miss_count ?? data.misses,
2360
+ entries: data.entries ?? data.count,
2361
+ raw: data
2362
+ };
2363
+ }
2364
+ async clear() {
2365
+ await this.synapCores._getHttpClient().post("/ai/cache/clear", {});
2366
+ }
2367
+ };
2368
+ var ChatClient = class {
2369
+ constructor(synapCores) {
2370
+ this.synapCores = synapCores;
2371
+ this.sessions = new ChatSessionsApi(synapCores);
2372
+ this.tools = new ChatToolsApi(synapCores);
2373
+ this.cache = new ChatCacheApi(synapCores);
2374
+ }
2375
+ /**
2376
+ * Send a one-shot chat message. The gateway accepts both /ai/chat and
2377
+ * the alias /ai/ — we use /ai/chat for clarity.
2378
+ */
2379
+ async send(sessionId, content, opts = {}) {
2380
+ const { data } = await this.synapCores._getHttpClient().post("/ai/chat", {
2381
+ session_id: sessionId,
2382
+ content,
2383
+ ...opts
2384
+ });
2385
+ const messageData = data.message ?? data;
2386
+ return {
2387
+ message: {
2388
+ id: String(messageData.id ?? messageData.message_id ?? ""),
2389
+ session_id: sessionId,
2390
+ role: messageData.role ?? "assistant",
2391
+ content: messageData.content ?? messageData.text ?? "",
2392
+ created_at: new Date(messageData.created_at ?? Date.now()),
2393
+ metadata: messageData.metadata
2394
+ },
2395
+ tool_calls: data.tool_calls,
2396
+ usage: data.usage
2397
+ };
2398
+ }
2399
+ /**
2400
+ * Stream a chat completion. Returns an async iterator over SSE chunks.
2401
+ */
2402
+ async *stream(sessionId, content, opts = {}) {
2403
+ const http = this.synapCores._getHttpClient();
2404
+ const response = await http.post(
2405
+ "/ai/chat/stream",
2406
+ {
2407
+ session_id: sessionId,
2408
+ content,
2409
+ ...opts
2410
+ },
2411
+ { responseType: "stream" }
2412
+ );
2413
+ const stream = response.data;
2414
+ let buffer = "";
2415
+ for await (const chunk of stream) {
2416
+ buffer += chunk.toString();
2417
+ const frames = buffer.split(/\n\n/);
2418
+ buffer = frames.pop() ?? "";
2419
+ for (const frame of frames) {
2420
+ const trimmed = frame.trim();
2421
+ if (!trimmed) continue;
2422
+ const line = trimmed.startsWith("data:") ? trimmed.slice(5).trim() : trimmed;
2423
+ if (line === "[DONE]") {
2424
+ yield { done: true };
2425
+ return;
2426
+ }
2427
+ try {
2428
+ const obj = JSON.parse(line);
2429
+ yield {
2430
+ delta: obj.delta ?? obj.choices?.[0]?.delta?.content ?? obj.text ?? void 0,
2431
+ content: obj.content ?? obj.message?.content,
2432
+ type: obj.type ?? obj.event,
2433
+ done: obj.done ?? obj.finished,
2434
+ raw: obj
2435
+ };
2436
+ } catch {
2437
+ yield { delta: line, raw: line };
2438
+ }
2439
+ }
2440
+ }
2441
+ if (buffer.trim()) {
2442
+ try {
2443
+ yield { raw: JSON.parse(buffer) };
2444
+ } catch {
2445
+ yield { delta: buffer };
2446
+ }
2447
+ }
2448
+ }
2449
+ /**
2450
+ * Get prompt suggestions, e.g. for an empty session UI.
2451
+ */
2452
+ async suggestions(opts = {}) {
2453
+ const { data } = await this.synapCores._getHttpClient().post("/ai/suggestions", opts);
2454
+ return (data.suggestions ?? data ?? []).map((s) => ({
2455
+ prompt: s.prompt ?? s.text ?? "",
2456
+ category: s.category,
2457
+ meta: s.meta ?? s.metadata
2458
+ }));
2459
+ }
2460
+ /**
2461
+ * List configured chat models.
1774
2462
  */
1775
- async deactivateSchedule(scheduleId) {
1776
- const { data } = await this.synapCores._getHttpClient().post(
1777
- `/backups/schedules/${scheduleId}/deactivate`
1778
- );
1779
- return {
1780
- id: data.id,
1781
- name: data.name,
1782
- cron: data.cron,
1783
- backup_options: data.backup_options,
1784
- active: data.active,
1785
- last_run_at: data.last_run_at ? new Date(data.last_run_at) : void 0,
1786
- next_run_at: data.next_run_at ? new Date(data.next_run_at) : void 0,
1787
- created_at: new Date(data.created_at),
1788
- tags: data.tags || []
1789
- };
2463
+ async models() {
2464
+ const { data } = await this.synapCores._getHttpClient().get("/ai/models");
2465
+ return (data.models ?? data ?? []).map((m) => ({
2466
+ id: m.id ?? m.name,
2467
+ name: m.name,
2468
+ provider: m.provider,
2469
+ context_window: m.context_window ?? m.max_context,
2470
+ capabilities: m.capabilities
2471
+ }));
1790
2472
  }
1791
2473
  /**
1792
- * Get backup metrics
2474
+ * List the available system prompts library.
1793
2475
  */
1794
- async getMetrics() {
1795
- const { data } = await this.synapCores._getHttpClient().get("/backups/metrics");
2476
+ async systemPrompts() {
2477
+ const { data } = await this.synapCores._getHttpClient().get("/ai/system-prompts");
2478
+ return (data.prompts ?? data.system_prompts ?? data ?? []).map((p) => ({
2479
+ id: String(p.id ?? p.name ?? ""),
2480
+ name: p.name,
2481
+ content: p.content ?? p.text ?? "",
2482
+ description: p.description,
2483
+ category: p.category
2484
+ }));
2485
+ }
2486
+ };
2487
+
2488
+ // src/multimodal.ts
2489
+ var MultimodalClient = class {
2490
+ constructor(synapCores) {
2491
+ this.synapCores = synapCores;
2492
+ }
2493
+ async similarity(a, b, opts = {}) {
2494
+ const { data } = await this.synapCores._getHttpClient().post("/multimodal/similarity", {
2495
+ a: typeof a === "string" ? { type: "text", text: a } : a,
2496
+ b: typeof b === "string" ? { type: "text", text: b } : b,
2497
+ ...opts
2498
+ });
1796
2499
  return {
1797
- total_backups: data.total_backups || 0,
1798
- total_size_bytes: data.total_size_bytes || 0,
1799
- successful_backups: data.successful_backups || 0,
1800
- failed_backups: data.failed_backups || 0,
1801
- avg_backup_size_bytes: data.avg_backup_size_bytes || 0,
1802
- avg_duration_ms: data.avg_duration_ms || 0,
1803
- last_backup_at: data.last_backup_at ? new Date(data.last_backup_at) : void 0,
1804
- next_scheduled_at: data.next_scheduled_at ? new Date(data.next_scheduled_at) : void 0
2500
+ similarity: data.similarity ?? data.score ?? 0,
2501
+ metric: data.metric ?? opts.metric,
2502
+ raw: data
1805
2503
  };
1806
2504
  }
1807
- /**
1808
- * Map raw backup data to Backup type
1809
- */
1810
- mapBackup(data) {
2505
+ async search(query, opts = {}) {
2506
+ const { data } = await this.synapCores._getHttpClient().post("/multimodal/search", {
2507
+ query: typeof query === "string" ? { type: "text", text: query } : query,
2508
+ ...opts
2509
+ });
2510
+ return (data.results ?? data.hits ?? data ?? []).map((r) => ({
2511
+ id: String(r.id ?? r.document_id ?? ""),
2512
+ score: r.score ?? r.similarity ?? 0,
2513
+ modality: r.modality,
2514
+ metadata: r.metadata
2515
+ }));
2516
+ }
2517
+ async join(left, right, opts = {}) {
2518
+ const normalize = (side) => Array.isArray(side) ? side.map((s) => typeof s === "string" ? { type: "text", text: s } : s) : side;
2519
+ const { data } = await this.synapCores._getHttpClient().post("/multimodal/join", {
2520
+ left: normalize(left),
2521
+ right: normalize(right),
2522
+ ...opts
2523
+ });
1811
2524
  return {
1812
- id: data.id,
1813
- name: data.name,
1814
- description: data.description,
1815
- type: data.type,
1816
- status: data.status,
1817
- size_bytes: data.size_bytes,
1818
- compressed_size_bytes: data.compressed_size_bytes,
1819
- table_count: data.table_count,
1820
- created_at: new Date(data.created_at),
1821
- completed_at: data.completed_at ? new Date(data.completed_at) : void 0,
1822
- duration_ms: data.duration_ms || data.took_ms,
1823
- storage: data.storage,
1824
- storage_path: data.storage_path,
1825
- encrypted: data.encrypted || false,
1826
- tags: data.tags || [],
1827
- parent_backup_id: data.parent_backup_id,
1828
- error: data.error
2525
+ pairs: (data.pairs ?? data.results ?? []).map((p) => ({
2526
+ left: p.left,
2527
+ right: p.right,
2528
+ score: p.score ?? p.similarity ?? 0
2529
+ }))
2530
+ };
2531
+ }
2532
+ async embed(input, model) {
2533
+ const { data } = await this.synapCores._getHttpClient().post("/multimodal/embed", {
2534
+ input: typeof input === "string" ? { type: "text", text: input } : input,
2535
+ model
2536
+ });
2537
+ const embedding = data.embedding ?? data.vector ?? [];
2538
+ return {
2539
+ embedding,
2540
+ modality: data.modality,
2541
+ model: data.model ?? model,
2542
+ dimensions: data.dimensions ?? embedding.length
1829
2543
  };
1830
2544
  }
1831
2545
  };
1832
2546
 
1833
- // src/errors.ts
1834
- var SynapCoresError = class _SynapCoresError extends Error {
1835
- constructor(message, code, details) {
1836
- super(message);
1837
- this.name = "SynapCoresError";
1838
- this.code = code;
1839
- this.details = details;
1840
- if (Error.captureStackTrace) {
1841
- Error.captureStackTrace(this, _SynapCoresError);
2547
+ // src/system.ts
2548
+ var VisionApi = class {
2549
+ constructor(synapCores) {
2550
+ this.synapCores = synapCores;
2551
+ }
2552
+ async get() {
2553
+ try {
2554
+ const { data } = await this.synapCores._getHttpClient().get("/system/vision");
2555
+ if (!data || Object.keys(data).length === 0) return null;
2556
+ return data;
2557
+ } catch (e) {
2558
+ if (e?.statusCode === 404 || e?.code === "NOT_FOUND") return null;
2559
+ throw e;
1842
2560
  }
1843
2561
  }
1844
- };
1845
- var ConnectionError = class extends SynapCoresError {
1846
- constructor(message, details) {
1847
- super(message, "CONNECTION_ERROR", details);
1848
- this.name = "ConnectionError";
2562
+ async set(cfg) {
2563
+ const { data } = await this.synapCores._getHttpClient().put("/system/vision", cfg);
2564
+ return data;
1849
2565
  }
1850
- };
1851
- var AuthenticationError = class extends SynapCoresError {
1852
- constructor(message, details) {
1853
- super(message, "AUTH_ERROR", details);
1854
- this.name = "AuthenticationError";
2566
+ async delete() {
2567
+ await this.synapCores._getHttpClient().delete("/system/vision");
1855
2568
  }
1856
- };
1857
- var ValidationError = class extends SynapCoresError {
1858
- constructor(message, details) {
1859
- super(message, "VALIDATION_ERROR", details);
1860
- this.name = "ValidationError";
2569
+ async test(payload = {}) {
2570
+ const { data } = await this.synapCores._getHttpClient().post("/system/vision/test", payload);
2571
+ return {
2572
+ success: data.success ?? false,
2573
+ latency_ms: data.latency_ms,
2574
+ response: data.response,
2575
+ error: data.error
2576
+ };
1861
2577
  }
1862
2578
  };
1863
- var NotFoundError = class extends SynapCoresError {
1864
- constructor(message, details) {
1865
- super(message, "NOT_FOUND", details);
1866
- this.name = "NotFoundError";
2579
+ var SystemClient = class {
2580
+ constructor(synapCores) {
2581
+ this.vision = new VisionApi(synapCores);
1867
2582
  }
1868
2583
  };
1869
- var ServerError = class extends SynapCoresError {
1870
- constructor(message, details) {
1871
- super(message, "SERVER_ERROR", details);
1872
- this.name = "ServerError";
2584
+
2585
+ // src/transactions.ts
2586
+ var Tx = class {
2587
+ constructor(http, id, options) {
2588
+ this.http = http;
2589
+ this.id = id;
2590
+ this.options = options;
2591
+ this.active = true;
1873
2592
  }
1874
- };
1875
- var TimeoutError = class extends SynapCoresError {
1876
- constructor(message, details) {
1877
- super(message, "TIMEOUT_ERROR", details);
1878
- this.name = "TimeoutError";
2593
+ isActive() {
2594
+ return this.active;
1879
2595
  }
1880
- };
1881
- var RateLimitError = class extends SynapCoresError {
1882
- constructor(message, retryAfter, details) {
1883
- super(message, "RATE_LIMIT_ERROR", details);
1884
- this.name = "RateLimitError";
1885
- this.retryAfter = retryAfter;
2596
+ async execute(sql, params = []) {
2597
+ this.assertActive();
2598
+ const { data } = await this.http.post(`/transactions/${this.id}/execute`, {
2599
+ sql,
2600
+ parameters: params
2601
+ });
2602
+ return {
2603
+ columns: data.columns ?? [],
2604
+ rows: data.rows ?? [],
2605
+ rows_affected: data.rows_affected,
2606
+ execution_time_ms: data.execution_time_ms ?? data.took_ms
2607
+ };
1886
2608
  }
1887
- };
1888
- var SQLError = class extends SynapCoresError {
1889
- constructor(message, code, severity = "ERROR", position, hint, detail, details) {
1890
- super(message, code, details);
1891
- this.name = "SQLError";
1892
- this.severity = severity;
1893
- this.position = position;
1894
- this.hint = hint;
1895
- this.detail = detail;
2609
+ async commit() {
2610
+ this.assertActive();
2611
+ await this.http.post(`/transactions/${this.id}/commit`, {});
2612
+ this.active = false;
2613
+ }
2614
+ async rollback() {
2615
+ this.assertActive();
2616
+ await this.http.post(`/transactions/${this.id}/rollback`, {});
2617
+ this.active = false;
2618
+ }
2619
+ async savepoint(name) {
2620
+ this.assertActive();
2621
+ await this.http.post(`/transactions/${this.id}/savepoint`, { name });
2622
+ }
2623
+ async rollbackTo(name) {
2624
+ this.assertActive();
2625
+ await this.http.post(`/transactions/${this.id}/savepoint/${name}/rollback`, {});
2626
+ }
2627
+ assertActive() {
2628
+ if (!this.active) {
2629
+ throw new Error(`Transaction ${this.id} has already been committed/rolled back`);
2630
+ }
1896
2631
  }
1897
2632
  };
1898
- var VectorError = class extends SynapCoresError {
1899
- constructor(message, code, vectorDimensions, expectedDimensions, operation, details) {
1900
- super(message, code, details);
1901
- this.name = "VectorError";
1902
- this.vectorDimensions = vectorDimensions;
1903
- this.expectedDimensions = expectedDimensions;
1904
- this.operation = operation;
2633
+ var TxHistoryApi = class {
2634
+ constructor(synapCores) {
2635
+ this.synapCores = synapCores;
2636
+ }
2637
+ async list(opts = {}) {
2638
+ const params = new URLSearchParams();
2639
+ if (opts.limit) params.append("limit", String(opts.limit));
2640
+ if (opts.status) params.append("status", opts.status);
2641
+ const qs = params.toString();
2642
+ const { data } = await this.synapCores._getHttpClient().get(
2643
+ `/transactions/history${qs ? `?${qs}` : ""}`
2644
+ );
2645
+ return (data.transactions ?? data.history ?? data ?? []).map((row) => ({
2646
+ id: String(row.id ?? row.transaction_id ?? ""),
2647
+ status: row.status ?? "unknown",
2648
+ started_at: new Date(row.started_at ?? row.created_at ?? Date.now()),
2649
+ completed_at: row.completed_at ? new Date(row.completed_at) : void 0,
2650
+ isolation_level: row.isolation_level,
2651
+ read_only: row.read_only,
2652
+ statement_count: row.statement_count ?? row.statements,
2653
+ metrics: row.metrics
2654
+ }));
2655
+ }
2656
+ async get(id) {
2657
+ const { data } = await this.synapCores._getHttpClient().get(
2658
+ `/transactions/history/${id}`
2659
+ );
2660
+ return {
2661
+ id: String(data.id ?? id),
2662
+ status: data.status ?? "unknown",
2663
+ started_at: new Date(data.started_at ?? data.created_at ?? Date.now()),
2664
+ completed_at: data.completed_at ? new Date(data.completed_at) : void 0,
2665
+ isolation_level: data.isolation_level,
2666
+ read_only: data.read_only,
2667
+ statement_count: data.statement_count ?? data.statements,
2668
+ metrics: data.metrics
2669
+ };
1905
2670
  }
1906
2671
  };
1907
- var TransactionError = class extends SynapCoresError {
1908
- constructor(message, code, transactionId, transactionState, details) {
1909
- super(message, code, details);
1910
- this.name = "TransactionError";
1911
- this.transactionId = transactionId;
1912
- this.transactionState = transactionState;
2672
+ var TransactionsClient = class {
2673
+ constructor(synapCores) {
2674
+ this.synapCores = synapCores;
2675
+ this.history = new TxHistoryApi(synapCores);
2676
+ }
2677
+ /**
2678
+ * Begin a new server-side transaction.
2679
+ */
2680
+ async begin(opts = {}) {
2681
+ const { data } = await this.synapCores._getHttpClient().post("/transactions", opts);
2682
+ const id = String(data.id ?? data.transaction_id ?? "");
2683
+ if (!id) {
2684
+ throw new Error("begin(): server did not return a transaction id");
2685
+ }
2686
+ return new Tx(this.synapCores._getHttpClient(), id, opts);
1913
2687
  }
1914
2688
  };
1915
- var BatchOperationError = class extends SynapCoresError {
1916
- constructor(message, code, failedItems, totalProcessed, successfulCount, details) {
1917
- super(message, code, details);
1918
- this.name = "BatchOperationError";
1919
- this.failedItems = failedItems;
1920
- this.totalProcessed = totalProcessed;
1921
- this.successfulCount = successfulCount;
2689
+
2690
+ // src/mcp.ts
2691
+ var mcpRequestCounter = 0;
2692
+ function withId(req) {
2693
+ if (req.id !== void 0 && req.id !== null) return req;
2694
+ mcpRequestCounter += 1;
2695
+ return { ...req, id: `mcp-${Date.now()}-${mcpRequestCounter}` };
2696
+ }
2697
+ var McpClient = class {
2698
+ constructor(synapCores) {
2699
+ this.synapCores = synapCores;
2700
+ }
2701
+ /**
2702
+ * Invoke a single MCP method.
2703
+ */
2704
+ async invoke(req) {
2705
+ const body = withId(req);
2706
+ const { data } = await this.synapCores._getHttpClient().post("/mcp", body);
2707
+ return {
2708
+ id: data.id ?? body.id,
2709
+ result: data.result,
2710
+ error: data.error,
2711
+ raw: data
2712
+ };
2713
+ }
2714
+ /**
2715
+ * Send an array of MCP invocations and resolve to the matching array
2716
+ * of responses (in the order returned by the gateway).
2717
+ */
2718
+ async batch(reqs) {
2719
+ const body = reqs.map(withId);
2720
+ const { data } = await this.synapCores._getHttpClient().post("/mcp/batch", body);
2721
+ const arr = Array.isArray(data) ? data : data.responses ?? data.results ?? [];
2722
+ return arr.map((r) => ({
2723
+ id: r.id,
2724
+ result: r.result,
2725
+ error: r.error,
2726
+ raw: r
2727
+ }));
2728
+ }
2729
+ /**
2730
+ * Discover the server's MCP capabilities and tools.
2731
+ */
2732
+ async info() {
2733
+ const { data } = await this.synapCores._getHttpClient().get("/mcp/info");
2734
+ return {
2735
+ version: data.version ?? data.mcp_version ?? "0",
2736
+ capabilities: data.capabilities,
2737
+ tools: data.tools,
2738
+ meta: data.meta ?? data.metadata
2739
+ };
1922
2740
  }
1923
2741
  };
1924
2742
 
@@ -1957,7 +2775,7 @@ var SynapCores = class {
1957
2775
  timeout: this.config.timeout,
1958
2776
  headers: {
1959
2777
  "Content-Type": "application/json",
1960
- "User-Agent": "synapcores-nodejs/0.1.0",
2778
+ "User-Agent": "synapcores-nodejs/0.2.0",
1961
2779
  ...authHeader
1962
2780
  },
1963
2781
  ...httpsAgent && { httpsAgent }
@@ -1973,6 +2791,44 @@ var SynapCores = class {
1973
2791
  this.import = new ImportExportClient(this);
1974
2792
  this.integrations = new IntegrationClient(this);
1975
2793
  this.backup = new BackupClient(this);
2794
+ this.graph = new GraphClient(this);
2795
+ this.nl2sql = new NL2SqlClient(this);
2796
+ this.filesystem = new FilesystemCollectionsClient(this);
2797
+ this.chat = new ChatClient(this);
2798
+ this.multimodal = new MultimodalClient(this);
2799
+ this.system = new SystemClient(this);
2800
+ this.transactions = new TransactionsClient(this);
2801
+ this.mcp = new McpClient(this);
2802
+ }
2803
+ /**
2804
+ * Build the WebSocket base URL (ws:// or wss://).
2805
+ */
2806
+ _getWsBaseUrl() {
2807
+ const protocol = this.config.useHttps ? "wss" : "ws";
2808
+ return `${protocol}://${this.config.host}:${this.config.port}`;
2809
+ }
2810
+ /**
2811
+ * Read-only access to the configured host/port for WS-clients.
2812
+ */
2813
+ _getConfig() {
2814
+ return this.config;
2815
+ }
2816
+ /**
2817
+ * Exchange the current credentials (JWT or API key) for a short-lived
2818
+ * WebSocket ticket. Use the returned token as the `?token=` query
2819
+ * param when opening any /ws endpoint.
2820
+ */
2821
+ async createWsTicket() {
2822
+ const { data } = await this.httpClient.post("/ws/ticket", {});
2823
+ const token = data.token ?? data.ticket;
2824
+ const expiresAt = typeof data.expiresAt === "number" ? data.expiresAt : data.expires_at ? Date.parse(data.expires_at) : Date.now() + 6e4;
2825
+ return { token, expiresAt };
2826
+ }
2827
+ /**
2828
+ * Revoke a previously-issued ticket (best-effort).
2829
+ */
2830
+ async revokeWsTicket(token) {
2831
+ await this.httpClient.post("/ws/ticket/revoke", { token });
1976
2832
  }
1977
2833
  handleError(error) {
1978
2834
  if (!error.response) {
@@ -2161,11 +3017,11 @@ var SynapCores = class {
2161
3017
  async embed(text, options = {}) {
2162
3018
  const isBatch = Array.isArray(text);
2163
3019
  const texts = isBatch ? text : [text];
2164
- const { data } = await this.httpClient.post("/ai/embed", {
2165
- texts,
2166
- model: options.model || "default"
2167
- });
2168
- return isBatch ? data.embeddings : data.embeddings[0];
3020
+ const path = isBatch ? "/ai/embeddings/batch" : "/ai/embeddings";
3021
+ const body = isBatch ? { texts, model: options.model } : { text: texts[0], model: options.model };
3022
+ const { data } = await this.httpClient.post(path, body);
3023
+ if (isBatch) return data.embeddings ?? data;
3024
+ return data.embedding ?? data.embeddings?.[0] ?? data;
2169
3025
  }
2170
3026
  // Internal method for HTTP client access
2171
3027
  _getHttpClient() {
@@ -2292,8 +3148,16 @@ var SynapCores = class {
2292
3148
  * @returns Promise resolving to table information
2293
3149
  */
2294
3150
  async describeTable(tableName) {
2295
- const { data } = await this.httpClient.get(`/table/${tableName}/info`);
2296
- return data;
3151
+ const [tableRes, colsRes, idxRes] = await Promise.all([
3152
+ this.httpClient.get(`/schema/tables/${tableName}`),
3153
+ this.httpClient.get(`/schema/tables/${tableName}/columns`),
3154
+ this.httpClient.get(`/schema/tables/${tableName}/indexes`)
3155
+ ]);
3156
+ return {
3157
+ ...tableRes.data,
3158
+ columns: colsRes.data?.columns ?? colsRes.data ?? [],
3159
+ indexes: idxRes.data?.indexes ?? idxRes.data ?? []
3160
+ };
2297
3161
  }
2298
3162
  /**
2299
3163
  * Lists all tables in the current database
@@ -2426,19 +3290,26 @@ var SynapCores = class {
2426
3290
  * @returns Promise resolving to batch operation result
2427
3291
  */
2428
3292
  async batchInsert(options) {
2429
- const { data } = await this.httpClient.post("/batch/insert", {
2430
- table_name: options.tableName,
2431
- columns: options.columns,
2432
- rows: options.rows,
2433
- on_conflict: options.onConflict,
2434
- batch_size: options.batchSize || 1e3
2435
- });
2436
- return {
2437
- totalProcessed: data.total_processed,
2438
- successful: data.successful,
2439
- failed: data.failed,
2440
- errors: data.errors,
2441
- tookMs: data.took_ms
3293
+ const cols = options.columns ?? [];
3294
+ const queries = options.rows.map((row) => {
3295
+ const values = Array.isArray(row) ? row : cols.map((c) => row[c]);
3296
+ return {
3297
+ sql: `INSERT INTO ${options.tableName} (${cols.join(", ")}) VALUES (${values.map((_, i) => "$" + (i + 1)).join(", ")})`,
3298
+ parameters: values
3299
+ };
3300
+ });
3301
+ const { data } = await this.httpClient.post("/query/execute/batch", {
3302
+ queries,
3303
+ transactional: false
3304
+ });
3305
+ const results = data.results ?? [];
3306
+ const successful = results.filter((r) => !r.error).length;
3307
+ return {
3308
+ totalProcessed: results.length,
3309
+ successful,
3310
+ failed: results.length - successful,
3311
+ errors: results.filter((r) => r.error).map((r) => r.error),
3312
+ tookMs: data.total_execution_time_ms ?? 0
2442
3313
  };
2443
3314
  }
2444
3315
  /**
@@ -2447,17 +3318,27 @@ var SynapCores = class {
2447
3318
  * @returns Promise resolving to batch operation result
2448
3319
  */
2449
3320
  async batchUpdate(options) {
2450
- const { data } = await this.httpClient.post("/batch/update", {
2451
- table_name: options.tableName,
2452
- updates: options.updates,
2453
- batch_size: options.batchSize || 1e3
3321
+ const queries = options.updates.map((u) => {
3322
+ const setClause = Object.keys(u.set ?? {}).map((k, i) => `${k} = $${i + 1}`).join(", ");
3323
+ const setVals = Object.values(u.set ?? {});
3324
+ const whereStr = u.where ?? "1=1";
3325
+ return {
3326
+ sql: `UPDATE ${options.tableName} SET ${setClause} WHERE ${whereStr}`,
3327
+ parameters: setVals
3328
+ };
2454
3329
  });
3330
+ const { data } = await this.httpClient.post("/query/execute/batch", {
3331
+ queries,
3332
+ transactional: false
3333
+ });
3334
+ const results = data.results ?? [];
3335
+ const successful = results.filter((r) => !r.error).length;
2455
3336
  return {
2456
- totalProcessed: data.total_processed,
2457
- successful: data.successful,
2458
- failed: data.failed,
2459
- errors: data.errors,
2460
- tookMs: data.took_ms
3337
+ totalProcessed: results.length,
3338
+ successful,
3339
+ failed: results.length - successful,
3340
+ errors: results.filter((r) => r.error).map((r) => r.error),
3341
+ tookMs: data.total_execution_time_ms ?? 0
2461
3342
  };
2462
3343
  }
2463
3344
  /**
@@ -2466,17 +3347,22 @@ var SynapCores = class {
2466
3347
  * @returns Promise resolving to batch operation result
2467
3348
  */
2468
3349
  async batchDelete(options) {
2469
- const { data } = await this.httpClient.post("/batch/delete", {
2470
- table_name: options.tableName,
2471
- where_conditions: options.whereConditions,
2472
- batch_size: options.batchSize || 1e3
3350
+ const queries = (options.whereConditions ?? []).map((cond) => ({
3351
+ sql: `DELETE FROM ${options.tableName} WHERE ${typeof cond === "string" ? cond : JSON.stringify(cond)}`,
3352
+ parameters: []
3353
+ }));
3354
+ const { data } = await this.httpClient.post("/query/execute/batch", {
3355
+ queries,
3356
+ transactional: false
2473
3357
  });
3358
+ const results = data.results ?? [];
3359
+ const successful = results.filter((r) => !r.error).length;
2474
3360
  return {
2475
- totalProcessed: data.total_processed,
2476
- successful: data.successful,
2477
- failed: data.failed,
2478
- errors: data.errors,
2479
- tookMs: data.took_ms
3361
+ totalProcessed: results.length,
3362
+ successful,
3363
+ failed: results.length - successful,
3364
+ errors: results.filter((r) => r.error).map((r) => r.error),
3365
+ tookMs: data.total_execution_time_ms ?? 0
2480
3366
  };
2481
3367
  }
2482
3368
  // =================================================================
@@ -2489,15 +3375,15 @@ var SynapCores = class {
2489
3375
  * @returns Promise resolving to prepared statement
2490
3376
  */
2491
3377
  async prepareStatement(sql, options = {}) {
2492
- const { data } = await this.httpClient.post("/prepare", {
3378
+ const { data } = await this.httpClient.post("/query/prepare", {
2493
3379
  sql,
2494
3380
  name: options.name,
2495
3381
  parameter_types: options.parameterTypes
2496
3382
  });
2497
3383
  const prepared = {
2498
- id: data.statement_id,
3384
+ id: data.statement_id ?? data.id,
2499
3385
  sql,
2500
- parameterCount: data.parameter_count
3386
+ parameterCount: data.parameter_count ?? data.parameters_count ?? 0
2501
3387
  };
2502
3388
  if (options.name) {
2503
3389
  this.preparedStatements.set(options.name, prepared);
@@ -2514,7 +3400,7 @@ var SynapCores = class {
2514
3400
  if (this.preparedStatements.has(statementId)) {
2515
3401
  statementId = this.preparedStatements.get(statementId).id;
2516
3402
  }
2517
- const { data } = await this.httpClient.post("/execute-prepared", {
3403
+ const { data } = await this.httpClient.post("/query/exec", {
2518
3404
  statement_id: statementId,
2519
3405
  parameters: params
2520
3406
  });
@@ -2534,10 +3420,10 @@ var SynapCores = class {
2534
3420
  async deallocatePrepared(statementId) {
2535
3421
  if (this.preparedStatements.has(statementId)) {
2536
3422
  const prepared = this.preparedStatements.get(statementId);
2537
- await this.httpClient.delete(`/prepare/${prepared.id}`);
3423
+ await this.httpClient.post("/query/close", { statement_id: prepared.id });
2538
3424
  this.preparedStatements.delete(statementId);
2539
3425
  } else {
2540
- await this.httpClient.delete(`/prepare/${statementId}`);
3426
+ await this.httpClient.post("/query/close", { statement_id: statementId });
2541
3427
  }
2542
3428
  }
2543
3429
  /**
@@ -2628,231 +3514,198 @@ var SynapCores = class {
2628
3514
  if (vector1.length !== vector2.length) {
2629
3515
  throw new VectorError("Vector dimensions must match", "DIMENSION_MISMATCH");
2630
3516
  }
2631
- const { data } = await this.httpClient.post("/vectors/add", {
2632
- vector1,
2633
- vector2
3517
+ const { data } = await this.httpClient.post("/vector-algebra/operation", {
3518
+ op: "add",
3519
+ a: vector1,
3520
+ b: vector2
2634
3521
  });
3522
+ const result = data.result ?? data.vector ?? [];
2635
3523
  return {
2636
- result: { values: data.result, dimensions: data.result.length },
3524
+ result: { values: result, dimensions: result.length },
2637
3525
  operation: "addition",
2638
3526
  tookMs: data.took_ms
2639
3527
  };
2640
3528
  }
2641
3529
  /**
2642
3530
  * Performs vector subtraction
2643
- * @param vector1 - First vector (minuend)
2644
- * @param vector2 - Second vector (subtrahend)
2645
- * @returns Promise resolving to vector subtraction result
2646
3531
  */
2647
3532
  async vectorSubtract(vector1, vector2) {
2648
3533
  if (vector1.length !== vector2.length) {
2649
3534
  throw new VectorError("Vector dimensions must match", "DIMENSION_MISMATCH");
2650
3535
  }
2651
- const { data } = await this.httpClient.post("/vectors/subtract", {
2652
- vector1,
2653
- vector2
3536
+ const { data } = await this.httpClient.post("/vector-algebra/operation", {
3537
+ op: "subtract",
3538
+ a: vector1,
3539
+ b: vector2
2654
3540
  });
3541
+ const result = data.result ?? data.vector ?? [];
2655
3542
  return {
2656
- result: { values: data.result, dimensions: data.result.length },
3543
+ result: { values: result, dimensions: result.length },
2657
3544
  operation: "subtraction",
2658
3545
  tookMs: data.took_ms
2659
3546
  };
2660
3547
  }
2661
3548
  /**
2662
3549
  * Performs scalar multiplication on a vector
2663
- * @param vector - Input vector
2664
- * @param scalar - Scalar value to multiply by
2665
- * @returns Promise resolving to scalar multiplication result
2666
3550
  */
2667
3551
  async vectorScalarMultiply(vector, scalar) {
2668
- const { data } = await this.httpClient.post("/vectors/scalar-multiply", {
2669
- vector,
3552
+ const { data } = await this.httpClient.post("/vector-algebra/operation", {
3553
+ op: "scalar_multiply",
3554
+ a: vector,
2670
3555
  scalar
2671
3556
  });
3557
+ const result = data.result ?? data.vector ?? [];
2672
3558
  return {
2673
- result: { values: data.result, dimensions: data.result.length },
3559
+ result: { values: result, dimensions: result.length },
2674
3560
  operation: "scalar_multiplication",
2675
3561
  tookMs: data.took_ms
2676
3562
  };
2677
3563
  }
2678
3564
  /**
2679
3565
  * Calculates the dot product of two vectors
2680
- * @param vector1 - First vector
2681
- * @param vector2 - Second vector
2682
- * @returns Promise resolving to dot product result
2683
3566
  */
2684
3567
  async vectorDotProduct(vector1, vector2) {
2685
3568
  if (vector1.length !== vector2.length) {
2686
3569
  throw new VectorError("Vector dimensions must match", "DIMENSION_MISMATCH");
2687
3570
  }
2688
- const { data } = await this.httpClient.post("/vectors/dot-product", {
2689
- vector1,
2690
- vector2
3571
+ const { data } = await this.httpClient.post("/vector-algebra/operation", {
3572
+ op: "dot_product",
3573
+ a: vector1,
3574
+ b: vector2
2691
3575
  });
2692
- return {
2693
- dotProduct: data.dot_product,
2694
- tookMs: data.took_ms
2695
- };
3576
+ return { dotProduct: data.scalar ?? data.dot_product ?? 0, tookMs: data.took_ms };
2696
3577
  }
2697
3578
  /**
2698
3579
  * Calculates cosine similarity between two vectors
2699
- * @param vector1 - First vector
2700
- * @param vector2 - Second vector
2701
- * @returns Promise resolving to cosine similarity result
2702
3580
  */
2703
3581
  async cosineSimilarity(vector1, vector2) {
2704
3582
  if (vector1.length !== vector2.length) {
2705
3583
  throw new VectorError("Vector dimensions must match", "DIMENSION_MISMATCH");
2706
3584
  }
2707
- const { data } = await this.httpClient.post("/vectors/cosine-similarity", {
2708
- vector1,
2709
- vector2
3585
+ const { data } = await this.httpClient.post("/vector-algebra/operation", {
3586
+ op: "cosine_similarity",
3587
+ a: vector1,
3588
+ b: vector2
2710
3589
  });
2711
- return {
2712
- similarity: data.similarity,
2713
- function: "cosine",
2714
- tookMs: data.took_ms
2715
- };
3590
+ return { similarity: data.scalar ?? data.similarity ?? 0, function: "cosine", tookMs: data.took_ms };
2716
3591
  }
2717
3592
  /**
2718
3593
  * Calculates L2 (Euclidean) distance between two vectors
2719
- * @param vector1 - First vector
2720
- * @param vector2 - Second vector
2721
- * @returns Promise resolving to L2 distance result
2722
3594
  */
2723
3595
  async l2Distance(vector1, vector2) {
2724
3596
  if (vector1.length !== vector2.length) {
2725
3597
  throw new VectorError("Vector dimensions must match", "DIMENSION_MISMATCH");
2726
3598
  }
2727
- const { data } = await this.httpClient.post("/vectors/l2-distance", {
2728
- vector1,
2729
- vector2
3599
+ const { data } = await this.httpClient.post("/vector-algebra/operation", {
3600
+ op: "l2_distance",
3601
+ a: vector1,
3602
+ b: vector2
2730
3603
  });
2731
- return {
2732
- distance: data.distance,
2733
- similarity: data.distance,
2734
- // Include similarity for compatibility
2735
- function: "l2",
2736
- tookMs: data.took_ms
2737
- };
3604
+ const distance = data.scalar ?? data.distance ?? 0;
3605
+ return { distance, similarity: distance, function: "l2", tookMs: data.took_ms };
2738
3606
  }
2739
3607
  /**
2740
3608
  * Calculates inner product between two vectors
2741
- * @param vector1 - First vector
2742
- * @param vector2 - Second vector
2743
- * @returns Promise resolving to inner product result
2744
3609
  */
2745
3610
  async innerProduct(vector1, vector2) {
2746
3611
  if (vector1.length !== vector2.length) {
2747
3612
  throw new VectorError("Vector dimensions must match", "DIMENSION_MISMATCH");
2748
3613
  }
2749
- const { data } = await this.httpClient.post("/vectors/inner-product", {
2750
- vector1,
2751
- vector2
3614
+ const { data } = await this.httpClient.post("/vector-algebra/operation", {
3615
+ op: "inner_product",
3616
+ a: vector1,
3617
+ b: vector2
2752
3618
  });
2753
- return {
2754
- similarity: data.inner_product,
2755
- function: "inner_product",
2756
- tookMs: data.took_ms
2757
- };
3619
+ return { similarity: data.scalar ?? data.inner_product ?? 0, function: "inner_product", tookMs: data.took_ms };
2758
3620
  }
2759
3621
  /**
2760
- * Performs K-nearest neighbors vector search
2761
- * @param options - KNN search options
2762
- * @returns Promise resolving to KNN search results
3622
+ * Performs K-nearest neighbors vector search.
3623
+ * v0.2.0: routes through /vectors/collections/:c/search with mode discriminator.
2763
3624
  */
2764
3625
  async knnSearch(options) {
2765
- const { data } = await this.httpClient.post("/vectors/knn-search", {
2766
- query_vector: options.queryVector,
2767
- k: options.k,
2768
- table_name: options.tableName,
2769
- vector_column: options.vectorColumn,
2770
- metadata_columns: options.metadataColumns,
3626
+ const collection = options.collectionName ?? options.tableName;
3627
+ const { data } = await this.httpClient.post(`/vectors/collections/${collection}/search`, {
3628
+ mode: "knn",
3629
+ vector: options.queryVector,
3630
+ limit: options.k,
2771
3631
  filter: options.filter
2772
3632
  });
2773
- return data.results.map((result) => ({
2774
- id: result.id,
2775
- vector: result.vector,
2776
- similarity: result.similarity,
2777
- distance: result.distance,
2778
- metadata: result.metadata
3633
+ return (data.matches ?? data.results ?? []).map((r) => ({
3634
+ id: r.id,
3635
+ vector: r.vector,
3636
+ similarity: r.similarity,
3637
+ distance: r.distance,
3638
+ metadata: r.metadata
2779
3639
  }));
2780
3640
  }
2781
3641
  /**
2782
- * Performs range-based vector similarity search
2783
- * @param options - Range search options
2784
- * @returns Promise resolving to range search results
3642
+ * Performs range-based vector similarity search.
2785
3643
  */
2786
3644
  async rangeSearch(options) {
2787
- const { data } = await this.httpClient.post("/vectors/range-search", {
2788
- query_vector: options.queryVector,
3645
+ const collection = options.collectionName ?? options.tableName;
3646
+ const { data } = await this.httpClient.post(`/vectors/collections/${collection}/search`, {
3647
+ mode: "range",
3648
+ vector: options.queryVector,
2789
3649
  threshold: options.threshold,
2790
- table_name: options.tableName,
2791
- vector_column: options.vectorColumn,
2792
- metadata_columns: options.metadataColumns,
2793
- filter: options.filter,
2794
- max_results: options.maxResults
2795
- });
2796
- return data.results.map((result) => ({
2797
- id: result.id,
2798
- vector: result.vector,
2799
- similarity: result.similarity,
2800
- distance: result.distance,
2801
- metadata: result.metadata
3650
+ max_results: options.maxResults,
3651
+ filter: options.filter
3652
+ });
3653
+ return (data.matches ?? data.results ?? []).map((r) => ({
3654
+ id: r.id,
3655
+ vector: r.vector,
3656
+ similarity: r.similarity,
3657
+ distance: r.distance,
3658
+ metadata: r.metadata
2802
3659
  }));
2803
3660
  }
2804
3661
  /**
2805
- * Performs hybrid search combining vector similarity and SQL filtering
2806
- * @param options - Hybrid search options
2807
- * @returns Promise resolving to hybrid search results
3662
+ * Performs hybrid search combining vector similarity and SQL filtering.
2808
3663
  */
2809
3664
  async hybridSearch(options) {
2810
- const { data } = await this.httpClient.post("/vectors/hybrid-search", {
3665
+ const collection = options.collectionName ?? options.tableName;
3666
+ const { data } = await this.httpClient.post(`/vectors/collections/${collection}/search`, {
3667
+ mode: "hybrid",
2811
3668
  vector: options.vector,
2812
3669
  text_query: options.textQuery,
2813
3670
  sql_filter: options.sqlFilter,
2814
- k: options.k,
3671
+ limit: options.k,
2815
3672
  threshold: options.threshold,
2816
3673
  metric: options.metric,
2817
3674
  filter: options.filter,
2818
3675
  weights: options.weights
2819
3676
  });
2820
- return data.results.map((result) => ({
2821
- id: result.id,
2822
- vector: result.vector,
2823
- similarity: result.similarity,
2824
- distance: result.distance,
2825
- metadata: result.metadata
3677
+ return (data.matches ?? data.results ?? []).map((r) => ({
3678
+ id: r.id,
3679
+ vector: r.vector,
3680
+ similarity: r.similarity,
3681
+ distance: r.distance,
3682
+ metadata: r.metadata
2826
3683
  }));
2827
3684
  }
2828
3685
  /**
2829
3686
  * Normalizes a vector to unit length
2830
- * @param vector - Input vector to normalize
2831
- * @returns Promise resolving to normalized vector
2832
3687
  */
2833
3688
  async normalizeVector(vector) {
2834
- const { data } = await this.httpClient.post("/vectors/normalize", {
2835
- vector
3689
+ const { data } = await this.httpClient.post("/vector-algebra/operation", {
3690
+ op: "normalize",
3691
+ a: vector
2836
3692
  });
3693
+ const result = data.result ?? data.vector ?? [];
2837
3694
  return {
2838
- result: { values: data.result, dimensions: data.result.length },
3695
+ result: { values: result, dimensions: result.length },
2839
3696
  operation: "normalization",
2840
3697
  tookMs: data.took_ms
2841
3698
  };
2842
3699
  }
2843
3700
  /**
2844
3701
  * Calculates the magnitude (length) of a vector
2845
- * @param vector - Input vector
2846
- * @returns Promise resolving to vector magnitude
2847
3702
  */
2848
3703
  async vectorMagnitude(vector) {
2849
- const { data } = await this.httpClient.post("/vectors/magnitude", {
2850
- vector
3704
+ const { data } = await this.httpClient.post("/vector-algebra/operation", {
3705
+ op: "magnitude",
3706
+ a: vector
2851
3707
  });
2852
- return {
2853
- magnitude: data.magnitude,
2854
- tookMs: data.took_ms
2855
- };
3708
+ return { magnitude: data.scalar ?? data.magnitude ?? 0, tookMs: data.took_ms };
2856
3709
  }
2857
3710
  // =================================================================
2858
3711
  // AUTHENTICATION & USER MANAGEMENT
@@ -2884,16 +3737,26 @@ var SynapCores = class {
2884
3737
  return data;
2885
3738
  }
2886
3739
  /**
2887
- * Refresh JWT token
3740
+ * Refresh JWT token.
3741
+ *
3742
+ * v0.2.0: the gateway does not currently expose a refresh endpoint —
3743
+ * this method now re-runs login() with the same credentials. Pass
3744
+ * the credentials in the call site (or supply them at SDK construction
3745
+ * time and we'll re-use the cached pair).
2888
3746
  */
2889
- async refreshToken() {
2890
- const { data } = await this.httpClient.post("/auth/refresh");
2891
- if (data.access_token) {
2892
- this.config.jwtToken = data.access_token;
2893
- this.httpClient.defaults.headers["Authorization"] = `Bearer ${data.access_token}`;
2894
- delete this.httpClient.defaults.headers["X-API-Key"];
3747
+ async refreshToken(credentials) {
3748
+ if (credentials?.username && credentials?.password) {
3749
+ const login = await this.login({ username: credentials.username, password: credentials.password });
3750
+ return {
3751
+ access_token: login.access_token,
3752
+ refresh_token: "",
3753
+ token_type: "Bearer",
3754
+ expires_in: login.expires_in
3755
+ };
2895
3756
  }
2896
- return data;
3757
+ throw new ValidationError(
3758
+ "refreshToken now requires credentials \u2014 the gateway has no /auth/refresh endpoint in v1.5.0-ce. Pass {username, password} or call login() again."
3759
+ );
2897
3760
  }
2898
3761
  /**
2899
3762
  * Set JWT token manually (useful after login)
@@ -3024,17 +3887,23 @@ var SynapCores = class {
3024
3887
 
3025
3888
  // src/index.ts
3026
3889
  import { z } from "zod";
3027
- var VERSION = "0.1.0";
3890
+ var VERSION = "0.2.0";
3028
3891
  export {
3029
3892
  AuthenticationError,
3030
3893
  AutoMLClient,
3031
3894
  AutoMLModel,
3032
3895
  BackupClient,
3033
3896
  BatchOperationError,
3897
+ ChatClient,
3034
3898
  Collection,
3035
3899
  ConnectionError,
3900
+ FilesystemCollectionsClient,
3901
+ GraphClient,
3036
3902
  ImportExportClient,
3037
3903
  IntegrationClient,
3904
+ McpClient,
3905
+ MultimodalClient,
3906
+ NL2SqlClient,
3038
3907
  NLPClient,
3039
3908
  NotFoundError,
3040
3909
  RateLimitError,
@@ -3045,8 +3914,11 @@ export {
3045
3914
  Subscription,
3046
3915
  SynapCores,
3047
3916
  SynapCoresError,
3917
+ SystemClient,
3048
3918
  TimeoutError,
3049
3919
  TransactionError,
3920
+ TransactionsClient,
3921
+ Tx,
3050
3922
  VERSION,
3051
3923
  ValidationError,
3052
3924
  VectorError,