@synapcores/sdk 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.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,972 @@ 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
+ * The gateway's MatchRequest expects `sql: String` (see
1980
+ * crates/aidb-gateway/src/routes/graph.rs MatchRequest); we keep the
1981
+ * SDK-facing parameter named `query` because every caller writes
1982
+ * Cypher, not SQL — the gateway's field name is a historical artifact.
1983
+ */
1984
+ async cypher(query, params = {}, graph) {
1985
+ const { data } = await this.synapCores._getHttpClient().post("/graph/match", {
1986
+ sql: query,
1987
+ params,
1988
+ graph
1989
+ });
1990
+ return this.normalizeCypher(data);
1991
+ }
1992
+ /**
1993
+ * Profile a Cypher / MATCH query (returns plan/profile metadata).
1994
+ */
1995
+ async cypherProfile(query, params = {}, graph) {
1996
+ const { data } = await this.synapCores._getHttpClient().post("/graph/match/profile", {
1997
+ sql: query,
1998
+ params,
1999
+ graph
2000
+ });
2001
+ return {
2002
+ ...this.normalizeCypher(data),
2003
+ plan: data.plan,
2004
+ profile: data.profile ?? data.profile_data
2005
+ };
2006
+ }
2007
+ /**
2008
+ * Run LLM-based extraction over text into the given graph.
2009
+ */
2010
+ async extract(req, graphName) {
2011
+ const body = typeof req === "string" ? { text: req, graph: graphName } : req;
2012
+ const { data } = await this.synapCores._getHttpClient().post("/graph/extract", body);
2013
+ return {
2014
+ nodes: (data.nodes ?? []).map((n) => ({
2015
+ id: String(n.id ?? ""),
2016
+ label: n.label,
2017
+ labels: n.labels,
2018
+ properties: n.properties ?? n.props ?? {}
2019
+ })),
2020
+ edges: (data.edges ?? []).map((e) => ({
2021
+ id: e.id !== void 0 ? String(e.id) : void 0,
2022
+ from: String(e.from ?? e.source ?? ""),
2023
+ to: String(e.to ?? e.target ?? ""),
2024
+ type: e.type ?? e.label ?? "",
2025
+ properties: e.properties ?? e.props ?? {}
2026
+ })),
2027
+ spans: data.spans
2028
+ };
2029
+ }
2030
+ normalizeCypher(data) {
2031
+ return {
2032
+ columns: data.columns ?? data.fields,
2033
+ rows: data.rows ?? data.values ?? [],
2034
+ records: data.records ?? data.results,
2035
+ stats: data.stats,
2036
+ execution_time_ms: data.execution_time_ms ?? data.took_ms
2037
+ };
2038
+ }
2039
+ };
2040
+
2041
+ // src/nl2sql.ts
2042
+ var NL2SqlClient = class {
2043
+ constructor(synapCores) {
2044
+ this.synapCores = synapCores;
2045
+ }
2046
+ /**
2047
+ * Ask a question in natural language. The gateway returns the
2048
+ * generated SQL and optionally the executed result set when
2049
+ * `execute=true`.
2050
+ */
2051
+ async ask(question, opts = {}) {
2052
+ const { data } = await this.synapCores._getHttpClient().post("/nl2sql/query", {
2053
+ question,
2054
+ ...opts
2055
+ });
2056
+ return {
2057
+ sql: data.sql ?? data.generated_sql ?? "",
2058
+ confidence: data.confidence,
2059
+ rows: data.rows ?? data.data,
2060
+ columns: data.columns,
2061
+ execution_time_ms: data.execution_time_ms ?? data.took_ms,
2062
+ trace: data.trace ?? data.plan,
2063
+ question
2064
+ };
2065
+ }
2066
+ /**
2067
+ * Push schema context the model should use for subsequent ask() calls.
2068
+ */
2069
+ async updateSchemaContext(payload) {
2070
+ const { data } = await this.synapCores._getHttpClient().post(
2071
+ "/nl2sql/schema/context",
2072
+ payload
2073
+ );
2074
+ return { accepted: data.accepted ?? data.success ?? true, raw: data };
2075
+ }
2076
+ /**
2077
+ * Retrieve recent NL2SQL history for the current authenticated user.
2078
+ */
2079
+ async history(opts = {}) {
2080
+ const params = new URLSearchParams();
2081
+ if (opts.limit) params.append("limit", String(opts.limit));
2082
+ if (opts.session_id) params.append("session_id", opts.session_id);
2083
+ const qs = params.toString();
2084
+ const { data } = await this.synapCores._getHttpClient().get(
2085
+ `/nl2sql/history${qs ? `?${qs}` : ""}`
2086
+ );
2087
+ return (data.history ?? data.entries ?? data ?? []).map((row) => ({
2088
+ id: String(row.id ?? row.entry_id ?? ""),
2089
+ question: row.question ?? row.prompt ?? "",
2090
+ sql: row.sql ?? row.generated_sql ?? "",
2091
+ created_at: new Date(row.created_at ?? row.timestamp ?? Date.now()),
2092
+ executed: row.executed,
2093
+ success: row.success
2094
+ }));
2095
+ }
2096
+ /**
2097
+ * Validate a SQL string against the current schema and policies.
2098
+ */
2099
+ async validate(sql) {
2100
+ const { data } = await this.synapCores._getHttpClient().post("/nl2sql/validate", {
2101
+ sql
2102
+ });
2103
+ return {
2104
+ is_valid: data.is_valid ?? data.valid ?? false,
2105
+ errors: data.errors ?? [],
2106
+ warnings: data.warnings ?? [],
2107
+ rewritten_sql: data.rewritten_sql ?? data.sql
2108
+ };
2109
+ }
2110
+ };
2111
+
2112
+ // src/filesystem.ts
2113
+ import WebSocket2 from "ws";
2114
+ var FsCollectionsApi = class {
2115
+ constructor(synapCores) {
2116
+ this.synapCores = synapCores;
2117
+ }
2118
+ async create(opts) {
2119
+ const { data } = await this.synapCores._getHttpClient().post(
2120
+ "/filesystem-collections",
2121
+ opts
2122
+ );
2123
+ return this.normalize(data);
2124
+ }
2125
+ async list() {
2126
+ const { data } = await this.synapCores._getHttpClient().get("/filesystem-collections");
2127
+ return (data.collections ?? data ?? []).map((c) => this.normalize(c));
2128
+ }
2129
+ async get(id) {
2130
+ const { data } = await this.synapCores._getHttpClient().get(
2131
+ `/filesystem-collections/${id}`
2132
+ );
2133
+ return this.normalize(data);
2134
+ }
2135
+ async patch(id, p) {
2136
+ const { data } = await this.synapCores._getHttpClient().patch(
2137
+ `/filesystem-collections/${id}`,
2138
+ p
2139
+ );
2140
+ return this.normalize(data);
2141
+ }
2142
+ async delete(id) {
2143
+ await this.synapCores._getHttpClient().delete(`/filesystem-collections/${id}`);
2144
+ }
2145
+ async documents(id, opts = {}) {
2146
+ const params = new URLSearchParams();
2147
+ if (opts.page) params.append("page", String(opts.page));
2148
+ if (opts.page_size) params.append("page_size", String(opts.page_size));
2149
+ const qs = params.toString();
2150
+ const { data } = await this.synapCores._getHttpClient().get(
2151
+ `/filesystem-collections/${id}/documents${qs ? `?${qs}` : ""}`
2152
+ );
2153
+ return (data.documents ?? data ?? []).map((d) => ({
2154
+ id: String(d.id ?? d.document_id ?? ""),
2155
+ collection_id: d.collection_id !== void 0 ? String(d.collection_id) : id,
2156
+ filename: d.filename ?? d.name,
2157
+ path: d.path,
2158
+ status: d.status,
2159
+ size_bytes: d.size_bytes,
2160
+ created_at: d.created_at ? new Date(d.created_at) : void 0,
2161
+ updated_at: d.updated_at ? new Date(d.updated_at) : void 0
2162
+ }));
2163
+ }
2164
+ async reprocess(id, fileId) {
2165
+ const body = fileId ? { document_id: fileId } : {};
2166
+ const { data } = await this.synapCores._getHttpClient().post(
2167
+ `/filesystem-collections/${id}/reprocess`,
2168
+ body
2169
+ );
2170
+ return { accepted: data.accepted ?? data.success ?? true, raw: data };
2171
+ }
2172
+ /**
2173
+ * Stream progress events for an in-flight ingestion. Each tick maps to
2174
+ * a JSON payload broadcast by the gateway over the WS channel. The
2175
+ * iterator ends when the server closes the socket or the consumer
2176
+ * breaks out of the for-await loop.
2177
+ */
2178
+ async *subscribeProgress(id, opts = {}) {
2179
+ const { token } = await this.synapCores.createWsTicket();
2180
+ const wsBase = this.synapCores._getWsBaseUrl();
2181
+ const url = `${wsBase}/ws/filesystem-collections/${id}/progress?token=${encodeURIComponent(token)}`;
2182
+ const ws = new WebSocket2(url);
2183
+ const queue = [];
2184
+ let resolver = null;
2185
+ const push = (p) => {
2186
+ if (resolver) {
2187
+ const r = resolver;
2188
+ resolver = null;
2189
+ r(p);
2190
+ } else {
2191
+ queue.push(p);
2192
+ }
2193
+ };
2194
+ ws.on("message", (raw) => {
2195
+ try {
2196
+ const obj = JSON.parse(raw.toString());
2197
+ push({
2198
+ kind: "value",
2199
+ value: {
2200
+ type: obj.type ?? obj.event ?? "progress",
2201
+ collection_id: obj.collection_id !== void 0 ? String(obj.collection_id) : id,
2202
+ document_id: obj.document_id !== void 0 ? String(obj.document_id) : void 0,
2203
+ filename: obj.filename ?? obj.path,
2204
+ status: obj.status,
2205
+ progress: obj.progress,
2206
+ message: obj.message,
2207
+ error: obj.error,
2208
+ timestamp: obj.timestamp ? new Date(obj.timestamp) : void 0,
2209
+ raw: obj
2210
+ }
2211
+ });
2212
+ } catch (e) {
2213
+ push({ kind: "error", error: e });
2214
+ }
2215
+ });
2216
+ ws.on("error", (err) => push({ kind: "error", error: err }));
2217
+ ws.on("close", () => push({ kind: "done" }));
2218
+ const onAbort = () => {
2219
+ try {
2220
+ ws.close();
2221
+ } catch {
2222
+ }
2223
+ };
2224
+ if (opts.signal) {
2225
+ if (opts.signal.aborted) onAbort();
2226
+ else opts.signal.addEventListener("abort", onAbort);
2227
+ }
2228
+ try {
2229
+ while (true) {
2230
+ const next = await new Promise((resolve) => {
2231
+ if (queue.length > 0) {
2232
+ resolve(queue.shift());
2233
+ } else {
2234
+ resolver = resolve;
2235
+ }
2236
+ });
2237
+ if (next.kind === "value") yield next.value;
2238
+ else if (next.kind === "error") throw next.error;
2239
+ else return;
2240
+ }
2241
+ } finally {
2242
+ try {
2243
+ ws.close();
2244
+ } catch {
2245
+ }
2246
+ if (opts.signal) opts.signal.removeEventListener("abort", onAbort);
2247
+ }
2248
+ }
2249
+ normalize(data) {
2250
+ return {
2251
+ id: String(data.id ?? data.collection_id ?? ""),
2252
+ name: data.name,
2253
+ description: data.description,
2254
+ path: data.path,
2255
+ status: data.status,
2256
+ document_count: data.document_count ?? data.documents,
2257
+ created_at: data.created_at ? new Date(data.created_at) : void 0,
2258
+ updated_at: data.updated_at ? new Date(data.updated_at) : void 0,
2259
+ config: data.config
2260
+ };
2261
+ }
2262
+ };
2263
+ var FilesystemCollectionsClient = class {
2264
+ constructor(synapCores) {
2265
+ this.collections = new FsCollectionsApi(synapCores);
2266
+ }
2267
+ };
2268
+
2269
+ // src/chat.ts
2270
+ var ChatSessionsApi = class {
2271
+ constructor(synapCores) {
2272
+ this.synapCores = synapCores;
2273
+ }
2274
+ async create(opts = {}) {
2275
+ const { data } = await this.synapCores._getHttpClient().post("/ai/sessions", opts);
2276
+ return this.normalize(data);
2277
+ }
2278
+ async list(opts = {}) {
2279
+ const params = new URLSearchParams();
2280
+ if (opts.limit) params.append("limit", String(opts.limit));
2281
+ if (opts.offset) params.append("offset", String(opts.offset));
2282
+ const qs = params.toString();
2283
+ const { data } = await this.synapCores._getHttpClient().get(
2284
+ `/ai/sessions${qs ? `?${qs}` : ""}`
2285
+ );
2286
+ return (data.sessions ?? data ?? []).map((s) => this.normalize(s));
2287
+ }
2288
+ async get(id) {
2289
+ const { data } = await this.synapCores._getHttpClient().get(`/ai/sessions/${id}`);
2290
+ return this.normalize(data);
2291
+ }
2292
+ async delete(id) {
2293
+ await this.synapCores._getHttpClient().delete(`/ai/sessions/${id}`);
2294
+ }
2295
+ async messages(id, opts = {}) {
2296
+ const params = new URLSearchParams();
2297
+ if (opts.limit) params.append("limit", String(opts.limit));
2298
+ if (opts.offset) params.append("offset", String(opts.offset));
2299
+ const qs = params.toString();
2300
+ const { data } = await this.synapCores._getHttpClient().get(
2301
+ `/ai/sessions/${id}/messages${qs ? `?${qs}` : ""}`
2302
+ );
2303
+ return (data.messages ?? data ?? []).map((m) => this.normalizeMessage(m, id));
2304
+ }
2305
+ normalize(data) {
2306
+ return {
2307
+ id: String(data.id ?? data.session_id ?? ""),
2308
+ title: data.title,
2309
+ model: data.model,
2310
+ system_prompt: data.system_prompt,
2311
+ created_at: new Date(data.created_at ?? Date.now()),
2312
+ updated_at: data.updated_at ? new Date(data.updated_at) : void 0,
2313
+ message_count: data.message_count ?? data.messages,
2314
+ metadata: data.metadata
2315
+ };
2316
+ }
2317
+ normalizeMessage(m, sessionId) {
2318
+ return {
2319
+ id: String(m.id ?? m.message_id ?? ""),
2320
+ session_id: m.session_id !== void 0 ? String(m.session_id) : sessionId,
2321
+ role: m.role,
2322
+ content: m.content ?? m.text ?? "",
2323
+ created_at: new Date(m.created_at ?? Date.now()),
2324
+ metadata: m.metadata
2325
+ };
2326
+ }
2327
+ };
2328
+ var ChatToolsApi = class {
2329
+ constructor(synapCores) {
2330
+ this.synapCores = synapCores;
2331
+ }
2332
+ async list() {
2333
+ const { data } = await this.synapCores._getHttpClient().get("/ai/tools");
2334
+ return (data.tools ?? data ?? []).map((t) => ({
2335
+ name: t.name,
2336
+ description: t.description,
2337
+ parameters: t.parameters ?? t.schema
2338
+ }));
2339
+ }
2340
+ async execute(name, args = {}) {
2341
+ const { data } = await this.synapCores._getHttpClient().post("/ai/tools/execute", {
2342
+ tool: name,
2343
+ arguments: args
2344
+ });
2345
+ return data;
2346
+ }
2347
+ async sql(sql, params = []) {
2348
+ const { data } = await this.synapCores._getHttpClient().post("/ai/tools/sql", {
2349
+ sql,
2350
+ parameters: params
2351
+ });
2352
+ return data;
2353
+ }
2354
+ };
2355
+ var ChatCacheApi = class {
2356
+ constructor(synapCores) {
2357
+ this.synapCores = synapCores;
2358
+ }
2359
+ async stats() {
2360
+ const { data } = await this.synapCores._getHttpClient().get("/ai/cache/stats");
2361
+ return {
2362
+ size_bytes: data.size_bytes ?? data.bytes,
2363
+ hit_count: data.hit_count ?? data.hits,
2364
+ miss_count: data.miss_count ?? data.misses,
2365
+ entries: data.entries ?? data.count,
2366
+ raw: data
2367
+ };
2368
+ }
2369
+ async clear() {
2370
+ await this.synapCores._getHttpClient().post("/ai/cache/clear", {});
2371
+ }
2372
+ };
2373
+ var ChatClient = class {
2374
+ constructor(synapCores) {
2375
+ this.synapCores = synapCores;
2376
+ this.sessions = new ChatSessionsApi(synapCores);
2377
+ this.tools = new ChatToolsApi(synapCores);
2378
+ this.cache = new ChatCacheApi(synapCores);
2379
+ }
2380
+ /**
2381
+ * Send a one-shot chat message. The gateway accepts both /ai/chat and
2382
+ * the alias /ai/ — we use /ai/chat for clarity.
2383
+ */
2384
+ async send(sessionId, content, opts = {}) {
2385
+ const { data } = await this.synapCores._getHttpClient().post("/ai/chat", {
2386
+ session_id: sessionId,
2387
+ content,
2388
+ ...opts
2389
+ });
2390
+ const messageData = data.message ?? data;
2391
+ return {
2392
+ message: {
2393
+ id: String(messageData.id ?? messageData.message_id ?? ""),
2394
+ session_id: sessionId,
2395
+ role: messageData.role ?? "assistant",
2396
+ content: messageData.content ?? messageData.text ?? "",
2397
+ created_at: new Date(messageData.created_at ?? Date.now()),
2398
+ metadata: messageData.metadata
2399
+ },
2400
+ tool_calls: data.tool_calls,
2401
+ usage: data.usage
2402
+ };
2403
+ }
2404
+ /**
2405
+ * Stream a chat completion. Returns an async iterator over SSE chunks.
2406
+ */
2407
+ async *stream(sessionId, content, opts = {}) {
2408
+ const http = this.synapCores._getHttpClient();
2409
+ const response = await http.post(
2410
+ "/ai/chat/stream",
2411
+ {
2412
+ session_id: sessionId,
2413
+ content,
2414
+ ...opts
2415
+ },
2416
+ { responseType: "stream" }
2417
+ );
2418
+ const stream = response.data;
2419
+ let buffer = "";
2420
+ for await (const chunk of stream) {
2421
+ buffer += chunk.toString();
2422
+ const frames = buffer.split(/\n\n/);
2423
+ buffer = frames.pop() ?? "";
2424
+ for (const frame of frames) {
2425
+ const trimmed = frame.trim();
2426
+ if (!trimmed) continue;
2427
+ const line = trimmed.startsWith("data:") ? trimmed.slice(5).trim() : trimmed;
2428
+ if (line === "[DONE]") {
2429
+ yield { done: true };
2430
+ return;
2431
+ }
2432
+ try {
2433
+ const obj = JSON.parse(line);
2434
+ yield {
2435
+ delta: obj.delta ?? obj.choices?.[0]?.delta?.content ?? obj.text ?? void 0,
2436
+ content: obj.content ?? obj.message?.content,
2437
+ type: obj.type ?? obj.event,
2438
+ done: obj.done ?? obj.finished,
2439
+ raw: obj
2440
+ };
2441
+ } catch {
2442
+ yield { delta: line, raw: line };
2443
+ }
2444
+ }
2445
+ }
2446
+ if (buffer.trim()) {
2447
+ try {
2448
+ yield { raw: JSON.parse(buffer) };
2449
+ } catch {
2450
+ yield { delta: buffer };
2451
+ }
2452
+ }
2453
+ }
2454
+ /**
2455
+ * Get prompt suggestions, e.g. for an empty session UI.
2456
+ */
2457
+ async suggestions(opts = {}) {
2458
+ const { data } = await this.synapCores._getHttpClient().post("/ai/suggestions", opts);
2459
+ return (data.suggestions ?? data ?? []).map((s) => ({
2460
+ prompt: s.prompt ?? s.text ?? "",
2461
+ category: s.category,
2462
+ meta: s.meta ?? s.metadata
2463
+ }));
2464
+ }
2465
+ /**
2466
+ * List configured chat models.
1774
2467
  */
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
- };
2468
+ async models() {
2469
+ const { data } = await this.synapCores._getHttpClient().get("/ai/models");
2470
+ return (data.models ?? data ?? []).map((m) => ({
2471
+ id: m.id ?? m.name,
2472
+ name: m.name,
2473
+ provider: m.provider,
2474
+ context_window: m.context_window ?? m.max_context,
2475
+ capabilities: m.capabilities
2476
+ }));
1790
2477
  }
