@synapcores/sdk 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +94 -1
- package/dist/index.d.mts +1019 -188
- package/dist/index.d.ts +1019 -188
- package/dist/index.js +1774 -893
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1765 -893
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
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
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
}
|
|
39
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
`/
|
|
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("/
|
|
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
|
-
`/
|
|
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("/
|
|
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("/
|
|
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
|
-
`/
|
|
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
|
-
`/
|
|
480
|
+
`/automl/jobs${qs ? `?${qs}` : ""}`
|
|
510
481
|
);
|
|
511
|
-
return (data.jobs
|
|
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(`/
|
|
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
|
-
`/
|
|
499
|
+
`/automl/jobs/${jobId}`
|
|
540
500
|
);
|
|
541
|
-
|
|
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
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
const
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
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
|
|
804
|
-
return data.
|
|
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
|
|
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
|
|
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
|
|
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:
|
|
845
|
-
type:
|
|
846
|
-
column_count:
|
|
847
|
-
row_count:
|
|
848
|
-
size_bytes:
|
|
849
|
-
created_at:
|
|
850
|
-
updated_at:
|
|
851
|
-
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:
|
|
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:
|
|
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:
|
|
876
|
-
relationships: (
|
|
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
|
|
891
|
-
|
|
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
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
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
|
-
*
|
|
1110
|
+
* Preview rows from a table without writing SQL.
|
|
1111
|
+
*
|
|
1112
|
+
* GET /schema/tables/:t/data?limit=&offset=
|
|
916
1113
|
*/
|
|
917
|
-
async
|
|
918
|
-
const
|
|
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
|
-
|
|
921
|
-
|
|
922
|
-
|
|
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
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
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
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
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
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
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
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
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
|
|
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)
|
|
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",
|
|
1268
|
+
formData.append("file", options.data, { filename: `data.${fmt}` });
|
|
1004
1269
|
} else {
|
|
1005
|
-
formData.append("
|
|
1270
|
+
formData.append("file", Buffer.from(String(options.data)), {
|
|
1271
|
+
filename: `data.${fmt}`
|
|
1272
|
+
});
|
|
1006
1273
|
}
|
|
1007
|
-
const
|
|
1008
|
-
|
|
1009
|
-
|
|
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
|
|
1014
|
-
success: data.success,
|
|
1015
|
-
rows_processed: data.rows_processed
|
|
1016
|
-
rows_imported: data.rows_imported
|
|
1017
|
-
rows_failed: data.rows_failed
|
|
1018
|
-
duration_ms: data.duration_ms
|
|
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
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
1384
|
+
* Get a specific integration by type-slug.
|
|
1259
1385
|
*/
|
|
1260
|
-
async get(
|
|
1261
|
-
const { data } = await this.synapCores._getHttpClient().get(
|
|
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(
|
|
1395
|
+
async update(type, updates) {
|
|
1268
1396
|
const { data } = await this.synapCores._getHttpClient().put(
|
|
1269
|
-
`/integrations/${
|
|
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
|
|
1302
|
-
|
|
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
|
|
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
|
-
*
|
|
1428
|
+
* List supported integration types and their config schemas.
|
|
1342
1429
|
*/
|
|
1343
|
-
async
|
|
1344
|
-
const
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
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
|
|
1440
|
+
* Get the integrations audit trail.
|
|
1363
1441
|
*/
|
|
1364
|
-
async
|
|
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
|
|
1448
|
+
`/integrations/audit${qs ? `?${qs}` : ""}`
|
|
1367
1449
|
);
|
|
1368
|
-
return {
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
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
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1465
|
-
|
|
1466
|
-
async
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
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
|
-
|
|
1629
|
-
|
|
1630
|
-
async cancelBackup(backupId) {
|
|
1631
|
-
await this.synapCores._getHttpClient().post(`/backups/${backupId}/cancel`);
|
|
1632
|
-
}
|
|
1633
|
-
/**
|
|
1634
|
-
* Cancel a restore in progress
|
|
1635
|
-
*/
|
|
1636
|
-
async cancelRestore(restoreId) {
|
|
1637
|
-
await this.synapCores._getHttpClient().post(`/backups/restore/${restoreId}/cancel`);
|
|
1638
|
-
}
|
|
1642
|
+
// cancelBackup() / cancelRestore() removed — gateway v1.5.0-ce has no
|
|
1643
|
+
// /backups/:id/cancel or /backups/restore/:id/cancel routes. Use
|
|
1644
|
+
// delete() to clean up an aborted backup record.
|
|
1639
1645
|
/**
|
|
1640
1646
|
* Download a backup file
|
|
1641
1647
|
*/
|
|
@@ -1770,155 +1776,967 @@ var BackupClient = class {
|
|
|
1770
1776
|
};
|
|
1771
1777
|
}
|
|
1772
1778
|
/**
|
|
1773
|
-
* Deactivate a schedule
|
|
1779
|
+
* Deactivate a schedule
|
|
1780
|
+
*/
|
|
1781
|
+
async deactivateSchedule(scheduleId) {
|
|
1782
|
+
const { data } = await this.synapCores._getHttpClient().post(
|
|
1783
|
+
`/backups/schedules/${scheduleId}/deactivate`
|
|
1784
|
+
);
|
|
1785
|
+
return {
|
|
1786
|
+
id: data.id,
|
|
1787
|
+
name: data.name,
|
|
1788
|
+
cron: data.cron,
|
|
1789
|
+
backup_options: data.backup_options,
|
|
1790
|
+
active: data.active,
|
|
1791
|
+
last_run_at: data.last_run_at ? new Date(data.last_run_at) : void 0,
|
|
1792
|
+
next_run_at: data.next_run_at ? new Date(data.next_run_at) : void 0,
|
|
1793
|
+
created_at: new Date(data.created_at),
|
|
1794
|
+
tags: data.tags || []
|
|
1795
|
+
};
|
|
1796
|
+
}
|
|
1797
|
+
// getMetrics() removed — gateway v1.5.0-ce has no /backups/metrics route.
|
|
1798
|
+
// Aggregate metrics can be derived client-side from list().
|
|
1799
|
+
/**
|
|
1800
|
+
* Map raw backup data to Backup type
|
|
1801
|
+
*/
|
|
1802
|
+
mapBackup(data) {
|
|
1803
|
+
return {
|
|
1804
|
+
id: data.id,
|
|
1805
|
+
name: data.name,
|
|
1806
|
+
description: data.description,
|
|
1807
|
+
type: data.type,
|
|
1808
|
+
status: data.status,
|
|
1809
|
+
size_bytes: data.size_bytes,
|
|
1810
|
+
compressed_size_bytes: data.compressed_size_bytes,
|
|
1811
|
+
table_count: data.table_count,
|
|
1812
|
+
created_at: new Date(data.created_at),
|
|
1813
|
+
completed_at: data.completed_at ? new Date(data.completed_at) : void 0,
|
|
1814
|
+
duration_ms: data.duration_ms || data.took_ms,
|
|
1815
|
+
storage: data.storage,
|
|
1816
|
+
storage_path: data.storage_path,
|
|
1817
|
+
encrypted: data.encrypted || false,
|
|
1818
|
+
tags: data.tags || [],
|
|
1819
|
+
parent_backup_id: data.parent_backup_id,
|
|
1820
|
+
error: data.error
|
|
1821
|
+
};
|
|
1822
|
+
}
|
|
1823
|
+
};
|
|
1824
|
+
|
|
1825
|
+
// src/graph.ts
|
|
1826
|
+
var GraphNodeApi = class {
|
|
1827
|
+
constructor(synapCores) {
|
|
1828
|
+
this.synapCores = synapCores;
|
|
1829
|
+
}
|
|
1830
|
+
async create(label, props = {}) {
|
|
1831
|
+
const { data } = await this.synapCores._getHttpClient().post("/graph/nodes", {
|
|
1832
|
+
label,
|
|
1833
|
+
properties: props
|
|
1834
|
+
});
|
|
1835
|
+
return this.normalize(data);
|
|
1836
|
+
}
|
|
1837
|
+
async get(id) {
|
|
1838
|
+
const { data } = await this.synapCores._getHttpClient().get(`/graph/nodes/${id}`);
|
|
1839
|
+
return this.normalize(data);
|
|
1840
|
+
}
|
|
1841
|
+
async update(id, patch) {
|
|
1842
|
+
const { data } = await this.synapCores._getHttpClient().patch(
|
|
1843
|
+
`/graph/nodes/${id}`,
|
|
1844
|
+
{ properties: patch }
|
|
1845
|
+
);
|
|
1846
|
+
return this.normalize(data);
|
|
1847
|
+
}
|
|
1848
|
+
async delete(id) {
|
|
1849
|
+
await this.synapCores._getHttpClient().delete(`/graph/nodes/${id}`);
|
|
1850
|
+
}
|
|
1851
|
+
async neighbors(id, opts = {}) {
|
|
1852
|
+
const params = new URLSearchParams();
|
|
1853
|
+
if (opts.direction) params.append("direction", opts.direction);
|
|
1854
|
+
if (opts.limit !== void 0) params.append("limit", String(opts.limit));
|
|
1855
|
+
if (opts.type) params.append("type", opts.type);
|
|
1856
|
+
const qs = params.toString();
|
|
1857
|
+
const { data } = await this.synapCores._getHttpClient().get(
|
|
1858
|
+
`/graph/nodes/${id}/neighbors${qs ? `?${qs}` : ""}`
|
|
1859
|
+
);
|
|
1860
|
+
return {
|
|
1861
|
+
nodes: (data.nodes ?? []).map((n) => this.normalize(n)),
|
|
1862
|
+
edges: (data.edges ?? []).map((e) => this.normalizeEdge(e))
|
|
1863
|
+
};
|
|
1864
|
+
}
|
|
1865
|
+
normalize(data) {
|
|
1866
|
+
return {
|
|
1867
|
+
id: String(data.id ?? data.node_id ?? ""),
|
|
1868
|
+
label: data.label,
|
|
1869
|
+
labels: data.labels,
|
|
1870
|
+
properties: data.properties ?? data.props ?? {}
|
|
1871
|
+
};
|
|
1872
|
+
}
|
|
1873
|
+
normalizeEdge(data) {
|
|
1874
|
+
return {
|
|
1875
|
+
id: data.id !== void 0 ? String(data.id) : void 0,
|
|
1876
|
+
from: String(data.from ?? data.source ?? ""),
|
|
1877
|
+
to: String(data.to ?? data.target ?? ""),
|
|
1878
|
+
type: data.type ?? data.label ?? "",
|
|
1879
|
+
properties: data.properties ?? data.props ?? {}
|
|
1880
|
+
};
|
|
1881
|
+
}
|
|
1882
|
+
};
|
|
1883
|
+
var GraphEdgeApi = class {
|
|
1884
|
+
constructor(synapCores) {
|
|
1885
|
+
this.synapCores = synapCores;
|
|
1886
|
+
}
|
|
1887
|
+
async create(from, to, type, props = {}) {
|
|
1888
|
+
const { data } = await this.synapCores._getHttpClient().post("/graph/edges", {
|
|
1889
|
+
from,
|
|
1890
|
+
to,
|
|
1891
|
+
type,
|
|
1892
|
+
properties: props
|
|
1893
|
+
});
|
|
1894
|
+
return {
|
|
1895
|
+
id: data.id !== void 0 ? String(data.id) : void 0,
|
|
1896
|
+
from: String(data.from ?? from),
|
|
1897
|
+
to: String(data.to ?? to),
|
|
1898
|
+
type: data.type ?? type,
|
|
1899
|
+
properties: data.properties ?? props
|
|
1900
|
+
};
|
|
1901
|
+
}
|
|
1902
|
+
};
|
|
1903
|
+
var GraphIndexesApi = class {
|
|
1904
|
+
constructor(synapCores) {
|
|
1905
|
+
this.synapCores = synapCores;
|
|
1906
|
+
}
|
|
1907
|
+
/**
|
|
1908
|
+
* Create a graph index (label/property index, fulltext, or vector
|
|
1909
|
+
* depending on the gateway's accepted DDL strings).
|
|
1910
|
+
*/
|
|
1911
|
+
async create(stmt) {
|
|
1912
|
+
const { data } = await this.synapCores._getHttpClient().post("/graph/indexes", {
|
|
1913
|
+
statement: stmt
|
|
1914
|
+
});
|
|
1915
|
+
return { name: data.name ?? data.index_name, raw: data };
|
|
1916
|
+
}
|
|
1917
|
+
};
|
|
1918
|
+
var GraphAlgorithmsApi = class {
|
|
1919
|
+
constructor(synapCores) {
|
|
1920
|
+
this.synapCores = synapCores;
|
|
1921
|
+
}
|
|
1922
|
+
async run(name, opts = {}) {
|
|
1923
|
+
const { data } = await this.synapCores._getHttpClient().post("/graph/algorithms", {
|
|
1924
|
+
algorithm: name,
|
|
1925
|
+
...opts
|
|
1926
|
+
});
|
|
1927
|
+
return {
|
|
1928
|
+
algorithm: name,
|
|
1929
|
+
results: data.results ?? data.result ?? data,
|
|
1930
|
+
stats: data.stats,
|
|
1931
|
+
execution_time_ms: data.execution_time_ms ?? data.took_ms
|
|
1932
|
+
};
|
|
1933
|
+
}
|
|
1934
|
+
};
|
|
1935
|
+
var GraphsApi = class {
|
|
1936
|
+
constructor(synapCores) {
|
|
1937
|
+
this.synapCores = synapCores;
|
|
1938
|
+
}
|
|
1939
|
+
async list() {
|
|
1940
|
+
const { data } = await this.synapCores._getHttpClient().get("/graphs");
|
|
1941
|
+
return (data.graphs ?? data ?? []).map((g) => this.normalize(g));
|
|
1942
|
+
}
|
|
1943
|
+
async create(name, opts = {}) {
|
|
1944
|
+
const { data } = await this.synapCores._getHttpClient().post("/graphs", {
|
|
1945
|
+
name,
|
|
1946
|
+
description: opts.description
|
|
1947
|
+
});
|
|
1948
|
+
return this.normalize(data);
|
|
1949
|
+
}
|
|
1950
|
+
async get(name) {
|
|
1951
|
+
const { data } = await this.synapCores._getHttpClient().get(`/graphs/${name}`);
|
|
1952
|
+
return this.normalize(data);
|
|
1953
|
+
}
|
|
1954
|
+
async delete(name) {
|
|
1955
|
+
await this.synapCores._getHttpClient().delete(`/graphs/${name}`);
|
|
1956
|
+
}
|
|
1957
|
+
normalize(data) {
|
|
1958
|
+
return {
|
|
1959
|
+
name: data.name,
|
|
1960
|
+
node_count: data.node_count ?? data.nodes,
|
|
1961
|
+
edge_count: data.edge_count ?? data.edges,
|
|
1962
|
+
created_at: data.created_at ? new Date(data.created_at) : void 0,
|
|
1963
|
+
description: data.description
|
|
1964
|
+
};
|
|
1965
|
+
}
|
|
1966
|
+
};
|
|
1967
|
+
var GraphClient = class {
|
|
1968
|
+
constructor(synapCores) {
|
|
1969
|
+
this.synapCores = synapCores;
|
|
1970
|
+
this.nodes = new GraphNodeApi(synapCores);
|
|
1971
|
+
this.edges = new GraphEdgeApi(synapCores);
|
|
1972
|
+
this.indexes = new GraphIndexesApi(synapCores);
|
|
1973
|
+
this.algorithms = new GraphAlgorithmsApi(synapCores);
|
|
1974
|
+
this.graphs = new GraphsApi(synapCores);
|
|
1975
|
+
}
|
|
1976
|
+
/**
|
|
1977
|
+
* Run a Cypher / MATCH query.
|
|
1978
|
+
*/
|
|
1979
|
+
async cypher(query, params = {}, graph) {
|
|
1980
|
+
const { data } = await this.synapCores._getHttpClient().post("/graph/match", {
|
|
1981
|
+
query,
|
|
1982
|
+
params,
|
|
1983
|
+
graph
|
|
1984
|
+
});
|
|
1985
|
+
return this.normalizeCypher(data);
|
|
1986
|
+
}
|
|
1987
|
+
/**
|
|
1988
|
+
* Profile a Cypher / MATCH query (returns plan/profile metadata).
|
|
1989
|
+
*/
|
|
1990
|
+
async cypherProfile(query, params = {}, graph) {
|
|
1991
|
+
const { data } = await this.synapCores._getHttpClient().post("/graph/match/profile", {
|
|
1992
|
+
query,
|
|
1993
|
+
params,
|
|
1994
|
+
graph
|
|
1995
|
+
});
|
|
1996
|
+
return {
|
|
1997
|
+
...this.normalizeCypher(data),
|
|
1998
|
+
plan: data.plan,
|
|
1999
|
+
profile: data.profile ?? data.profile_data
|
|
2000
|
+
};
|
|
2001
|
+
}
|
|
2002
|
+
/**
|
|
2003
|
+
* Run LLM-based extraction over text into the given graph.
|
|
2004
|
+
*/
|
|
2005
|
+
async extract(req, graphName) {
|
|
2006
|
+
const body = typeof req === "string" ? { text: req, graph: graphName } : req;
|
|
2007
|
+
const { data } = await this.synapCores._getHttpClient().post("/graph/extract", body);
|
|
2008
|
+
return {
|
|
2009
|
+
nodes: (data.nodes ?? []).map((n) => ({
|
|
2010
|
+
id: String(n.id ?? ""),
|
|
2011
|
+
label: n.label,
|
|
2012
|
+
labels: n.labels,
|
|
2013
|
+
properties: n.properties ?? n.props ?? {}
|
|
2014
|
+
})),
|
|
2015
|
+
edges: (data.edges ?? []).map((e) => ({
|
|
2016
|
+
id: e.id !== void 0 ? String(e.id) : void 0,
|
|
2017
|
+
from: String(e.from ?? e.source ?? ""),
|
|
2018
|
+
to: String(e.to ?? e.target ?? ""),
|
|
2019
|
+
type: e.type ?? e.label ?? "",
|
|
2020
|
+
properties: e.properties ?? e.props ?? {}
|
|
2021
|
+
})),
|
|
2022
|
+
spans: data.spans
|
|
2023
|
+
};
|
|
2024
|
+
}
|
|
2025
|
+
normalizeCypher(data) {
|
|
2026
|
+
return {
|
|
2027
|
+
columns: data.columns ?? data.fields,
|
|
2028
|
+
rows: data.rows ?? data.values ?? [],
|
|
2029
|
+
records: data.records ?? data.results,
|
|
2030
|
+
stats: data.stats,
|
|
2031
|
+
execution_time_ms: data.execution_time_ms ?? data.took_ms
|
|
2032
|
+
};
|
|
2033
|
+
}
|
|
2034
|
+
};
|
|
2035
|
+
|
|
2036
|
+
// src/nl2sql.ts
|
|
2037
|
+
var NL2SqlClient = class {
|
|
2038
|
+
constructor(synapCores) {
|
|
2039
|
+
this.synapCores = synapCores;
|
|
2040
|
+
}
|
|
2041
|
+
/**
|
|
2042
|
+
* Ask a question in natural language. The gateway returns the
|
|
2043
|
+
* generated SQL and optionally the executed result set when
|
|
2044
|
+
* `execute=true`.
|
|
2045
|
+
*/
|
|
2046
|
+
async ask(question, opts = {}) {
|
|
2047
|
+
const { data } = await this.synapCores._getHttpClient().post("/nl2sql/query", {
|
|
2048
|
+
question,
|
|
2049
|
+
...opts
|
|
2050
|
+
});
|
|
2051
|
+
return {
|
|
2052
|
+
sql: data.sql ?? data.generated_sql ?? "",
|
|
2053
|
+
confidence: data.confidence,
|
|
2054
|
+
rows: data.rows ?? data.data,
|
|
2055
|
+
columns: data.columns,
|
|
2056
|
+
execution_time_ms: data.execution_time_ms ?? data.took_ms,
|
|
2057
|
+
trace: data.trace ?? data.plan,
|
|
2058
|
+
question
|
|
2059
|
+
};
|
|
2060
|
+
}
|
|
2061
|
+
/**
|
|
2062
|
+
* Push schema context the model should use for subsequent ask() calls.
|
|
2063
|
+
*/
|
|
2064
|
+
async updateSchemaContext(payload) {
|
|
2065
|
+
const { data } = await this.synapCores._getHttpClient().post(
|
|
2066
|
+
"/nl2sql/schema/context",
|
|
2067
|
+
payload
|
|
2068
|
+
);
|
|
2069
|
+
return { accepted: data.accepted ?? data.success ?? true, raw: data };
|
|
2070
|
+
}
|
|
2071
|
+
/**
|
|
2072
|
+
* Retrieve recent NL2SQL history for the current authenticated user.
|
|
2073
|
+
*/
|
|
2074
|
+
async history(opts = {}) {
|
|
2075
|
+
const params = new URLSearchParams();
|
|
2076
|
+
if (opts.limit) params.append("limit", String(opts.limit));
|
|
2077
|
+
if (opts.session_id) params.append("session_id", opts.session_id);
|
|
2078
|
+
const qs = params.toString();
|
|
2079
|
+
const { data } = await this.synapCores._getHttpClient().get(
|
|
2080
|
+
`/nl2sql/history${qs ? `?${qs}` : ""}`
|
|
2081
|
+
);
|
|
2082
|
+
return (data.history ?? data.entries ?? data ?? []).map((row) => ({
|
|
2083
|
+
id: String(row.id ?? row.entry_id ?? ""),
|
|
2084
|
+
question: row.question ?? row.prompt ?? "",
|
|
2085
|
+
sql: row.sql ?? row.generated_sql ?? "",
|
|
2086
|
+
created_at: new Date(row.created_at ?? row.timestamp ?? Date.now()),
|
|
2087
|
+
executed: row.executed,
|
|
2088
|
+
success: row.success
|
|
2089
|
+
}));
|
|
2090
|
+
}
|
|
2091
|
+
/**
|
|
2092
|
+
* Validate a SQL string against the current schema and policies.
|
|
2093
|
+
*/
|
|
2094
|
+
async validate(sql) {
|
|
2095
|
+
const { data } = await this.synapCores._getHttpClient().post("/nl2sql/validate", {
|
|
2096
|
+
sql
|
|
2097
|
+
});
|
|
2098
|
+
return {
|
|
2099
|
+
is_valid: data.is_valid ?? data.valid ?? false,
|
|
2100
|
+
errors: data.errors ?? [],
|
|
2101
|
+
warnings: data.warnings ?? [],
|
|
2102
|
+
rewritten_sql: data.rewritten_sql ?? data.sql
|
|
2103
|
+
};
|
|
2104
|
+
}
|
|
2105
|
+
};
|
|
2106
|
+
|
|
2107
|
+
// src/filesystem.ts
|
|
2108
|
+
import WebSocket2 from "ws";
|
|
2109
|
+
var FsCollectionsApi = class {
|
|
2110
|
+
constructor(synapCores) {
|
|
2111
|
+
this.synapCores = synapCores;
|
|
2112
|
+
}
|
|
2113
|
+
async create(opts) {
|
|
2114
|
+
const { data } = await this.synapCores._getHttpClient().post(
|
|
2115
|
+
"/filesystem-collections",
|
|
2116
|
+
opts
|
|
2117
|
+
);
|
|
2118
|
+
return this.normalize(data);
|
|
2119
|
+
}
|
|
2120
|
+
async list() {
|
|
2121
|
+
const { data } = await this.synapCores._getHttpClient().get("/filesystem-collections");
|
|
2122
|
+
return (data.collections ?? data ?? []).map((c) => this.normalize(c));
|
|
2123
|
+
}
|
|
2124
|
+
async get(id) {
|
|
2125
|
+
const { data } = await this.synapCores._getHttpClient().get(
|
|
2126
|
+
`/filesystem-collections/${id}`
|
|
2127
|
+
);
|
|
2128
|
+
return this.normalize(data);
|
|
2129
|
+
}
|
|
2130
|
+
async patch(id, p) {
|
|
2131
|
+
const { data } = await this.synapCores._getHttpClient().patch(
|
|
2132
|
+
`/filesystem-collections/${id}`,
|
|
2133
|
+
p
|
|
2134
|
+
);
|
|
2135
|
+
return this.normalize(data);
|
|
2136
|
+
}
|
|
2137
|
+
async delete(id) {
|
|
2138
|
+
await this.synapCores._getHttpClient().delete(`/filesystem-collections/${id}`);
|
|
2139
|
+
}
|
|
2140
|
+
async documents(id, opts = {}) {
|
|
2141
|
+
const params = new URLSearchParams();
|
|
2142
|
+
if (opts.page) params.append("page", String(opts.page));
|
|
2143
|
+
if (opts.page_size) params.append("page_size", String(opts.page_size));
|
|
2144
|
+
const qs = params.toString();
|
|
2145
|
+
const { data } = await this.synapCores._getHttpClient().get(
|
|
2146
|
+
`/filesystem-collections/${id}/documents${qs ? `?${qs}` : ""}`
|
|
2147
|
+
);
|
|
2148
|
+
return (data.documents ?? data ?? []).map((d) => ({
|
|
2149
|
+
id: String(d.id ?? d.document_id ?? ""),
|
|
2150
|
+
collection_id: d.collection_id !== void 0 ? String(d.collection_id) : id,
|
|
2151
|
+
filename: d.filename ?? d.name,
|
|
2152
|
+
path: d.path,
|
|
2153
|
+
status: d.status,
|
|
2154
|
+
size_bytes: d.size_bytes,
|
|
2155
|
+
created_at: d.created_at ? new Date(d.created_at) : void 0,
|
|
2156
|
+
updated_at: d.updated_at ? new Date(d.updated_at) : void 0
|
|
2157
|
+
}));
|
|
2158
|
+
}
|
|
2159
|
+
async reprocess(id, fileId) {
|
|
2160
|
+
const body = fileId ? { document_id: fileId } : {};
|
|
2161
|
+
const { data } = await this.synapCores._getHttpClient().post(
|
|
2162
|
+
`/filesystem-collections/${id}/reprocess`,
|
|
2163
|
+
body
|
|
2164
|
+
);
|
|
2165
|
+
return { accepted: data.accepted ?? data.success ?? true, raw: data };
|
|
2166
|
+
}
|
|
2167
|
+
/**
|
|
2168
|
+
* Stream progress events for an in-flight ingestion. Each tick maps to
|
|
2169
|
+
* a JSON payload broadcast by the gateway over the WS channel. The
|
|
2170
|
+
* iterator ends when the server closes the socket or the consumer
|
|
2171
|
+
* breaks out of the for-await loop.
|
|
2172
|
+
*/
|
|
2173
|
+
async *subscribeProgress(id, opts = {}) {
|
|
2174
|
+
const { token } = await this.synapCores.createWsTicket();
|
|
2175
|
+
const wsBase = this.synapCores._getWsBaseUrl();
|
|
2176
|
+
const url = `${wsBase}/ws/filesystem-collections/${id}/progress?token=${encodeURIComponent(token)}`;
|
|
2177
|
+
const ws = new WebSocket2(url);
|
|
2178
|
+
const queue = [];
|
|
2179
|
+
let resolver = null;
|
|
2180
|
+
const push = (p) => {
|
|
2181
|
+
if (resolver) {
|
|
2182
|
+
const r = resolver;
|
|
2183
|
+
resolver = null;
|
|
2184
|
+
r(p);
|
|
2185
|
+
} else {
|
|
2186
|
+
queue.push(p);
|
|
2187
|
+
}
|
|
2188
|
+
};
|
|
2189
|
+
ws.on("message", (raw) => {
|
|
2190
|
+
try {
|
|
2191
|
+
const obj = JSON.parse(raw.toString());
|
|
2192
|
+
push({
|
|
2193
|
+
kind: "value",
|
|
2194
|
+
value: {
|
|
2195
|
+
type: obj.type ?? obj.event ?? "progress",
|
|
2196
|
+
collection_id: obj.collection_id !== void 0 ? String(obj.collection_id) : id,
|
|
2197
|
+
document_id: obj.document_id !== void 0 ? String(obj.document_id) : void 0,
|
|
2198
|
+
filename: obj.filename ?? obj.path,
|
|
2199
|
+
status: obj.status,
|
|
2200
|
+
progress: obj.progress,
|
|
2201
|
+
message: obj.message,
|
|
2202
|
+
error: obj.error,
|
|
2203
|
+
timestamp: obj.timestamp ? new Date(obj.timestamp) : void 0,
|
|
2204
|
+
raw: obj
|
|
2205
|
+
}
|
|
2206
|
+
});
|
|
2207
|
+
} catch (e) {
|
|
2208
|
+
push({ kind: "error", error: e });
|
|
2209
|
+
}
|
|
2210
|
+
});
|
|
2211
|
+
ws.on("error", (err) => push({ kind: "error", error: err }));
|
|
2212
|
+
ws.on("close", () => push({ kind: "done" }));
|
|
2213
|
+
const onAbort = () => {
|
|
2214
|
+
try {
|
|
2215
|
+
ws.close();
|
|
2216
|
+
} catch {
|
|
2217
|
+
}
|
|
2218
|
+
};
|
|
2219
|
+
if (opts.signal) {
|
|
2220
|
+
if (opts.signal.aborted) onAbort();
|
|
2221
|
+
else opts.signal.addEventListener("abort", onAbort);
|
|
2222
|
+
}
|
|
2223
|
+
try {
|
|
2224
|
+
while (true) {
|
|
2225
|
+
const next = await new Promise((resolve) => {
|
|
2226
|
+
if (queue.length > 0) {
|
|
2227
|
+
resolve(queue.shift());
|
|
2228
|
+
} else {
|
|
2229
|
+
resolver = resolve;
|
|
2230
|
+
}
|
|
2231
|
+
});
|
|
2232
|
+
if (next.kind === "value") yield next.value;
|
|
2233
|
+
else if (next.kind === "error") throw next.error;
|
|
2234
|
+
else return;
|
|
2235
|
+
}
|
|
2236
|
+
} finally {
|
|
2237
|
+
try {
|
|
2238
|
+
ws.close();
|
|
2239
|
+
} catch {
|
|
2240
|
+
}
|
|
2241
|
+
if (opts.signal) opts.signal.removeEventListener("abort", onAbort);
|
|
2242
|
+
}
|
|
2243
|
+
}
|
|
2244
|
+
normalize(data) {
|
|
2245
|
+
return {
|
|
2246
|
+
id: String(data.id ?? data.collection_id ?? ""),
|
|
2247
|
+
name: data.name,
|
|
2248
|
+
description: data.description,
|
|
2249
|
+
path: data.path,
|
|
2250
|
+
status: data.status,
|
|
2251
|
+
document_count: data.document_count ?? data.documents,
|
|
2252
|
+
created_at: data.created_at ? new Date(data.created_at) : void 0,
|
|
2253
|
+
updated_at: data.updated_at ? new Date(data.updated_at) : void 0,
|
|
2254
|
+
config: data.config
|
|
2255
|
+
};
|
|
2256
|
+
}
|
|
2257
|
+
};
|
|
2258
|
+
var FilesystemCollectionsClient = class {
|
|
2259
|
+
constructor(synapCores) {
|
|
2260
|
+
this.collections = new FsCollectionsApi(synapCores);
|
|
2261
|
+
}
|
|
2262
|
+
};
|
|
2263
|
+
|
|
2264
|
+
// src/chat.ts
|
|
2265
|
+
var ChatSessionsApi = class {
|
|
2266
|
+
constructor(synapCores) {
|
|
2267
|
+
this.synapCores = synapCores;
|
|
2268
|
+
}
|
|
2269
|
+
async create(opts = {}) {
|
|
2270
|
+
const { data } = await this.synapCores._getHttpClient().post("/ai/sessions", opts);
|
|
2271
|
+
return this.normalize(data);
|
|
2272
|
+
}
|
|
2273
|
+
async list(opts = {}) {
|
|
2274
|
+
const params = new URLSearchParams();
|
|
2275
|
+
if (opts.limit) params.append("limit", String(opts.limit));
|
|
2276
|
+
if (opts.offset) params.append("offset", String(opts.offset));
|
|
2277
|
+
const qs = params.toString();
|
|
2278
|
+
const { data } = await this.synapCores._getHttpClient().get(
|
|
2279
|
+
`/ai/sessions${qs ? `?${qs}` : ""}`
|
|
2280
|
+
);
|
|
2281
|
+
return (data.sessions ?? data ?? []).map((s) => this.normalize(s));
|
|
2282
|
+
}
|
|
2283
|
+
async get(id) {
|
|
2284
|
+
const { data } = await this.synapCores._getHttpClient().get(`/ai/sessions/${id}`);
|
|
2285
|
+
return this.normalize(data);
|
|
2286
|
+
}
|
|
2287
|
+
async delete(id) {
|
|
2288
|
+
await this.synapCores._getHttpClient().delete(`/ai/sessions/${id}`);
|
|
2289
|
+
}
|
|
2290
|
+
async messages(id, opts = {}) {
|
|
2291
|
+
const params = new URLSearchParams();
|
|
2292
|
+
if (opts.limit) params.append("limit", String(opts.limit));
|
|
2293
|
+
if (opts.offset) params.append("offset", String(opts.offset));
|
|
2294
|
+
const qs = params.toString();
|
|
2295
|
+
const { data } = await this.synapCores._getHttpClient().get(
|
|
2296
|
+
`/ai/sessions/${id}/messages${qs ? `?${qs}` : ""}`
|
|
2297
|
+
);
|
|
2298
|
+
return (data.messages ?? data ?? []).map((m) => this.normalizeMessage(m, id));
|
|
2299
|
+
}
|
|
2300
|
+
normalize(data) {
|
|
2301
|
+
return {
|
|
2302
|
+
id: String(data.id ?? data.session_id ?? ""),
|
|
2303
|
+
title: data.title,
|
|
2304
|
+
model: data.model,
|
|
2305
|
+
system_prompt: data.system_prompt,
|
|
2306
|
+
created_at: new Date(data.created_at ?? Date.now()),
|
|
2307
|
+
updated_at: data.updated_at ? new Date(data.updated_at) : void 0,
|
|
2308
|
+
message_count: data.message_count ?? data.messages,
|
|
2309
|
+
metadata: data.metadata
|
|
2310
|
+
};
|
|
2311
|
+
}
|
|
2312
|
+
normalizeMessage(m, sessionId) {
|
|
2313
|
+
return {
|
|
2314
|
+
id: String(m.id ?? m.message_id ?? ""),
|
|
2315
|
+
session_id: m.session_id !== void 0 ? String(m.session_id) : sessionId,
|
|
2316
|
+
role: m.role,
|
|
2317
|
+
content: m.content ?? m.text ?? "",
|
|
2318
|
+
created_at: new Date(m.created_at ?? Date.now()),
|
|
2319
|
+
metadata: m.metadata
|
|
2320
|
+
};
|
|
2321
|
+
}
|
|
2322
|
+
};
|
|
2323
|
+
var ChatToolsApi = class {
|
|
2324
|
+
constructor(synapCores) {
|
|
2325
|
+
this.synapCores = synapCores;
|
|
2326
|
+
}
|
|
2327
|
+
async list() {
|
|
2328
|
+
const { data } = await this.synapCores._getHttpClient().get("/ai/tools");
|
|
2329
|
+
return (data.tools ?? data ?? []).map((t) => ({
|
|
2330
|
+
name: t.name,
|
|
2331
|
+
description: t.description,
|
|
2332
|
+
parameters: t.parameters ?? t.schema
|
|
2333
|
+
}));
|
|
2334
|
+
}
|
|
2335
|
+
async execute(name, args = {}) {
|
|
2336
|
+
const { data } = await this.synapCores._getHttpClient().post("/ai/tools/execute", {
|
|
2337
|
+
tool: name,
|
|
2338
|
+
arguments: args
|
|
2339
|
+
});
|
|
2340
|
+
return data;
|
|
2341
|
+
}
|
|
2342
|
+
async sql(sql, params = []) {
|
|
2343
|
+
const { data } = await this.synapCores._getHttpClient().post("/ai/tools/sql", {
|
|
2344
|
+
sql,
|
|
2345
|
+
parameters: params
|
|
2346
|
+
});
|
|
2347
|
+
return data;
|
|
2348
|
+
}
|
|
2349
|
+
};
|
|
2350
|
+
var ChatCacheApi = class {
|
|
2351
|
+
constructor(synapCores) {
|
|
2352
|
+
this.synapCores = synapCores;
|
|
2353
|
+
}
|
|
2354
|
+
async stats() {
|
|
2355
|
+
const { data } = await this.synapCores._getHttpClient().get("/ai/cache/stats");
|
|
2356
|
+
return {
|
|
2357
|
+
size_bytes: data.size_bytes ?? data.bytes,
|
|
2358
|
+
hit_count: data.hit_count ?? data.hits,
|
|
2359
|
+
miss_count: data.miss_count ?? data.misses,
|
|
2360
|
+
entries: data.entries ?? data.count,
|
|
2361
|
+
raw: data
|
|
2362
|
+
};
|
|
2363
|
+
}
|
|
2364
|
+
async clear() {
|
|
2365
|
+
await this.synapCores._getHttpClient().post("/ai/cache/clear", {});
|
|
2366
|
+
}
|
|
2367
|
+
};
|
|
2368
|
+
var ChatClient = class {
|
|
2369
|
+
constructor(synapCores) {
|
|
2370
|
+
this.synapCores = synapCores;
|
|
2371
|
+
this.sessions = new ChatSessionsApi(synapCores);
|
|
2372
|
+
this.tools = new ChatToolsApi(synapCores);
|
|
2373
|
+
this.cache = new ChatCacheApi(synapCores);
|
|
2374
|
+
}
|
|
2375
|
+
/**
|
|
2376
|
+
* Send a one-shot chat message. The gateway accepts both /ai/chat and
|
|
2377
|
+
* the alias /ai/ — we use /ai/chat for clarity.
|
|
2378
|
+
*/
|
|
2379
|
+
async send(sessionId, content, opts = {}) {
|
|
2380
|
+
const { data } = await this.synapCores._getHttpClient().post("/ai/chat", {
|
|
2381
|
+
session_id: sessionId,
|
|
2382
|
+
content,
|
|
2383
|
+
...opts
|
|
2384
|
+
});
|
|
2385
|
+
const messageData = data.message ?? data;
|
|
2386
|
+
return {
|
|
2387
|
+
message: {
|
|
2388
|
+
id: String(messageData.id ?? messageData.message_id ?? ""),
|
|
2389
|
+
session_id: sessionId,
|
|
2390
|
+
role: messageData.role ?? "assistant",
|
|
2391
|
+
content: messageData.content ?? messageData.text ?? "",
|
|
2392
|
+
created_at: new Date(messageData.created_at ?? Date.now()),
|
|
2393
|
+
metadata: messageData.metadata
|
|
2394
|
+
},
|
|
2395
|
+
tool_calls: data.tool_calls,
|
|
2396
|
+
usage: data.usage
|
|
2397
|
+
};
|
|
2398
|
+
}
|
|
2399
|
+
/**
|
|
2400
|
+
* Stream a chat completion. Returns an async iterator over SSE chunks.
|
|
2401
|
+
*/
|
|
2402
|
+
async *stream(sessionId, content, opts = {}) {
|
|
2403
|
+
const http = this.synapCores._getHttpClient();
|
|
2404
|
+
const response = await http.post(
|
|
2405
|
+
"/ai/chat/stream",
|
|
2406
|
+
{
|
|
2407
|
+
session_id: sessionId,
|
|
2408
|
+
content,
|
|
2409
|
+
...opts
|
|
2410
|
+
},
|
|
2411
|
+
{ responseType: "stream" }
|
|
2412
|
+
);
|
|
2413
|
+
const stream = response.data;
|
|
2414
|
+
let buffer = "";
|
|
2415
|
+
for await (const chunk of stream) {
|
|
2416
|
+
buffer += chunk.toString();
|
|
2417
|
+
const frames = buffer.split(/\n\n/);
|
|
2418
|
+
buffer = frames.pop() ?? "";
|
|
2419
|
+
for (const frame of frames) {
|
|
2420
|
+
const trimmed = frame.trim();
|
|
2421
|
+
if (!trimmed) continue;
|
|
2422
|
+
const line = trimmed.startsWith("data:") ? trimmed.slice(5).trim() : trimmed;
|
|
2423
|
+
if (line === "[DONE]") {
|
|
2424
|
+
yield { done: true };
|
|
2425
|
+
return;
|
|
2426
|
+
}
|
|
2427
|
+
try {
|
|
2428
|
+
const obj = JSON.parse(line);
|
|
2429
|
+
yield {
|
|
2430
|
+
delta: obj.delta ?? obj.choices?.[0]?.delta?.content ?? obj.text ?? void 0,
|
|
2431
|
+
content: obj.content ?? obj.message?.content,
|
|
2432
|
+
type: obj.type ?? obj.event,
|
|
2433
|
+
done: obj.done ?? obj.finished,
|
|
2434
|
+
raw: obj
|
|
2435
|
+
};
|
|
2436
|
+
} catch {
|
|
2437
|
+
yield { delta: line, raw: line };
|
|
2438
|
+
}
|
|
2439
|
+
}
|
|
2440
|
+
}
|
|
2441
|
+
if (buffer.trim()) {
|
|
2442
|
+
try {
|
|
2443
|
+
yield { raw: JSON.parse(buffer) };
|
|
2444
|
+
} catch {
|
|
2445
|
+
yield { delta: buffer };
|
|
2446
|
+
}
|
|
2447
|
+
}
|
|
2448
|
+
}
|
|
2449
|
+
/**
|
|
2450
|
+
* Get prompt suggestions, e.g. for an empty session UI.
|
|
2451
|
+
*/
|
|
2452
|
+
async suggestions(opts = {}) {
|
|
2453
|
+
const { data } = await this.synapCores._getHttpClient().post("/ai/suggestions", opts);
|
|
2454
|
+
return (data.suggestions ?? data ?? []).map((s) => ({
|
|
2455
|
+
prompt: s.prompt ?? s.text ?? "",
|
|
2456
|
+
category: s.category,
|
|
2457
|
+
meta: s.meta ?? s.metadata
|
|
2458
|
+
}));
|
|
2459
|
+
}
|
|
2460
|
+
/**
|
|
2461
|
+
* List configured chat models.
|
|
1774
2462
|
*/
|
|
1775
|
-
async
|
|
1776
|
-
const { data } = await this.synapCores._getHttpClient().
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
active: data.active,
|
|
1785
|
-
last_run_at: data.last_run_at ? new Date(data.last_run_at) : void 0,
|
|
1786
|
-
next_run_at: data.next_run_at ? new Date(data.next_run_at) : void 0,
|
|
1787
|
-
created_at: new Date(data.created_at),
|
|
1788
|
-
tags: data.tags || []
|
|
1789
|
-
};
|
|
2463
|
+
async models() {
|
|
2464
|
+
const { data } = await this.synapCores._getHttpClient().get("/ai/models");
|
|
2465
|
+
return (data.models ?? data ?? []).map((m) => ({
|
|
2466
|
+
id: m.id ?? m.name,
|
|
2467
|
+
name: m.name,
|
|
2468
|
+
provider: m.provider,
|
|
2469
|
+
context_window: m.context_window ?? m.max_context,
|
|
2470
|
+
capabilities: m.capabilities
|
|
2471
|
+
}));
|
|
1790
2472
|
}
|
|
1791
2473
|
/**
|
|
1792
|
-
*
|
|
2474
|
+
* List the available system prompts library.
|
|
1793
2475
|
*/
|
|
1794
|
-
async
|
|
1795
|
-
const { data } = await this.synapCores._getHttpClient().get("/
|
|
2476
|
+
async systemPrompts() {
|
|
2477
|
+
const { data } = await this.synapCores._getHttpClient().get("/ai/system-prompts");
|
|
2478
|
+
return (data.prompts ?? data.system_prompts ?? data ?? []).map((p) => ({
|
|
2479
|
+
id: String(p.id ?? p.name ?? ""),
|
|
2480
|
+
name: p.name,
|
|
2481
|
+
content: p.content ?? p.text ?? "",
|
|
2482
|
+
description: p.description,
|
|
2483
|
+
category: p.category
|
|
2484
|
+
}));
|
|
2485
|
+
}
|
|
2486
|
+
};
|
|
2487
|
+
|
|
2488
|
+
// src/multimodal.ts
|
|
2489
|
+
var MultimodalClient = class {
|
|
2490
|
+
constructor(synapCores) {
|
|
2491
|
+
this.synapCores = synapCores;
|
|
2492
|
+
}
|
|
2493
|
+
async similarity(a, b, opts = {}) {
|
|
2494
|
+
const { data } = await this.synapCores._getHttpClient().post("/multimodal/similarity", {
|
|
2495
|
+
a: typeof a === "string" ? { type: "text", text: a } : a,
|
|
2496
|
+
b: typeof b === "string" ? { type: "text", text: b } : b,
|
|
2497
|
+
...opts
|
|
2498
|
+
});
|
|
1796
2499
|
return {
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
failed_backups: data.failed_backups || 0,
|
|
1801
|
-
avg_backup_size_bytes: data.avg_backup_size_bytes || 0,
|
|
1802
|
-
avg_duration_ms: data.avg_duration_ms || 0,
|
|
1803
|
-
last_backup_at: data.last_backup_at ? new Date(data.last_backup_at) : void 0,
|
|
1804
|
-
next_scheduled_at: data.next_scheduled_at ? new Date(data.next_scheduled_at) : void 0
|
|
2500
|
+
similarity: data.similarity ?? data.score ?? 0,
|
|
2501
|
+
metric: data.metric ?? opts.metric,
|
|
2502
|
+
raw: data
|
|
1805
2503
|
};
|
|
1806
2504
|
}
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
2505
|
+
async search(query, opts = {}) {
|
|
2506
|
+
const { data } = await this.synapCores._getHttpClient().post("/multimodal/search", {
|
|
2507
|
+
query: typeof query === "string" ? { type: "text", text: query } : query,
|
|
2508
|
+
...opts
|
|
2509
|
+
});
|
|
2510
|
+
return (data.results ?? data.hits ?? data ?? []).map((r) => ({
|
|
2511
|
+
id: String(r.id ?? r.document_id ?? ""),
|
|
2512
|
+
score: r.score ?? r.similarity ?? 0,
|
|
2513
|
+
modality: r.modality,
|
|
2514
|
+
metadata: r.metadata
|
|
2515
|
+
}));
|
|
2516
|
+
}
|
|
2517
|
+
async join(left, right, opts = {}) {
|
|
2518
|
+
const normalize = (side) => Array.isArray(side) ? side.map((s) => typeof s === "string" ? { type: "text", text: s } : s) : side;
|
|
2519
|
+
const { data } = await this.synapCores._getHttpClient().post("/multimodal/join", {
|
|
2520
|
+
left: normalize(left),
|
|
2521
|
+
right: normalize(right),
|
|
2522
|
+
...opts
|
|
2523
|
+
});
|
|
1811
2524
|
return {
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
2525
|
+
pairs: (data.pairs ?? data.results ?? []).map((p) => ({
|
|
2526
|
+
left: p.left,
|
|
2527
|
+
right: p.right,
|
|
2528
|
+
score: p.score ?? p.similarity ?? 0
|
|
2529
|
+
}))
|
|
2530
|
+
};
|
|
2531
|
+
}
|
|
2532
|
+
async embed(input, model) {
|
|
2533
|
+
const { data } = await this.synapCores._getHttpClient().post("/multimodal/embed", {
|
|
2534
|
+
input: typeof input === "string" ? { type: "text", text: input } : input,
|
|
2535
|
+
model
|
|
2536
|
+
});
|
|
2537
|
+
const embedding = data.embedding ?? data.vector ?? [];
|
|
2538
|
+
return {
|
|
2539
|
+
embedding,
|
|
2540
|
+
modality: data.modality,
|
|
2541
|
+
model: data.model ?? model,
|
|
2542
|
+
dimensions: data.dimensions ?? embedding.length
|
|
1829
2543
|
};
|
|
1830
2544
|
}
|
|
1831
2545
|
};
|
|
1832
2546
|
|
|
1833
|
-
// src/
|
|
1834
|
-
var
|
|
1835
|
-
constructor(
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
2547
|
+
// src/system.ts
|
|
2548
|
+
var VisionApi = class {
|
|
2549
|
+
constructor(synapCores) {
|
|
2550
|
+
this.synapCores = synapCores;
|
|
2551
|
+
}
|
|
2552
|
+
async get() {
|
|
2553
|
+
try {
|
|
2554
|
+
const { data } = await this.synapCores._getHttpClient().get("/system/vision");
|
|
2555
|
+
if (!data || Object.keys(data).length === 0) return null;
|
|
2556
|
+
return data;
|
|
2557
|
+
} catch (e) {
|
|
2558
|
+
if (e?.statusCode === 404 || e?.code === "NOT_FOUND") return null;
|
|
2559
|
+
throw e;
|
|
1842
2560
|
}
|
|
1843
2561
|
}
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
super(message, "CONNECTION_ERROR", details);
|
|
1848
|
-
this.name = "ConnectionError";
|
|
2562
|
+
async set(cfg) {
|
|
2563
|
+
const { data } = await this.synapCores._getHttpClient().put("/system/vision", cfg);
|
|
2564
|
+
return data;
|
|
1849
2565
|
}
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
constructor(message, details) {
|
|
1853
|
-
super(message, "AUTH_ERROR", details);
|
|
1854
|
-
this.name = "AuthenticationError";
|
|
2566
|
+
async delete() {
|
|
2567
|
+
await this.synapCores._getHttpClient().delete("/system/vision");
|
|
1855
2568
|
}
|
|
1856
|
-
}
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
2569
|
+
async test(payload = {}) {
|
|
2570
|
+
const { data } = await this.synapCores._getHttpClient().post("/system/vision/test", payload);
|
|
2571
|
+
return {
|
|
2572
|
+
success: data.success ?? false,
|
|
2573
|
+
latency_ms: data.latency_ms,
|
|
2574
|
+
response: data.response,
|
|
2575
|
+
error: data.error
|
|
2576
|
+
};
|
|
1861
2577
|
}
|
|
1862
2578
|
};
|
|
1863
|
-
var
|
|
1864
|
-
constructor(
|
|
1865
|
-
|
|
1866
|
-
this.name = "NotFoundError";
|
|
2579
|
+
var SystemClient = class {
|
|
2580
|
+
constructor(synapCores) {
|
|
2581
|
+
this.vision = new VisionApi(synapCores);
|
|
1867
2582
|
}
|
|
1868
2583
|
};
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
2584
|
+
|
|
2585
|
+
// src/transactions.ts
|
|
2586
|
+
var Tx = class {
|
|
2587
|
+
constructor(http, id, options) {
|
|
2588
|
+
this.http = http;
|
|
2589
|
+
this.id = id;
|
|
2590
|
+
this.options = options;
|
|
2591
|
+
this.active = true;
|
|
1873
2592
|
}
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
constructor(message, details) {
|
|
1877
|
-
super(message, "TIMEOUT_ERROR", details);
|
|
1878
|
-
this.name = "TimeoutError";
|
|
2593
|
+
isActive() {
|
|
2594
|
+
return this.active;
|
|
1879
2595
|
}
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
2596
|
+
async execute(sql, params = []) {
|
|
2597
|
+
this.assertActive();
|
|
2598
|
+
const { data } = await this.http.post(`/transactions/${this.id}/execute`, {
|
|
2599
|
+
sql,
|
|
2600
|
+
parameters: params
|
|
2601
|
+
});
|
|
2602
|
+
return {
|
|
2603
|
+
columns: data.columns ?? [],
|
|
2604
|
+
rows: data.rows ?? [],
|
|
2605
|
+
rows_affected: data.rows_affected,
|
|
2606
|
+
execution_time_ms: data.execution_time_ms ?? data.took_ms
|
|
2607
|
+
};
|
|
1886
2608
|
}
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
this.
|
|
1894
|
-
this.
|
|
1895
|
-
this.
|
|
2609
|
+
async commit() {
|
|
2610
|
+
this.assertActive();
|
|
2611
|
+
await this.http.post(`/transactions/${this.id}/commit`, {});
|
|
2612
|
+
this.active = false;
|
|
2613
|
+
}
|
|
2614
|
+
async rollback() {
|
|
2615
|
+
this.assertActive();
|
|
2616
|
+
await this.http.post(`/transactions/${this.id}/rollback`, {});
|
|
2617
|
+
this.active = false;
|
|
2618
|
+
}
|
|
2619
|
+
async savepoint(name) {
|
|
2620
|
+
this.assertActive();
|
|
2621
|
+
await this.http.post(`/transactions/${this.id}/savepoint`, { name });
|
|
2622
|
+
}
|
|
2623
|
+
async rollbackTo(name) {
|
|
2624
|
+
this.assertActive();
|
|
2625
|
+
await this.http.post(`/transactions/${this.id}/savepoint/${name}/rollback`, {});
|
|
2626
|
+
}
|
|
2627
|
+
assertActive() {
|
|
2628
|
+
if (!this.active) {
|
|
2629
|
+
throw new Error(`Transaction ${this.id} has already been committed/rolled back`);
|
|
2630
|
+
}
|
|
1896
2631
|
}
|
|
1897
2632
|
};
|
|
1898
|
-
var
|
|
1899
|
-
constructor(
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
2633
|
+
var TxHistoryApi = class {
|
|
2634
|
+
constructor(synapCores) {
|
|
2635
|
+
this.synapCores = synapCores;
|
|
2636
|
+
}
|
|
2637
|
+
async list(opts = {}) {
|
|
2638
|
+
const params = new URLSearchParams();
|
|
2639
|
+
if (opts.limit) params.append("limit", String(opts.limit));
|
|
2640
|
+
if (opts.status) params.append("status", opts.status);
|
|
2641
|
+
const qs = params.toString();
|
|
2642
|
+
const { data } = await this.synapCores._getHttpClient().get(
|
|
2643
|
+
`/transactions/history${qs ? `?${qs}` : ""}`
|
|
2644
|
+
);
|
|
2645
|
+
return (data.transactions ?? data.history ?? data ?? []).map((row) => ({
|
|
2646
|
+
id: String(row.id ?? row.transaction_id ?? ""),
|
|
2647
|
+
status: row.status ?? "unknown",
|
|
2648
|
+
started_at: new Date(row.started_at ?? row.created_at ?? Date.now()),
|
|
2649
|
+
completed_at: row.completed_at ? new Date(row.completed_at) : void 0,
|
|
2650
|
+
isolation_level: row.isolation_level,
|
|
2651
|
+
read_only: row.read_only,
|
|
2652
|
+
statement_count: row.statement_count ?? row.statements,
|
|
2653
|
+
metrics: row.metrics
|
|
2654
|
+
}));
|
|
2655
|
+
}
|
|
2656
|
+
async get(id) {
|
|
2657
|
+
const { data } = await this.synapCores._getHttpClient().get(
|
|
2658
|
+
`/transactions/history/${id}`
|
|
2659
|
+
);
|
|
2660
|
+
return {
|
|
2661
|
+
id: String(data.id ?? id),
|
|
2662
|
+
status: data.status ?? "unknown",
|
|
2663
|
+
started_at: new Date(data.started_at ?? data.created_at ?? Date.now()),
|
|
2664
|
+
completed_at: data.completed_at ? new Date(data.completed_at) : void 0,
|
|
2665
|
+
isolation_level: data.isolation_level,
|
|
2666
|
+
read_only: data.read_only,
|
|
2667
|
+
statement_count: data.statement_count ?? data.statements,
|
|
2668
|
+
metrics: data.metrics
|
|
2669
|
+
};
|
|
1905
2670
|
}
|
|
1906
2671
|
};
|
|
1907
|
-
var
|
|
1908
|
-
constructor(
|
|
1909
|
-
|
|
1910
|
-
this.
|
|
1911
|
-
|
|
1912
|
-
|
|
2672
|
+
var TransactionsClient = class {
|
|
2673
|
+
constructor(synapCores) {
|
|
2674
|
+
this.synapCores = synapCores;
|
|
2675
|
+
this.history = new TxHistoryApi(synapCores);
|
|
2676
|
+
}
|
|
2677
|
+
/**
|
|
2678
|
+
* Begin a new server-side transaction.
|
|
2679
|
+
*/
|
|
2680
|
+
async begin(opts = {}) {
|
|
2681
|
+
const { data } = await this.synapCores._getHttpClient().post("/transactions", opts);
|
|
2682
|
+
const id = String(data.id ?? data.transaction_id ?? "");
|
|
2683
|
+
if (!id) {
|
|
2684
|
+
throw new Error("begin(): server did not return a transaction id");
|
|
2685
|
+
}
|
|
2686
|
+
return new Tx(this.synapCores._getHttpClient(), id, opts);
|
|
1913
2687
|
}
|
|
1914
2688
|
};
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
2689
|
+
|
|
2690
|
+
// src/mcp.ts
|
|
2691
|
+
var mcpRequestCounter = 0;
|
|
2692
|
+
function withId(req) {
|
|
2693
|
+
if (req.id !== void 0 && req.id !== null) return req;
|
|
2694
|
+
mcpRequestCounter += 1;
|
|
2695
|
+
return { ...req, id: `mcp-${Date.now()}-${mcpRequestCounter}` };
|
|
2696
|
+
}
|
|
2697
|
+
var McpClient = class {
|
|
2698
|
+
constructor(synapCores) {
|
|
2699
|
+
this.synapCores = synapCores;
|
|
2700
|
+
}
|
|
2701
|
+
/**
|
|
2702
|
+
* Invoke a single MCP method.
|
|
2703
|
+
*/
|
|
2704
|
+
async invoke(req) {
|
|
2705
|
+
const body = withId(req);
|
|
2706
|
+
const { data } = await this.synapCores._getHttpClient().post("/mcp", body);
|
|
2707
|
+
return {
|
|
2708
|
+
id: data.id ?? body.id,
|
|
2709
|
+
result: data.result,
|
|
2710
|
+
error: data.error,
|
|
2711
|
+
raw: data
|
|
2712
|
+
};
|
|
2713
|
+
}
|
|
2714
|
+
/**
|
|
2715
|
+
* Send an array of MCP invocations and resolve to the matching array
|
|
2716
|
+
* of responses (in the order returned by the gateway).
|
|
2717
|
+
*/
|
|
2718
|
+
async batch(reqs) {
|
|
2719
|
+
const body = reqs.map(withId);
|
|
2720
|
+
const { data } = await this.synapCores._getHttpClient().post("/mcp/batch", body);
|
|
2721
|
+
const arr = Array.isArray(data) ? data : data.responses ?? data.results ?? [];
|
|
2722
|
+
return arr.map((r) => ({
|
|
2723
|
+
id: r.id,
|
|
2724
|
+
result: r.result,
|
|
2725
|
+
error: r.error,
|
|
2726
|
+
raw: r
|
|
2727
|
+
}));
|
|
2728
|
+
}
|
|
2729
|
+
/**
|
|
2730
|
+
* Discover the server's MCP capabilities and tools.
|
|
2731
|
+
*/
|
|
2732
|
+
async info() {
|
|
2733
|
+
const { data } = await this.synapCores._getHttpClient().get("/mcp/info");
|
|
2734
|
+
return {
|
|
2735
|
+
version: data.version ?? data.mcp_version ?? "0",
|
|
2736
|
+
capabilities: data.capabilities,
|
|
2737
|
+
tools: data.tools,
|
|
2738
|
+
meta: data.meta ?? data.metadata
|
|
2739
|
+
};
|
|
1922
2740
|
}
|
|
1923
2741
|
};
|
|
1924
2742
|
|
|
@@ -1957,7 +2775,7 @@ var SynapCores = class {
|
|
|
1957
2775
|
timeout: this.config.timeout,
|
|
1958
2776
|
headers: {
|
|
1959
2777
|
"Content-Type": "application/json",
|
|
1960
|
-
"User-Agent": "synapcores-nodejs/0.
|
|
2778
|
+
"User-Agent": "synapcores-nodejs/0.2.0",
|
|
1961
2779
|
...authHeader
|
|
1962
2780
|
},
|
|
1963
2781
|
...httpsAgent && { httpsAgent }
|
|
@@ -1973,6 +2791,44 @@ var SynapCores = class {
|
|
|
1973
2791
|
this.import = new ImportExportClient(this);
|
|
1974
2792
|
this.integrations = new IntegrationClient(this);
|
|
1975
2793
|
this.backup = new BackupClient(this);
|
|
2794
|
+
this.graph = new GraphClient(this);
|
|
2795
|
+
this.nl2sql = new NL2SqlClient(this);
|
|
2796
|
+
this.filesystem = new FilesystemCollectionsClient(this);
|
|
2797
|
+
this.chat = new ChatClient(this);
|
|
2798
|
+
this.multimodal = new MultimodalClient(this);
|
|
2799
|
+
this.system = new SystemClient(this);
|
|
2800
|
+
this.transactions = new TransactionsClient(this);
|
|
2801
|
+
this.mcp = new McpClient(this);
|
|
2802
|
+
}
|
|
2803
|
+
/**
|
|
2804
|
+
* Build the WebSocket base URL (ws:// or wss://).
|
|
2805
|
+
*/
|
|
2806
|
+
_getWsBaseUrl() {
|
|
2807
|
+
const protocol = this.config.useHttps ? "wss" : "ws";
|
|
2808
|
+
return `${protocol}://${this.config.host}:${this.config.port}`;
|
|
2809
|
+
}
|
|
2810
|
+
/**
|
|
2811
|
+
* Read-only access to the configured host/port for WS-clients.
|
|
2812
|
+
*/
|
|
2813
|
+
_getConfig() {
|
|
2814
|
+
return this.config;
|
|
2815
|
+
}
|
|
2816
|
+
/**
|
|
2817
|
+
* Exchange the current credentials (JWT or API key) for a short-lived
|
|
2818
|
+
* WebSocket ticket. Use the returned token as the `?token=` query
|
|
2819
|
+
* param when opening any /ws endpoint.
|
|
2820
|
+
*/
|
|
2821
|
+
async createWsTicket() {
|
|
2822
|
+
const { data } = await this.httpClient.post("/ws/ticket", {});
|
|
2823
|
+
const token = data.token ?? data.ticket;
|
|
2824
|
+
const expiresAt = typeof data.expiresAt === "number" ? data.expiresAt : data.expires_at ? Date.parse(data.expires_at) : Date.now() + 6e4;
|
|
2825
|
+
return { token, expiresAt };
|
|
2826
|
+
}
|
|
2827
|
+
/**
|
|
2828
|
+
* Revoke a previously-issued ticket (best-effort).
|
|
2829
|
+
*/
|
|
2830
|
+
async revokeWsTicket(token) {
|
|
2831
|
+
await this.httpClient.post("/ws/ticket/revoke", { token });
|
|
1976
2832
|
}
|
|
1977
2833
|
handleError(error) {
|
|
1978
2834
|
if (!error.response) {
|
|
@@ -2161,11 +3017,11 @@ var SynapCores = class {
|
|
|
2161
3017
|
async embed(text, options = {}) {
|
|
2162
3018
|
const isBatch = Array.isArray(text);
|
|
2163
3019
|
const texts = isBatch ? text : [text];
|
|
2164
|
-
const
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
return
|
|
3020
|
+
const path = isBatch ? "/ai/embeddings/batch" : "/ai/embeddings";
|
|
3021
|
+
const body = isBatch ? { texts, model: options.model } : { text: texts[0], model: options.model };
|
|
3022
|
+
const { data } = await this.httpClient.post(path, body);
|
|
3023
|
+
if (isBatch) return data.embeddings ?? data;
|
|
3024
|
+
return data.embedding ?? data.embeddings?.[0] ?? data;
|
|
2169
3025
|
}
|
|
2170
3026
|
// Internal method for HTTP client access
|
|
2171
3027
|
_getHttpClient() {
|
|
@@ -2292,8 +3148,16 @@ var SynapCores = class {
|
|
|
2292
3148
|
* @returns Promise resolving to table information
|
|
2293
3149
|
*/
|
|
2294
3150
|
async describeTable(tableName) {
|
|
2295
|
-
const
|
|
2296
|
-
|
|
3151
|
+
const [tableRes, colsRes, idxRes] = await Promise.all([
|
|
3152
|
+
this.httpClient.get(`/schema/tables/${tableName}`),
|
|
3153
|
+
this.httpClient.get(`/schema/tables/${tableName}/columns`),
|
|
3154
|
+
this.httpClient.get(`/schema/tables/${tableName}/indexes`)
|
|
3155
|
+
]);
|
|
3156
|
+
return {
|
|
3157
|
+
...tableRes.data,
|
|
3158
|
+
columns: colsRes.data?.columns ?? colsRes.data ?? [],
|
|
3159
|
+
indexes: idxRes.data?.indexes ?? idxRes.data ?? []
|
|
3160
|
+
};
|
|
2297
3161
|
}
|
|
2298
3162
|
/**
|
|
2299
3163
|
* Lists all tables in the current database
|
|
@@ -2426,19 +3290,26 @@ var SynapCores = class {
|
|
|
2426
3290
|
* @returns Promise resolving to batch operation result
|
|
2427
3291
|
*/
|
|
2428
3292
|
async batchInsert(options) {
|
|
2429
|
-
const
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
3293
|
+
const cols = options.columns ?? [];
|
|
3294
|
+
const queries = options.rows.map((row) => {
|
|
3295
|
+
const values = Array.isArray(row) ? row : cols.map((c) => row[c]);
|
|
3296
|
+
return {
|
|
3297
|
+
sql: `INSERT INTO ${options.tableName} (${cols.join(", ")}) VALUES (${values.map((_, i) => "$" + (i + 1)).join(", ")})`,
|
|
3298
|
+
parameters: values
|
|
3299
|
+
};
|
|
3300
|
+
});
|
|
3301
|
+
const { data } = await this.httpClient.post("/query/execute/batch", {
|
|
3302
|
+
queries,
|
|
3303
|
+
transactional: false
|
|
3304
|
+
});
|
|
3305
|
+
const results = data.results ?? [];
|
|
3306
|
+
const successful = results.filter((r) => !r.error).length;
|
|
3307
|
+
return {
|
|
3308
|
+
totalProcessed: results.length,
|
|
3309
|
+
successful,
|
|
3310
|
+
failed: results.length - successful,
|
|
3311
|
+
errors: results.filter((r) => r.error).map((r) => r.error),
|
|
3312
|
+
tookMs: data.total_execution_time_ms ?? 0
|
|
2442
3313
|
};
|
|
2443
3314
|
}
|
|
2444
3315
|
/**
|
|
@@ -2447,17 +3318,27 @@ var SynapCores = class {
|
|
|
2447
3318
|
* @returns Promise resolving to batch operation result
|
|
2448
3319
|
*/
|
|
2449
3320
|
async batchUpdate(options) {
|
|
2450
|
-
const
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
3321
|
+
const queries = options.updates.map((u) => {
|
|
3322
|
+
const setClause = Object.keys(u.set ?? {}).map((k, i) => `${k} = $${i + 1}`).join(", ");
|
|
3323
|
+
const setVals = Object.values(u.set ?? {});
|
|
3324
|
+
const whereStr = u.where ?? "1=1";
|
|
3325
|
+
return {
|
|
3326
|
+
sql: `UPDATE ${options.tableName} SET ${setClause} WHERE ${whereStr}`,
|
|
3327
|
+
parameters: setVals
|
|
3328
|
+
};
|
|
2454
3329
|
});
|
|
3330
|
+
const { data } = await this.httpClient.post("/query/execute/batch", {
|
|
3331
|
+
queries,
|
|
3332
|
+
transactional: false
|
|
3333
|
+
});
|
|
3334
|
+
const results = data.results ?? [];
|
|
3335
|
+
const successful = results.filter((r) => !r.error).length;
|
|
2455
3336
|
return {
|
|
2456
|
-
totalProcessed:
|
|
2457
|
-
successful
|
|
2458
|
-
failed:
|
|
2459
|
-
errors:
|
|
2460
|
-
tookMs: data.
|
|
3337
|
+
totalProcessed: results.length,
|
|
3338
|
+
successful,
|
|
3339
|
+
failed: results.length - successful,
|
|
3340
|
+
errors: results.filter((r) => r.error).map((r) => r.error),
|
|
3341
|
+
tookMs: data.total_execution_time_ms ?? 0
|
|
2461
3342
|
};
|
|
2462
3343
|
}
|
|
2463
3344
|
/**
|
|
@@ -2466,17 +3347,22 @@ var SynapCores = class {
|
|
|
2466
3347
|
* @returns Promise resolving to batch operation result
|
|
2467
3348
|
*/
|
|
2468
3349
|
async batchDelete(options) {
|
|
2469
|
-
const
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
3350
|
+
const queries = (options.whereConditions ?? []).map((cond) => ({
|
|
3351
|
+
sql: `DELETE FROM ${options.tableName} WHERE ${typeof cond === "string" ? cond : JSON.stringify(cond)}`,
|
|
3352
|
+
parameters: []
|
|
3353
|
+
}));
|
|
3354
|
+
const { data } = await this.httpClient.post("/query/execute/batch", {
|
|
3355
|
+
queries,
|
|
3356
|
+
transactional: false
|
|
2473
3357
|
});
|
|
3358
|
+
const results = data.results ?? [];
|
|
3359
|
+
const successful = results.filter((r) => !r.error).length;
|
|
2474
3360
|
return {
|
|
2475
|
-
totalProcessed:
|
|
2476
|
-
successful
|
|
2477
|
-
failed:
|
|
2478
|
-
errors:
|
|
2479
|
-
tookMs: data.
|
|
3361
|
+
totalProcessed: results.length,
|
|
3362
|
+
successful,
|
|
3363
|
+
failed: results.length - successful,
|
|
3364
|
+
errors: results.filter((r) => r.error).map((r) => r.error),
|
|
3365
|
+
tookMs: data.total_execution_time_ms ?? 0
|
|
2480
3366
|
};
|
|
2481
3367
|
}
|
|
2482
3368
|
// =================================================================
|
|
@@ -2489,15 +3375,15 @@ var SynapCores = class {
|
|
|
2489
3375
|
* @returns Promise resolving to prepared statement
|
|
2490
3376
|
*/
|
|
2491
3377
|
async prepareStatement(sql, options = {}) {
|
|
2492
|
-
const { data } = await this.httpClient.post("/prepare", {
|
|
3378
|
+
const { data } = await this.httpClient.post("/query/prepare", {
|
|
2493
3379
|
sql,
|
|
2494
3380
|
name: options.name,
|
|
2495
3381
|
parameter_types: options.parameterTypes
|
|
2496
3382
|
});
|
|
2497
3383
|
const prepared = {
|
|
2498
|
-
id: data.statement_id,
|
|
3384
|
+
id: data.statement_id ?? data.id,
|
|
2499
3385
|
sql,
|
|
2500
|
-
parameterCount: data.parameter_count
|
|
3386
|
+
parameterCount: data.parameter_count ?? data.parameters_count ?? 0
|
|
2501
3387
|
};
|
|
2502
3388
|
if (options.name) {
|
|
2503
3389
|
this.preparedStatements.set(options.name, prepared);
|
|
@@ -2514,7 +3400,7 @@ var SynapCores = class {
|
|
|
2514
3400
|
if (this.preparedStatements.has(statementId)) {
|
|
2515
3401
|
statementId = this.preparedStatements.get(statementId).id;
|
|
2516
3402
|
}
|
|
2517
|
-
const { data } = await this.httpClient.post("/
|
|
3403
|
+
const { data } = await this.httpClient.post("/query/exec", {
|
|
2518
3404
|
statement_id: statementId,
|
|
2519
3405
|
parameters: params
|
|
2520
3406
|
});
|
|
@@ -2534,10 +3420,10 @@ var SynapCores = class {
|
|
|
2534
3420
|
async deallocatePrepared(statementId) {
|
|
2535
3421
|
if (this.preparedStatements.has(statementId)) {
|
|
2536
3422
|
const prepared = this.preparedStatements.get(statementId);
|
|
2537
|
-
await this.httpClient.
|
|
3423
|
+
await this.httpClient.post("/query/close", { statement_id: prepared.id });
|
|
2538
3424
|
this.preparedStatements.delete(statementId);
|
|
2539
3425
|
} else {
|
|
2540
|
-
await this.httpClient.
|
|
3426
|
+
await this.httpClient.post("/query/close", { statement_id: statementId });
|
|
2541
3427
|
}
|
|
2542
3428
|
}
|
|
2543
3429
|
/**
|
|
@@ -2628,231 +3514,198 @@ var SynapCores = class {
|
|
|
2628
3514
|
if (vector1.length !== vector2.length) {
|
|
2629
3515
|
throw new VectorError("Vector dimensions must match", "DIMENSION_MISMATCH");
|
|
2630
3516
|
}
|
|
2631
|
-
const { data } = await this.httpClient.post("/
|
|
2632
|
-
|
|
2633
|
-
|
|
3517
|
+
const { data } = await this.httpClient.post("/vector-algebra/operation", {
|
|
3518
|
+
op: "add",
|
|
3519
|
+
a: vector1,
|
|
3520
|
+
b: vector2
|
|
2634
3521
|
});
|
|
3522
|
+
const result = data.result ?? data.vector ?? [];
|
|
2635
3523
|
return {
|
|
2636
|
-
result: { values:
|
|
3524
|
+
result: { values: result, dimensions: result.length },
|
|
2637
3525
|
operation: "addition",
|
|
2638
3526
|
tookMs: data.took_ms
|
|
2639
3527
|
};
|
|
2640
3528
|
}
|
|
2641
3529
|
/**
|
|
2642
3530
|
* Performs vector subtraction
|
|
2643
|
-
* @param vector1 - First vector (minuend)
|
|
2644
|
-
* @param vector2 - Second vector (subtrahend)
|
|
2645
|
-
* @returns Promise resolving to vector subtraction result
|
|
2646
3531
|
*/
|
|
2647
3532
|
async vectorSubtract(vector1, vector2) {
|
|
2648
3533
|
if (vector1.length !== vector2.length) {
|
|
2649
3534
|
throw new VectorError("Vector dimensions must match", "DIMENSION_MISMATCH");
|
|
2650
3535
|
}
|
|
2651
|
-
const { data } = await this.httpClient.post("/
|
|
2652
|
-
|
|
2653
|
-
|
|
3536
|
+
const { data } = await this.httpClient.post("/vector-algebra/operation", {
|
|
3537
|
+
op: "subtract",
|
|
3538
|
+
a: vector1,
|
|
3539
|
+
b: vector2
|
|
2654
3540
|
});
|
|
3541
|
+
const result = data.result ?? data.vector ?? [];
|
|
2655
3542
|
return {
|
|
2656
|
-
result: { values:
|
|
3543
|
+
result: { values: result, dimensions: result.length },
|
|
2657
3544
|
operation: "subtraction",
|
|
2658
3545
|
tookMs: data.took_ms
|
|
2659
3546
|
};
|
|
2660
3547
|
}
|
|
2661
3548
|
/**
|
|
2662
3549
|
* Performs scalar multiplication on a vector
|
|
2663
|
-
* @param vector - Input vector
|
|
2664
|
-
* @param scalar - Scalar value to multiply by
|
|
2665
|
-
* @returns Promise resolving to scalar multiplication result
|
|
2666
3550
|
*/
|
|
2667
3551
|
async vectorScalarMultiply(vector, scalar) {
|
|
2668
|
-
const { data } = await this.httpClient.post("/
|
|
2669
|
-
|
|
3552
|
+
const { data } = await this.httpClient.post("/vector-algebra/operation", {
|
|
3553
|
+
op: "scalar_multiply",
|
|
3554
|
+
a: vector,
|
|
2670
3555
|
scalar
|
|
2671
3556
|
});
|
|
3557
|
+
const result = data.result ?? data.vector ?? [];
|
|
2672
3558
|
return {
|
|
2673
|
-
result: { values:
|
|
3559
|
+
result: { values: result, dimensions: result.length },
|
|
2674
3560
|
operation: "scalar_multiplication",
|
|
2675
3561
|
tookMs: data.took_ms
|
|
2676
3562
|
};
|
|
2677
3563
|
}
|
|
2678
3564
|
/**
|
|
2679
3565
|
* Calculates the dot product of two vectors
|
|
2680
|
-
* @param vector1 - First vector
|
|
2681
|
-
* @param vector2 - Second vector
|
|
2682
|
-
* @returns Promise resolving to dot product result
|
|
2683
3566
|
*/
|
|
2684
3567
|
async vectorDotProduct(vector1, vector2) {
|
|
2685
3568
|
if (vector1.length !== vector2.length) {
|
|
2686
3569
|
throw new VectorError("Vector dimensions must match", "DIMENSION_MISMATCH");
|
|
2687
3570
|
}
|
|
2688
|
-
const { data } = await this.httpClient.post("/
|
|
2689
|
-
|
|
2690
|
-
|
|
3571
|
+
const { data } = await this.httpClient.post("/vector-algebra/operation", {
|
|
3572
|
+
op: "dot_product",
|
|
3573
|
+
a: vector1,
|
|
3574
|
+
b: vector2
|
|
2691
3575
|
});
|
|
2692
|
-
return {
|
|
2693
|
-
dotProduct: data.dot_product,
|
|
2694
|
-
tookMs: data.took_ms
|
|
2695
|
-
};
|
|
3576
|
+
return { dotProduct: data.scalar ?? data.dot_product ?? 0, tookMs: data.took_ms };
|
|
2696
3577
|
}
|
|
2697
3578
|
/**
|
|
2698
3579
|
* Calculates cosine similarity between two vectors
|
|
2699
|
-
* @param vector1 - First vector
|
|
2700
|
-
* @param vector2 - Second vector
|
|
2701
|
-
* @returns Promise resolving to cosine similarity result
|
|
2702
3580
|
*/
|
|
2703
3581
|
async cosineSimilarity(vector1, vector2) {
|
|
2704
3582
|
if (vector1.length !== vector2.length) {
|
|
2705
3583
|
throw new VectorError("Vector dimensions must match", "DIMENSION_MISMATCH");
|
|
2706
3584
|
}
|
|
2707
|
-
const { data } = await this.httpClient.post("/
|
|
2708
|
-
|
|
2709
|
-
|
|
3585
|
+
const { data } = await this.httpClient.post("/vector-algebra/operation", {
|
|
3586
|
+
op: "cosine_similarity",
|
|
3587
|
+
a: vector1,
|
|
3588
|
+
b: vector2
|
|
2710
3589
|
});
|
|
2711
|
-
return {
|
|
2712
|
-
similarity: data.similarity,
|
|
2713
|
-
function: "cosine",
|
|
2714
|
-
tookMs: data.took_ms
|
|
2715
|
-
};
|
|
3590
|
+
return { similarity: data.scalar ?? data.similarity ?? 0, function: "cosine", tookMs: data.took_ms };
|
|
2716
3591
|
}
|
|
2717
3592
|
/**
|
|
2718
3593
|
* Calculates L2 (Euclidean) distance between two vectors
|
|
2719
|
-
* @param vector1 - First vector
|
|
2720
|
-
* @param vector2 - Second vector
|
|
2721
|
-
* @returns Promise resolving to L2 distance result
|
|
2722
3594
|
*/
|
|
2723
3595
|
async l2Distance(vector1, vector2) {
|
|
2724
3596
|
if (vector1.length !== vector2.length) {
|
|
2725
3597
|
throw new VectorError("Vector dimensions must match", "DIMENSION_MISMATCH");
|
|
2726
3598
|
}
|
|
2727
|
-
const { data } = await this.httpClient.post("/
|
|
2728
|
-
|
|
2729
|
-
|
|
3599
|
+
const { data } = await this.httpClient.post("/vector-algebra/operation", {
|
|
3600
|
+
op: "l2_distance",
|
|
3601
|
+
a: vector1,
|
|
3602
|
+
b: vector2
|
|
2730
3603
|
});
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
similarity: data.distance,
|
|
2734
|
-
// Include similarity for compatibility
|
|
2735
|
-
function: "l2",
|
|
2736
|
-
tookMs: data.took_ms
|
|
2737
|
-
};
|
|
3604
|
+
const distance = data.scalar ?? data.distance ?? 0;
|
|
3605
|
+
return { distance, similarity: distance, function: "l2", tookMs: data.took_ms };
|
|
2738
3606
|
}
|
|
2739
3607
|
/**
|
|
2740
3608
|
* Calculates inner product between two vectors
|
|
2741
|
-
* @param vector1 - First vector
|
|
2742
|
-
* @param vector2 - Second vector
|
|
2743
|
-
* @returns Promise resolving to inner product result
|
|
2744
3609
|
*/
|
|
2745
3610
|
async innerProduct(vector1, vector2) {
|
|
2746
3611
|
if (vector1.length !== vector2.length) {
|
|
2747
3612
|
throw new VectorError("Vector dimensions must match", "DIMENSION_MISMATCH");
|
|
2748
3613
|
}
|
|
2749
|
-
const { data } = await this.httpClient.post("/
|
|
2750
|
-
|
|
2751
|
-
|
|
3614
|
+
const { data } = await this.httpClient.post("/vector-algebra/operation", {
|
|
3615
|
+
op: "inner_product",
|
|
3616
|
+
a: vector1,
|
|
3617
|
+
b: vector2
|
|
2752
3618
|
});
|
|
2753
|
-
return {
|
|
2754
|
-
similarity: data.inner_product,
|
|
2755
|
-
function: "inner_product",
|
|
2756
|
-
tookMs: data.took_ms
|
|
2757
|
-
};
|
|
3619
|
+
return { similarity: data.scalar ?? data.inner_product ?? 0, function: "inner_product", tookMs: data.took_ms };
|
|
2758
3620
|
}
|
|
2759
3621
|
/**
|
|
2760
|
-
* Performs K-nearest neighbors vector search
|
|
2761
|
-
*
|
|
2762
|
-
* @returns Promise resolving to KNN search results
|
|
3622
|
+
* Performs K-nearest neighbors vector search.
|
|
3623
|
+
* v0.2.0: routes through /vectors/collections/:c/search with mode discriminator.
|
|
2763
3624
|
*/
|
|
2764
3625
|
async knnSearch(options) {
|
|
2765
|
-
const
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
metadata_columns: options.metadataColumns,
|
|
3626
|
+
const collection = options.collectionName ?? options.tableName;
|
|
3627
|
+
const { data } = await this.httpClient.post(`/vectors/collections/${collection}/search`, {
|
|
3628
|
+
mode: "knn",
|
|
3629
|
+
vector: options.queryVector,
|
|
3630
|
+
limit: options.k,
|
|
2771
3631
|
filter: options.filter
|
|
2772
3632
|
});
|
|
2773
|
-
return data.results.map((
|
|
2774
|
-
id:
|
|
2775
|
-
vector:
|
|
2776
|
-
similarity:
|
|
2777
|
-
distance:
|
|
2778
|
-
metadata:
|
|
3633
|
+
return (data.matches ?? data.results ?? []).map((r) => ({
|
|
3634
|
+
id: r.id,
|
|
3635
|
+
vector: r.vector,
|
|
3636
|
+
similarity: r.similarity,
|
|
3637
|
+
distance: r.distance,
|
|
3638
|
+
metadata: r.metadata
|
|
2779
3639
|
}));
|
|
2780
3640
|
}
|
|
2781
3641
|
/**
|
|
2782
|
-
* Performs range-based vector similarity search
|
|
2783
|
-
* @param options - Range search options
|
|
2784
|
-
* @returns Promise resolving to range search results
|
|
3642
|
+
* Performs range-based vector similarity search.
|
|
2785
3643
|
*/
|
|
2786
3644
|
async rangeSearch(options) {
|
|
2787
|
-
const
|
|
2788
|
-
|
|
3645
|
+
const collection = options.collectionName ?? options.tableName;
|
|
3646
|
+
const { data } = await this.httpClient.post(`/vectors/collections/${collection}/search`, {
|
|
3647
|
+
mode: "range",
|
|
3648
|
+
vector: options.queryVector,
|
|
2789
3649
|
threshold: options.threshold,
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
similarity: result.similarity,
|
|
2800
|
-
distance: result.distance,
|
|
2801
|
-
metadata: result.metadata
|
|
3650
|
+
max_results: options.maxResults,
|
|
3651
|
+
filter: options.filter
|
|
3652
|
+
});
|
|
3653
|
+
return (data.matches ?? data.results ?? []).map((r) => ({
|
|
3654
|
+
id: r.id,
|
|
3655
|
+
vector: r.vector,
|
|
3656
|
+
similarity: r.similarity,
|
|
3657
|
+
distance: r.distance,
|
|
3658
|
+
metadata: r.metadata
|
|
2802
3659
|
}));
|
|
2803
3660
|
}
|
|
2804
3661
|
/**
|
|
2805
|
-
* Performs hybrid search combining vector similarity and SQL filtering
|
|
2806
|
-
* @param options - Hybrid search options
|
|
2807
|
-
* @returns Promise resolving to hybrid search results
|
|
3662
|
+
* Performs hybrid search combining vector similarity and SQL filtering.
|
|
2808
3663
|
*/
|
|
2809
3664
|
async hybridSearch(options) {
|
|
2810
|
-
const
|
|
3665
|
+
const collection = options.collectionName ?? options.tableName;
|
|
3666
|
+
const { data } = await this.httpClient.post(`/vectors/collections/${collection}/search`, {
|
|
3667
|
+
mode: "hybrid",
|
|
2811
3668
|
vector: options.vector,
|
|
2812
3669
|
text_query: options.textQuery,
|
|
2813
3670
|
sql_filter: options.sqlFilter,
|
|
2814
|
-
|
|
3671
|
+
limit: options.k,
|
|
2815
3672
|
threshold: options.threshold,
|
|
2816
3673
|
metric: options.metric,
|
|
2817
3674
|
filter: options.filter,
|
|
2818
3675
|
weights: options.weights
|
|
2819
3676
|
});
|
|
2820
|
-
return data.results.map((
|
|
2821
|
-
id:
|
|
2822
|
-
vector:
|
|
2823
|
-
similarity:
|
|
2824
|
-
distance:
|
|
2825
|
-
metadata:
|
|
3677
|
+
return (data.matches ?? data.results ?? []).map((r) => ({
|
|
3678
|
+
id: r.id,
|
|
3679
|
+
vector: r.vector,
|
|
3680
|
+
similarity: r.similarity,
|
|
3681
|
+
distance: r.distance,
|
|
3682
|
+
metadata: r.metadata
|
|
2826
3683
|
}));
|
|
2827
3684
|
}
|
|
2828
3685
|
/**
|
|
2829
3686
|
* Normalizes a vector to unit length
|
|
2830
|
-
* @param vector - Input vector to normalize
|
|
2831
|
-
* @returns Promise resolving to normalized vector
|
|
2832
3687
|
*/
|
|
2833
3688
|
async normalizeVector(vector) {
|
|
2834
|
-
const { data } = await this.httpClient.post("/
|
|
2835
|
-
|
|
3689
|
+
const { data } = await this.httpClient.post("/vector-algebra/operation", {
|
|
3690
|
+
op: "normalize",
|
|
3691
|
+
a: vector
|
|
2836
3692
|
});
|
|
3693
|
+
const result = data.result ?? data.vector ?? [];
|
|
2837
3694
|
return {
|
|
2838
|
-
result: { values:
|
|
3695
|
+
result: { values: result, dimensions: result.length },
|
|
2839
3696
|
operation: "normalization",
|
|
2840
3697
|
tookMs: data.took_ms
|
|
2841
3698
|
};
|
|
2842
3699
|
}
|
|
2843
3700
|
/**
|
|
2844
3701
|
* Calculates the magnitude (length) of a vector
|
|
2845
|
-
* @param vector - Input vector
|
|
2846
|
-
* @returns Promise resolving to vector magnitude
|
|
2847
3702
|
*/
|
|
2848
3703
|
async vectorMagnitude(vector) {
|
|
2849
|
-
const { data } = await this.httpClient.post("/
|
|
2850
|
-
|
|
3704
|
+
const { data } = await this.httpClient.post("/vector-algebra/operation", {
|
|
3705
|
+
op: "magnitude",
|
|
3706
|
+
a: vector
|
|
2851
3707
|
});
|
|
2852
|
-
return {
|
|
2853
|
-
magnitude: data.magnitude,
|
|
2854
|
-
tookMs: data.took_ms
|
|
2855
|
-
};
|
|
3708
|
+
return { magnitude: data.scalar ?? data.magnitude ?? 0, tookMs: data.took_ms };
|
|
2856
3709
|
}
|
|
2857
3710
|
// =================================================================
|
|
2858
3711
|
// AUTHENTICATION & USER MANAGEMENT
|
|
@@ -2884,16 +3737,26 @@ var SynapCores = class {
|
|
|
2884
3737
|
return data;
|
|
2885
3738
|
}
|
|
2886
3739
|
/**
|
|
2887
|
-
* Refresh JWT token
|
|
3740
|
+
* Refresh JWT token.
|
|
3741
|
+
*
|
|
3742
|
+
* v0.2.0: the gateway does not currently expose a refresh endpoint —
|
|
3743
|
+
* this method now re-runs login() with the same credentials. Pass
|
|
3744
|
+
* the credentials in the call site (or supply them at SDK construction
|
|
3745
|
+
* time and we'll re-use the cached pair).
|
|
2888
3746
|
*/
|
|
2889
|
-
async refreshToken() {
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
3747
|
+
async refreshToken(credentials) {
|
|
3748
|
+
if (credentials?.username && credentials?.password) {
|
|
3749
|
+
const login = await this.login({ username: credentials.username, password: credentials.password });
|
|
3750
|
+
return {
|
|
3751
|
+
access_token: login.access_token,
|
|
3752
|
+
refresh_token: "",
|
|
3753
|
+
token_type: "Bearer",
|
|
3754
|
+
expires_in: login.expires_in
|
|
3755
|
+
};
|
|
2895
3756
|
}
|
|
2896
|
-
|
|
3757
|
+
throw new ValidationError(
|
|
3758
|
+
"refreshToken now requires credentials \u2014 the gateway has no /auth/refresh endpoint in v1.5.0-ce. Pass {username, password} or call login() again."
|
|
3759
|
+
);
|
|
2897
3760
|
}
|
|
2898
3761
|
/**
|
|
2899
3762
|
* Set JWT token manually (useful after login)
|
|
@@ -3024,17 +3887,23 @@ var SynapCores = class {
|
|
|
3024
3887
|
|
|
3025
3888
|
// src/index.ts
|
|
3026
3889
|
import { z } from "zod";
|
|
3027
|
-
var VERSION = "0.
|
|
3890
|
+
var VERSION = "0.2.0";
|
|
3028
3891
|
export {
|
|
3029
3892
|
AuthenticationError,
|
|
3030
3893
|
AutoMLClient,
|
|
3031
3894
|
AutoMLModel,
|
|
3032
3895
|
BackupClient,
|
|
3033
3896
|
BatchOperationError,
|
|
3897
|
+
ChatClient,
|
|
3034
3898
|
Collection,
|
|
3035
3899
|
ConnectionError,
|
|
3900
|
+
FilesystemCollectionsClient,
|
|
3901
|
+
GraphClient,
|
|
3036
3902
|
ImportExportClient,
|
|
3037
3903
|
IntegrationClient,
|
|
3904
|
+
McpClient,
|
|
3905
|
+
MultimodalClient,
|
|
3906
|
+
NL2SqlClient,
|
|
3038
3907
|
NLPClient,
|
|
3039
3908
|
NotFoundError,
|
|
3040
3909
|
RateLimitError,
|
|
@@ -3045,8 +3914,11 @@ export {
|
|
|
3045
3914
|
Subscription,
|
|
3046
3915
|
SynapCores,
|
|
3047
3916
|
SynapCoresError,
|
|
3917
|
+
SystemClient,
|
|
3048
3918
|
TimeoutError,
|
|
3049
3919
|
TransactionError,
|
|
3920
|
+
TransactionsClient,
|
|
3921
|
+
Tx,
|
|
3050
3922
|
VERSION,
|
|
3051
3923
|
ValidationError,
|
|
3052
3924
|
VectorError,
|