1791
2478
  /**
1792
- * Get backup metrics
2479
+ * List the available system prompts library.
1793
2480
  */
1794
- async getMetrics() {
1795
- const { data } = await this.synapCores._getHttpClient().get("/backups/metrics");
2481
+ async systemPrompts() {
2482
+ const { data } = await this.synapCores._getHttpClient().get("/ai/system-prompts");
2483
+ return (data.prompts ?? data.system_prompts ?? data ?? []).map((p) => ({
2484
+ id: String(p.id ?? p.name ?? ""),
2485
+ name: p.name,
2486
+ content: p.content ?? p.text ?? "",
2487
+ description: p.description,
2488
+ category: p.category
2489
+ }));
2490
+ }
2491
+ };
2492
+
2493
+ // src/multimodal.ts
2494
+ var MultimodalClient = class {
2495
+ constructor(synapCores) {
2496
+ this.synapCores = synapCores;
2497
+ }
2498
+ async similarity(a, b, opts = {}) {
2499
+ const { data } = await this.synapCores._getHttpClient().post("/multimodal/similarity", {
2500
+ a: typeof a === "string" ? { type: "text", text: a } : a,
2501
+ b: typeof b === "string" ? { type: "text", text: b } : b,
2502
+ ...opts
2503
+ });
1796
2504
  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
2505
+ similarity: data.similarity ?? data.score ?? 0,
2506
+ metric: data.metric ?? opts.metric,
2507
+ raw: data
1805
2508
  };
1806
2509
  }
1807
- /**
1808
- * Map raw backup data to Backup type
1809
- */
1810
- mapBackup(data) {
2510
+ async search(query, opts = {}) {
2511
+ const { data } = await this.synapCores._getHttpClient().post("/multimodal/search", {
2512
+ query: typeof query === "string" ? { type: "text", text: query } : query,
2513
+ ...opts
2514
+ });
2515
+ return (data.results ?? data.hits ?? data ?? []).map((r) => ({
2516
+ id: String(r.id ?? r.document_id ?? ""),
2517
+ score: r.score ?? r.similarity ?? 0,
2518
+ modality: r.modality,
2519
+ metadata: r.metadata
2520
+ }));
2521
+ }
2522
+ async join(left, right, opts = {}) {
2523
+ const normalize = (side) => Array.isArray(side) ? side.map((s) => typeof s === "string" ? { type: "text", text: s } : s) : side;
2524
+ const { data } = await this.synapCores._getHttpClient().post("/multimodal/join", {
2525
+ left: normalize(left),
2526
+ right: normalize(right),
2527
+ ...opts
2528
+ });
1811
2529
  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
2530
+ pairs: (data.pairs ?? data.results ?? []).map((p) => ({
2531
+ left: p.left,
2532
+ right: p.right,
2533
+ score: p.score ?? p.similarity ?? 0
2534
+ }))
2535
+ };
2536
+ }
2537
+ async embed(input, model) {
2538
+ const { data } = await this.synapCores._getHttpClient().post("/multimodal/embed", {
2539
+ input: typeof input === "string" ? { type: "text", text: input } : input,
2540
+ model
2541
+ });
2542
+ const embedding = data.embedding ?? data.vector ?? [];
2543
+ return {
2544
+ embedding,
2545
+ modality: data.modality,
2546
+ model: data.model ?? model,
2547
+ dimensions: data.dimensions ?? embedding.length
1829
2548
  };
1830
2549
  }
1831
2550
  };
1832
2551
 
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);
2552
+ // src/system.ts
2553
+ var VisionApi = class {
2554
+ constructor(synapCores) {
2555
+ this.synapCores = synapCores;
2556
+ }
2557
+ async get() {
2558
+ try {
2559
+ const { data } = await this.synapCores._getHttpClient().get("/system/vision");
2560
+ if (!data || Object.keys(data).length === 0) return null;
2561
+ return data;
2562
+ } catch (e) {
2563
+ if (e?.statusCode === 404 || e?.code === "NOT_FOUND") return null;
2564
+ throw e;
1842
2565
  }
1843
2566
  }
1844
- };
1845
- var ConnectionError = class extends SynapCoresError {
1846
- constructor(message, details) {
1847
- super(message, "CONNECTION_ERROR", details);
1848
- this.name = "ConnectionError";
2567
+ async set(cfg) {
2568
+ const { data } = await this.synapCores._getHttpClient().put("/system/vision", cfg);
2569
+ return data;
1849
2570
  }
1850
- };
1851
- var AuthenticationError = class extends SynapCoresError {
1852
- constructor(message, details) {
1853
- super(message, "AUTH_ERROR", details);
1854
- this.name = "AuthenticationError";
2571
+ async delete() {
2572
+ await this.synapCores._getHttpClient().delete("/system/vision");
1855
2573
  }
1856
- };
1857
- var ValidationError = class extends SynapCoresError {
1858
- constructor(message, details) {
1859
- super(message, "VALIDATION_ERROR", details);
1860
- this.name = "ValidationError";
2574
+ async test(payload = {}) {
2575
+ const { data } = await this.synapCores._getHttpClient().post("/system/vision/test", payload);
2576
+ return {
2577
+ success: data.success ?? false,
2578
+ latency_ms: data.latency_ms,
2579
+ response: data.response,
2580
+ error: data.error
2581
+ };
1861
2582
  }
1862
2583
  };
1863
- var NotFoundError = class extends SynapCoresError {
1864
- constructor(message, details) {
1865
- super(message, "NOT_FOUND", details);
1866
- this.name = "NotFoundError";
2584
+ var SystemClient = class {
2585
+ constructor(synapCores) {
2586
+ this.vision = new VisionApi(synapCores);
1867
2587
  }
1868
2588
  };
1869
- var ServerError = class extends SynapCoresError {
1870
- constructor(message, details) {
1871
- super(message, "SERVER_ERROR", details);
1872
- this.name = "ServerError";
2589
+
2590
+ // src/transactions.ts
2591
+ var Tx = class {
2592
+ constructor(http, id, options) {
2593
+ this.http = http;
2594
+ this.id = id;
2595
+ this.options = options;
2596
+ this.active = true;
1873
2597
  }
1874
- };
1875
- var TimeoutError = class extends SynapCoresError {
1876
- constructor(message, details) {
1877
- super(message, "TIMEOUT_ERROR", details);
1878
- this.name = "TimeoutError";
2598
+ isActive() {
2599
+ return this.active;
1879
2600
  }
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;
2601
+ async execute(sql, params = []) {
2602
+ this.assertActive();
2603
+ const { data } = await this.http.post(`/transactions/${this.id}/execute`, {
2604
+ sql,
2605
+ parameters: params
2606
+ });
2607
+ return {
2608
+ columns: data.columns ?? [],
2609
+ rows: data.rows ?? [],
2610
+ rows_affected: data.rows_affected,
2611
+ execution_time_ms: data.execution_time_ms ?? data.took_ms
2612
+ };
1886
2613
  }
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;
2614
+ async commit() {
2615
+ this.assertActive();
2616
+ await this.http.post(`/transactions/${this.id}/commit`, {});
2617
+ this.active = false;
2618
+ }
2619
+ async rollback() {
2620
+ this.assertActive();
2621
+ await this.http.post(`/transactions/${this.id}/rollback`, {});
2622
+ this.active = false;
2623
+ }
2624
+ async savepoint(name) {
2625
+ this.assertActive();
2626
+ await this.http.post(`/transactions/${this.id}/savepoint`, { name });
2627
+ }
2628
+ async rollbackTo(name) {
2629
+ this.assertActive();
2630
+ await this.http.post(`/transactions/${this.id}/savepoint/${name}/rollback`, {});
2631
+ }
2632
+ assertActive() {
2633
+ if (!this.active) {
2634
+ throw new Error(`Transaction ${this.id} has already been committed/rolled back`);
2635
+ }
1896
2636
  }
1897
2637
  };
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;
2638
+ var TxHistoryApi = class {
2639
+ constructor(synapCores) {
2640
+ this.synapCores = synapCores;
2641
+ }
2642
+ async list(opts = {}) {
2643
+ const params = new URLSearchParams();
2644
+ if (opts.limit) params.append("limit", String(opts.limit));
2645
+ if (opts.status) params.append("status", opts.status);
2646
+ const qs = params.toString();
2647
+ const { data } = await this.synapCores._getHttpClient().get(
2648
+ `/transactions/history${qs ? `?${qs}` : ""}`
2649
+ );
2650
+ return (data.transactions ?? data.history ?? data ?? []).map((row) => ({
2651
+ id: String(row.id ?? row.transaction_id ?? ""),
2652
+ status: row.status ?? "unknown",
2653
+ started_at: new Date(row.started_at ?? row.created_at ?? Date.now()),
2654
+ completed_at: row.completed_at ? new Date(row.completed_at) : void 0,
2655
+ isolation_level: row.isolation_level,
2656
+ read_only: row.read_only,
2657
+ statement_count: row.statement_count ?? row.statements,
2658
+ metrics: row.metrics
2659
+ }));
2660
+ }
2661
+ async get(id) {
2662
+ const { data } = await this.synapCores._getHttpClient().get(
2663
+ `/transactions/history/${id}`
2664
+ );
2665
+ return {
2666
+ id: String(data.id ?? id),
2667
+ status: data.status ?? "unknown",
2668
+ started_at: new Date(data.started_at ?? data.created_at ?? Date.now()),
2669
+ completed_at: data.completed_at ? new Date(data.completed_at) : void 0,
2670
+ isolation_level: data.isolation_level,
2671
+ read_only: data.read_only,
2672
+ statement_count: data.statement_count ?? data.statements,
2673
+ metrics: data.metrics
2674
+ };
1905
2675
  }
1906
2676
  };
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;
2677
+ var TransactionsClient = class {
2678
+ constructor(synapCores) {
2679
+ this.synapCores = synapCores;
2680
+ this.history = new TxHistoryApi(synapCores);
2681
+ }
2682
+ /**
2683
+ * Begin a new server-side transaction.
2684
+ */
2685
+ async begin(opts = {}) {
2686
+ const { data } = await this.synapCores._getHttpClient().post("/transactions", opts);
2687
+ const id = String(data.id ?? data.transaction_id ?? "");
2688
+ if (!id) {
2689
+ throw new Error("begin(): server did not return a transaction id");
2690
+ }
2691
+ return new Tx(this.synapCores._getHttpClient(), id, opts);
1913
2692
  }
1914
2693
  };
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;
2694
+
2695
+ // src/mcp.ts
2696
+ var mcpRequestCounter = 0;
2697
+ function withId(req) {
2698
+ if (req.id !== void 0 && req.id !== null) return req;
2699
+ mcpRequestCounter += 1;
2700
+ return { ...req, id: `mcp-${Date.now()}-${mcpRequestCounter}` };
2701
+ }
2702
+ var McpClient = class {
2703
+ constructor(synapCores) {
2704
+ this.synapCores = synapCores;
2705
+ }
2706
+ /**
2707
+ * Invoke a single MCP method.
2708
+ */
2709
+ async invoke(req) {
2710
+ const body = withId(req);
2711
+ const { data } = await this.synapCores._getHttpClient().post("/mcp", body);
2712
+ return {
2713
+ id: data.id ?? body.id,
2714
+ result: data.result,
2715
+ error: data.error,
2716
+ raw: data
2717
+ };
2718
+ }
2719
+ /**
2720
+ * Send an array of MCP invocations and resolve to the matching array
2721
+ * of responses (in the order returned by the gateway).
2722
+ */
2723
+ async batch(reqs) {
2724
+ const body = reqs.map(withId);
2725
+ const { data } = await this.synapCores._getHttpClient().post("/mcp/batch", body);
2726
+ const arr = Array.isArray(data) ? data : data.responses ?? data.results ?? [];
2727
+ return arr.map((r) => ({
2728
+ id: r.id,
2729
+ result: r.result,
2730
+ error: r.error,
2731
+ raw: r
2732
+ }));
2733
+ }
2734
+ /**
2735
+ * Discover the server's MCP capabilities and tools.
2736
+ */
2737
+ async info() {
2738
+ const { data } = await this.synapCores._getHttpClient().get("/mcp/info");
2739
+ return {
2740
+ version: data.version ?? data.mcp_version ?? "0",
2741
+ capabilities: data.capabilities,
2742
+ tools: data.tools,
2743
+ meta: data.meta ?? data.metadata
2744
+ };
1922
2745
  }
1923
2746
  };
1924
2747
 
@@ -1957,7 +2780,7 @@ var SynapCores = class {
1957
2780
  timeout: this.config.timeout,
1958
2781
  headers: {
1959
2782
  "Content-Type": "application/json",
1960
- "User-Agent": "synapcores-nodejs/0.1.0",
2783
+ "User-Agent": "synapcores-nodejs/0.2.0",
1961
2784
  ...authHeader
1962
2785
  },
1963
2786
  ...httpsAgent && { httpsAgent }
@@ -1973,6 +2796,44 @@ var SynapCores = class {
1973
2796
  this.import = new ImportExportClient(this);
1974
2797
  this.integrations = new IntegrationClient(this);
1975
2798
  this.backup = new BackupClient(this);
2799
+ this.graph = new GraphClient(this);
2800
+ this.nl2sql = new NL2SqlClient(this);
2801
+ this.filesystem = new FilesystemCollectionsClient(this);
2802
+ this.chat = new ChatClient(this);
2803
+ this.multimodal = new MultimodalClient(this);
2804
+ this.system = new SystemClient(this);
2805
+ this.transactions = new TransactionsClient(this);
2806
+ this.mcp = new McpClient(this);
2807
+ }
2808
+ /**
2809
+ * Build the WebSocket base URL (ws:// or wss://).
2810
+ */
2811
+ _getWsBaseUrl() {
2812
+ const protocol = this.config.useHttps ? "wss" : "ws";
2813
+ return `${protocol}://${this.config.host}:${this.config.port}`;
2814
+ }
2815
+ /**
2816
+ * Read-only access to the configured host/port for WS-clients.
2817
+ */
2818
+ _getConfig() {
2819
+ return this.config;
2820
+ }
2821
+ /**
2822
+ * Exchange the current credentials (JWT or API key) for a short-lived
2823
+ * WebSocket ticket. Use the returned token as the `?token=` query
2824
+ * param when opening any /ws endpoint.
2825
+ */
2826
+ async createWsTicket() {
2827
+ const { data } = await this.httpClient.post("/ws/ticket", {});
2828
+ const token = data.token ?? data.ticket;
2829
+ const expiresAt = typeof data.expiresAt === "number" ? data.expiresAt : data.expires_at ? Date.parse(data.expires_at) : Date.now() + 6e4;
2830
+ return { token, expiresAt };
2831
+ }
2832
+ /**
2833
+ * Revoke a previously-issued ticket (best-effort).
2834
+ */
2835
+ async revokeWsTicket(token) {
2836
+ await this.httpClient.post("/ws/ticket/revoke", { token });
1976
2837
  }
1977
2838
  handleError(error) {
1978
2839
  if (!error.response) {
@@ -2161,11 +3022,11 @@ var SynapCores = class {
2161
3022
  async embed(text, options = {}) {
2162
3023
  const isBatch = Array.isArray(text);
2163
3024
  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];
3025
+ const path = isBatch ? "/ai/embeddings/batch" : "/ai/embeddings";
3026
+ const body = isBatch ? { texts, model: options.model } : { text: texts[0], model: options.model };
3027
+ const { data } = await this.httpClient.post(path, body);
3028
+ if (isBatch) return data.embeddings ?? data;
3029
+ return data.embedding ?? data.embeddings?.[0] ?? data;
2169
3030
  }
2170
3031
  // Internal method for HTTP client access
2171
3032
  _getHttpClient() {
@@ -2292,8 +3153,16 @@ var SynapCores = class {
2292
3153
  * @returns Promise resolving to table information
2293
3154
  */
2294
3155
  async describeTable(tableName) {
2295
- const { data } = await this.httpClient.get(`/table/${tableName}/info`);
2296
- return data;
3156
+ const [tableRes, colsRes, idxRes] = await Promise.all([
3157
+ this.httpClient.get(`/schema/tables/${tableName}`),
3158
+ this.httpClient.get(`/schema/tables/${tableName}/columns`),
3159
+ this.httpClient.get(`/schema/tables/${tableName}/indexes`)
3160
+ ]);
3161
+ return {
3162
+ ...tableRes.data,
3163
+ columns: colsRes.data?.columns ?? colsRes.data ?? [],
3164
+ indexes: idxRes.data?.indexes ?? idxRes.data ?? []
3165
+ };
2297
3166
  }
2298
3167
  /**
2299
3168
  * Lists all tables in the current database
@@ -2426,19 +3295,26 @@ var SynapCores = class {
2426
3295
  * @returns Promise resolving to batch operation result
2427
3296
  */
2428
3297
  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
3298
+ const cols = options.columns ?? [];
3299
+ const queries = options.rows.map((row) => {
3300
+ const values = Array.isArray(row) ? row : cols.map((c) => row[c]);
3301
+ return {
3302
+ sql: `INSERT INTO ${options.tableName} (${cols.join(", ")}) VALUES (${values.map((_, i) => "$" + (i + 1)).join(", ")})`,
3303
+ parameters: values
3304
+ };
3305
+ });
3306
+ const { data } = await this.httpClient.post("/query/execute/batch", {
3307
+ queries,
3308
+ transactional: false
3309
+ });
3310
+ const results = data.results ?? [];
3311
+ const successful = results.filter((r) => !r.error).length;
3312
+ return {
3313
+ totalProcessed: results.length,
3314
+ successful,
3315
+ failed: results.length - successful,
3316
+ errors: results.filter((r) => r.error).map((r) => r.error),
3317
+ tookMs: data.total_execution_time_ms ?? 0
2442
3318
  };
2443
3319
  }
2444
3320
  /**
@@ -2447,17 +3323,27 @@ var SynapCores = class {
2447
3323
  * @returns Promise resolving to batch operation result
2448
3324
  */
2449
3325
  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
3326
+ const queries = options.updates.map((u) => {
3327
+ const setClause = Object.keys(u.set ?? {}).map((k, i) => `${k} = $${i + 1}`).join(", ");
3328
+ const setVals = Object.values(u.set ?? {});
3329
+ const whereStr = u.where ?? "1=1";
3330
+ return {
3331
+ sql: `UPDATE ${options.tableName} SET ${setClause} WHERE ${whereStr}`,
3332
+ parameters: setVals
3333
+ };
2454
3334
  });
3335
+ const { data } = await this.httpClient.post("/query/execute/batch", {
3336
+ queries,
3337
+ transactional: false
3338
+ });
3339
+ const results = data.results ?? [];
3340
+ const successful = results.filter((r) => !r.error).length;
2455
3341
  return {
2456
- totalProcessed: data.total_processed,
2457
- successful: data.successful,
2458
- failed: data.failed,
2459
- errors: data.errors,
2460
- tookMs: data.took_ms
3342
+ totalProcessed: results.length,
3343
+ successful,
3344
+ failed: results.length - successful,
3345
+ errors: results.filter((r) => r.error).map((r) => r.error),
3346
+ tookMs: data.total_execution_time_ms ?? 0
2461
3347
  };
2462
3348
  }
2463
3349
  /**
@@ -2466,17 +3352,22 @@ var SynapCores = class {
2466
3352
  * @returns Promise resolving to batch operation result
2467
3353
  */
2468
3354
  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
3355
+ const queries = (options.whereConditions ?? []).map((cond) => ({
3356
+ sql: `DELETE FROM ${options.tableName} WHERE ${typeof cond === "string" ? cond : JSON.stringify(cond)}`,
3357
+ parameters: []
3358
+ }));
3359
+ const { data } = await this.httpClient.post("/query/execute/batch", {
3360
+ queries,
3361
+ transactional: false
2473
3362
  });
3363
+ const results = data.results ?? [];
3364
+ const successful = results.filter((r) => !r.error).length;
2474
3365
  return {
2475
- totalProcessed: data.total_processed,
2476
- successful: data.successful,
2477
- failed: data.failed,
2478
- errors: data.errors,
2479
- tookMs: data.took_ms
3366
+ totalProcessed: results.length,
3367
+ successful,
3368
+ failed: results.length - successful,
3369
+ errors: results.filter((r) => r.error).map((r) => r.error),
3370
+ tookMs: data.total_execution_time_ms ?? 0
2480
3371
  };
2481
3372
  }
2482
3373
  // =================================================================
@@ -2489,15 +3380,15 @@ var SynapCores = class {
2489
3380
  * @returns Promise resolving to prepared statement
2490
3381
  */
2491
3382
  async prepareStatement(sql, options = {}) {
2492
- const { data } = await this.httpClient.post("/prepare", {
3383
+ const { data } = await this.httpClient.post("/query/prepare", {
2493
3384
  sql,
2494
3385
  name: options.name,
2495
3386
  parameter_types: options.parameterTypes
2496
3387
  });
2497
3388
  const prepared = {
2498
- id: data.statement_id,
3389
+ id: data.statement_id ?? data.id,
2499
3390
  sql,
2500
- parameterCount: data.parameter_count
3391
+ parameterCount: data.parameter_count ?? data.parameters_count ?? 0
2501
3392
  };
2502
3393
  if (options.name) {
2503
3394
  this.preparedStatements.set(options.name, prepared);
@@ -2514,7 +3405,7 @@ var SynapCores = class {
2514
3405
  if (this.preparedStatements.has(statementId)) {
2515
3406
  statementId = this.preparedStatements.get(statementId).id;
2516
3407
  }
2517
- const { data } = await this.httpClient.post("/execute-prepared", {
3408
+ const { data } = await this.httpClient.post("/query/exec", {
2518
3409
  statement_id: statementId,
2519
3410
  parameters: params
2520
3411
  });
@@ -2534,10 +3425,10 @@ var SynapCores = class {
2534
3425
  async deallocatePrepared(statementId) {
2535
3426
  if (this.preparedStatements.has(statementId)) {
2536
3427
  const prepared = this.preparedStatements.get(statementId);
2537
- await this.httpClient.delete(`/prepare/${prepared.id}`);
3428
+ await this.httpClient.post("/query/close", { statement_id: prepared.id });
2538
3429
  this.preparedStatements.delete(statementId);
2539
3430
  } else {
2540
- await this.httpClient.delete(`/prepare/${statementId}`);
3431
+ await this.httpClient.post("/query/close", { statement_id: statementId });
2541
3432
  }
2542
3433
  }
2543
3434
  /**
@@ -2628,231 +3519,198 @@ var SynapCores = class {
2628
3519
  if (vector1.length !== vector2.length) {
2629
3520
  throw new VectorError("Vector dimensions must match", "DIMENSION_MISMATCH");
2630
3521
  }
2631
- const { data } = await this.httpClient.post("/vectors/add", {
2632
- vector1,
2633
- vector2
3522
+ const { data } = await this.httpClient.post("/vector-algebra/operation", {
3523
+ op: "add",
3524
+ a: vector1,
3525
+ b: vector2
2634
3526
  });
3527
+ const result = data.result ?? data.vector ?? [];
2635
3528
  return {
2636
- result: { values: data.result, dimensions: data.result.length },
3529
+ result: { values: result, dimensions: result.length },
2637
3530
  operation: "addition",
2638
3531
  tookMs: data.took_ms
2639
3532
  };
2640
3533
  }
2641
3534
  /**
2642
3535
  * Performs vector subtraction
2643
- * @param vector1 - First vector (minuend)
2644
- * @param vector2 - Second vector (subtrahend)
2645
- * @returns Promise resolving to vector subtraction result
2646
3536
  */
2647
3537
  async vectorSubtract(vector1, vector2) {
2648
3538
  if (vector1.length !== vector2.length) {
2649
3539
  throw new VectorError("Vector dimensions must match", "DIMENSION_MISMATCH");
2650
3540
  }
2651
- const { data } = await this.httpClient.post("/vectors/subtract", {
2652
- vector1,
2653
- vector2
3541
+ const { data } = await this.httpClient.post("/vector-algebra/operation", {
3542
+ op: "subtract",
3543
+ a: vector1,
3544
+ b: vector2
2654
3545
  });
3546
+ const result = data.result ?? data.vector ?? [];
2655
3547
  return {
2656
- result: { values: data.result, dimensions: data.result.length },
3548
+ result: { values: result, dimensions: result.length },
2657
3549
  operation: "subtraction",
2658
3550
  tookMs: data.took_ms
2659
3551
  };
2660
3552
  }
2661
3553
  /**
2662
3554
  * 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
3555
  */
2667
3556
  async vectorScalarMultiply(vector, scalar) {
2668
- const { data } = await this.httpClient.post("/vectors/scalar-multiply", {
2669
- vector,
3557
+ const { data } = await this.httpClient.post("/vector-algebra/operation", {
3558
+ op: "scalar_multiply",
3559
+ a: vector,
2670
3560
  scalar
2671
3561
  });
3562
+ const result = data.result ?? data.vector ?? [];
2672
3563
  return {
2673
- result: { values: data.result, dimensions: data.result.length },
3564
+ result: { values: result, dimensions: result.length },
2674
3565
  operation: "scalar_multiplication",
2675
3566
  tookMs: data.took_ms
2676
3567
  };
2677
3568
  }
2678
3569
  /**
2679
3570
  * 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
3571
  */
2684
3572
  async vectorDotProduct(vector1, vector2) {
2685
3573
  if (vector1.length !== vector2.length) {
2686
3574
  throw new VectorError("Vector dimensions must match", "DIMENSION_MISMATCH");
2687
3575
  }
2688
- const { data } = await this.httpClient.post("/vectors/dot-product", {
2689
- vector1,
2690
- vector2
3576
+ const { data } = await this.httpClient.post("/vector-algebra/operation", {
3577
+ op: "dot_product",
3578
+ a: vector1,
3579
+ b: vector2
2691
3580
  });
2692
- return {
2693
- dotProduct: data.dot_product,
2694
- tookMs: data.took_ms
2695
- };
3581
+ return { dotProduct: data.scalar ?? data.dot_product ?? 0, tookMs: data.took_ms };
2696
3582
  }
2697
3583
  /**
2698
3584
  * 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
3585
  */
2703
3586
  async cosineSimilarity(vector1, vector2) {
2704
3587
  if (vector1.length !== vector2.length) {
2705
3588
  throw new VectorError("Vector dimensions must match", "DIMENSION_MISMATCH");
2706
3589
  }
2707
- const { data } = await this.httpClient.post("/vectors/cosine-similarity", {
2708
- vector1,
2709
- vector2
3590
+ const { data } = await this.httpClient.post("/vector-algebra/operation", {
3591
+ op: "cosine_similarity",
3592
+ a: vector1,
3593
+ b: vector2
2710
3594
  });
2711
- return {
2712
- similarity: data.similarity,
2713
- function: "cosine",
2714
- tookMs: data.took_ms
2715
- };
3595
+ return { similarity: data.scalar ?? data.similarity ?? 0, function: "cosine", tookMs: data.took_ms };
2716
3596
  }
2717
3597
  /**
2718
3598
  * 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
3599
  */
2723
3600
  async l2Distance(vector1, vector2) {
2724
3601
  if (vector1.length !== vector2.length) {
2725
3602
  throw new VectorError("Vector dimensions must match", "DIMENSION_MISMATCH");
2726
3603
  }
2727
- const { data } = await this.httpClient.post("/vectors/l2-distance", {
2728
- vector1,
2729
- vector2
3604
+ const { data } = await this.httpClient.post("/vector-algebra/operation", {
3605
+ op: "l2_distance",
3606
+ a: vector1,
3607
+ b: vector2
2730
3608
  });
2731
- return {
2732
- distance: data.distance,
2733
- similarity: data.distance,
2734
- // Include similarity for compatibility
2735
- function: "l2",
2736
- tookMs: data.took_ms
2737
- };
3609
+ const distance = data.scalar ?? data.distance ?? 0;
3610
+ return { distance, similarity: distance, function: "l2", tookMs: data.took_ms };
2738
3611
  }
2739
3612
  /**
2740
3613
  * 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
3614
  */
2745
3615
  async innerProduct(vector1, vector2) {
2746
3616
  if (vector1.length !== vector2.length) {
2747
3617
  throw new VectorError("Vector dimensions must match", "DIMENSION_MISMATCH");
2748
3618
  }
2749
- const { data } = await this.httpClient.post("/vectors/inner-product", {
2750
- vector1,
2751
- vector2
3619
+ const { data } = await this.httpClient.post("/vector-algebra/operation", {
3620
+ op: "inner_product",
3621
+ a: vector1,
3622
+ b: vector2
2752
3623
  });
2753
- return {
2754
- similarity: data.inner_product,
2755
- function: "inner_product",
2756
- tookMs: data.took_ms
2757
- };
3624
+ return { similarity: data.scalar ?? data.inner_product ?? 0, function: "inner_product", tookMs: data.took_ms };
2758
3625
  }
2759
3626
  /**
2760
- * Performs K-nearest neighbors vector search
2761
- * @param options - KNN search options
2762
- * @returns Promise resolving to KNN search results
3627
+ * Performs K-nearest neighbors vector search.
3628
+ * v0.2.0: routes through /vectors/collections/:c/search with mode discriminator.
2763
3629
  */
2764
3630
  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,
3631
+ const collection = options.collectionName ?? options.tableName;
3632
+ const { data } = await this.httpClient.post(`/vectors/collections/${collection}/search`, {
3633
+ mode: "knn",
3634
+ vector: options.queryVector,
3635
+ limit: options.k,
2771
3636
  filter: options.filter
2772
3637
  });
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
3638
+ return (data.matches ?? data.results ?? []).map((r) => ({
3639
+ id: r.id,
3640
+ vector: r.vector,
3641
+ similarity: r.similarity,
3642
+ distance: r.distance,
3643
+ metadata: r.metadata
2779
3644
  }));
2780
3645
  }
2781
3646
  /**
2782
- * Performs range-based vector similarity search
2783
- * @param options - Range search options
2784
- * @returns Promise resolving to range search results
3647
+ * Performs range-based vector similarity search.
2785
3648
  */
2786
3649
  async rangeSearch(options) {
2787
- const { data } = await this.httpClient.post("/vectors/range-search", {
2788
- query_vector: options.queryVector,
3650
+ const collection = options.collectionName ?? options.tableName;
3651
+ const { data } = await this.httpClient.post(`/vectors/collections/${collection}/search`, {
3652
+ mode: "range",
3653
+ vector: options.queryVector,
2789
3654
  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
3655
+ max_results: options.maxResults,
3656
+ filter: options.filter
3657
+ });
3658
+ return (data.matches ?? data.results ?? []).map((r) => ({
3659
+ id: r.id,
3660
+ vector: r.vector,
3661
+ similarity: r.similarity,
3662
+ distance: r.distance,
3663
+ metadata: r.metadata
2802
3664
  }));
2803
3665
  }
2804
3666
  /**
2805
- * Performs hybrid search combining vector similarity and SQL filtering
2806
- * @param options - Hybrid search options
2807
- * @returns Promise resolving to hybrid search results
3667
+ * Performs hybrid search combining vector similarity and SQL filtering.
2808
3668
  */
2809
3669
  async hybridSearch(options) {
2810
- const { data } = await this.httpClient.post("/vectors/hybrid-search", {
3670
+ const collection = options.collectionName ?? options.tableName;
3671
+ const { data } = await this.httpClient.post(`/vectors/collections/${collection}/search`, {
3672
+ mode: "hybrid",
2811
3673
  vector: options.vector,
2812
3674
  text_query: options.textQuery,
2813
3675
  sql_filter: options.sqlFilter,
2814
- k: options.k,
3676
+ limit: options.k,
2815
3677
  threshold: options.threshold,
2816
3678
  metric: options.metric,
2817
3679
  filter: options.filter,
2818
3680
  weights: options.weights
2819
3681
  });
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
3682
+ return (data.matches ?? data.results ?? []).map((r) => ({
3683
+ id: r.id,
3684
+ vector: r.vector,
3685
+ similarity: r.similarity,
3686
+ distance: r.distance,
3687
+ metadata: r.metadata
2826
3688
  }));
2827
3689
  }
2828
3690
  /**
2829
3691
  * Normalizes a vector to unit length
2830
- * @param vector - Input vector to normalize
2831
- * @returns Promise resolving to normalized vector
2832
3692
  */
2833
3693
  async normalizeVector(vector) {
2834
- const { data } = await this.httpClient.post("/vectors/normalize", {
2835
- vector
3694
+ const { data } = await this.httpClient.post("/vector-algebra/operation", {
3695
+ op: "normalize",
3696
+ a: vector
2836
3697
  });
3698
+ const result = data.result ?? data.vector ?? [];
2837
3699
  return {
2838
- result: { values: data.result, dimensions: data.result.length },
3700
+ result: { values: result, dimensions: result.length },
2839
3701
  operation: "normalization",
2840
3702
  tookMs: data.took_ms
2841
3703
  };
2842
3704
  }
2843
3705
  /**
2844
3706
  * Calculates the magnitude (length) of a vector
2845
- * @param vector - Input vector
2846
- * @returns Promise resolving to vector magnitude
2847
3707
  */
2848
3708
  async vectorMagnitude(vector) {
2849
- const { data } = await this.httpClient.post("/vectors/magnitude", {
2850
- vector
3709
+ const { data } = await this.httpClient.post("/vector-algebra/operation", {
3710
+ op: "magnitude",
3711
+ a: vector
2851
3712
  });
2852
- return {
2853
- magnitude: data.magnitude,
2854
- tookMs: data.took_ms
2855
- };
3713
+ return { magnitude: data.scalar ?? data.magnitude ?? 0, tookMs: data.took_ms };
2856
3714
  }
2857
3715
  // =================================================================
2858
3716
  // AUTHENTICATION & USER MANAGEMENT
@@ -2884,16 +3742,26 @@ var SynapCores = class {
2884
3742
  return data;
2885
3743
  }
2886
3744
  /**
2887
- * Refresh JWT token
3745
+ * Refresh JWT token.
3746
+ *
3747
+ * v0.2.0: the gateway does not currently expose a refresh endpoint —
3748
+ * this method now re-runs login() with the same credentials. Pass
3749
+ * the credentials in the call site (or supply them at SDK construction
3750
+ * time and we'll re-use the cached pair).
2888
3751
  */
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"];
3752
+ async refreshToken(credentials) {
3753
+ if (credentials?.username && credentials?.password) {
3754
+ const login = await this.login({ username: credentials.username, password: credentials.password });
3755
+ return {
3756
+ access_token: login.access_token,
3757
+ refresh_token: "",
3758
+ token_type: "Bearer",
3759
+ expires_in: login.expires_in
3760
+ };
2895
3761
  }
2896
- return data;
3762
+ throw new ValidationError(
3763
+ "refreshToken now requires credentials \u2014 the gateway has no /auth/refresh endpoint in v1.5.0-ce. Pass {username, password} or call login() again."
3764
+ );
2897
3765
  }
2898
3766
  /**
2899
3767
  * Set JWT token manually (useful after login)
@@ -3024,17 +3892,23 @@ var SynapCores = class {
3024
3892
 
3025
3893
  // src/index.ts
3026
3894
  import { z } from "zod";
3027
- var VERSION = "0.1.0";
3895
+ var VERSION = "0.2.0";
3028
3896
  export {
3029
3897
  AuthenticationError,
3030
3898
  AutoMLClient,
3031
3899
  AutoMLModel,
3032
3900
  BackupClient,
3033
3901
  BatchOperationError,
3902
+ ChatClient,
3034
3903
  Collection,
3035
3904
  ConnectionError,
3905
+ FilesystemCollectionsClient,
3906
+ GraphClient,
3036
3907
  ImportExportClient,
3037
3908
  IntegrationClient,
3909
+ McpClient,
3910
+ MultimodalClient,
3911
+ NL2SqlClient,
3038
3912
  NLPClient,
3039
3913
  NotFoundError,
3040
3914
  RateLimitError,
@@ -3045,8 +3919,11 @@ export {
3045
3919
  Subscription,
3046
3920
  SynapCores,
3047
3921
  SynapCoresError,
3922
+ SystemClient,
3048
3923
  TimeoutError,
3049
3924
  TransactionError,
3925
+ TransactionsClient,
3926
+ Tx,
3050
3927
  VERSION,
3051
3928
  ValidationError,
3052
3929
  VectorError,