valyu-js 2.1.7 → 2.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +110 -0
- package/dist/index.d.mts +264 -7
- package/dist/index.d.ts +264 -7
- package/dist/index.js +474 -132
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +474 -132
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -47,6 +47,17 @@ var Valyu = class {
|
|
|
47
47
|
"Content-Type": "application/json",
|
|
48
48
|
"x-api-key": apiKey
|
|
49
49
|
};
|
|
50
|
+
this.deepresearch = {
|
|
51
|
+
create: this._deepresearchCreate.bind(this),
|
|
52
|
+
status: this._deepresearchStatus.bind(this),
|
|
53
|
+
wait: this._deepresearchWait.bind(this),
|
|
54
|
+
stream: this._deepresearchStream.bind(this),
|
|
55
|
+
list: this._deepresearchList.bind(this),
|
|
56
|
+
update: this._deepresearchUpdate.bind(this),
|
|
57
|
+
cancel: this._deepresearchCancel.bind(this),
|
|
58
|
+
delete: this._deepresearchDelete.bind(this),
|
|
59
|
+
togglePublic: this._deepresearchTogglePublic.bind(this)
|
|
60
|
+
};
|
|
50
61
|
}
|
|
51
62
|
/**
|
|
52
63
|
* Validates date format (YYYY-MM-DD)
|
|
@@ -466,177 +477,508 @@ var Valyu = class {
|
|
|
466
477
|
}
|
|
467
478
|
}
|
|
468
479
|
/**
|
|
469
|
-
*
|
|
470
|
-
* @param query - The question or query string
|
|
471
|
-
* @param options - Answer configuration options
|
|
472
|
-
* @param options.structuredOutput - JSON Schema object for structured responses
|
|
473
|
-
* @param options.systemInstructions - Custom system-level instructions (max 2000 chars)
|
|
474
|
-
* @param options.searchType - Type of search: "web", "proprietary", "all", or "news"
|
|
475
|
-
* @param options.dataMaxPrice - Maximum spend (USD) for data retrieval
|
|
476
|
-
* @param options.countryCode - Country code filter for search results
|
|
477
|
-
* @param options.includedSources - List of specific sources to include
|
|
478
|
-
* @param options.excludedSources - List of URLs/domains to exclude from search results
|
|
479
|
-
* @param options.startDate - Start date filter (YYYY-MM-DD format)
|
|
480
|
-
* @param options.endDate - End date filter (YYYY-MM-DD format)
|
|
481
|
-
* @param options.fastMode - Fast mode for quicker but shorter results (default: false)
|
|
482
|
-
* @returns Promise resolving to answer response
|
|
480
|
+
* DeepResearch: Create a new research task
|
|
483
481
|
*/
|
|
484
|
-
async
|
|
482
|
+
async _deepresearchCreate(options) {
|
|
485
483
|
try {
|
|
486
|
-
|
|
487
|
-
if (!query || typeof query !== "string" || query.trim().length === 0) {
|
|
484
|
+
if (!options.input?.trim()) {
|
|
488
485
|
return {
|
|
489
486
|
success: false,
|
|
490
|
-
error: "
|
|
487
|
+
error: "input is required and cannot be empty"
|
|
491
488
|
};
|
|
492
489
|
}
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
490
|
+
const payload = {
|
|
491
|
+
input: options.input,
|
|
492
|
+
model: options.model || "lite",
|
|
493
|
+
output_formats: options.outputFormats || ["markdown"],
|
|
494
|
+
code_execution: options.codeExecution !== false
|
|
495
|
+
};
|
|
496
|
+
if (options.strategy) payload.strategy = options.strategy;
|
|
497
|
+
if (options.search) {
|
|
498
|
+
payload.search = {
|
|
499
|
+
search_type: options.search.searchType,
|
|
500
|
+
included_sources: options.search.includedSources
|
|
501
501
|
};
|
|
502
502
|
}
|
|
503
|
-
if (options.
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
503
|
+
if (options.urls) payload.urls = options.urls;
|
|
504
|
+
if (options.files) payload.files = options.files;
|
|
505
|
+
if (options.mcpServers) payload.mcp_servers = options.mcpServers;
|
|
506
|
+
if (options.previousReports) {
|
|
507
|
+
payload.previous_reports = options.previousReports;
|
|
508
|
+
}
|
|
509
|
+
if (options.webhookUrl) payload.webhook_url = options.webhookUrl;
|
|
510
|
+
if (options.metadata) payload.metadata = options.metadata;
|
|
511
|
+
const response = await import_axios.default.post(
|
|
512
|
+
`${this.baseUrl}/deepresearch/tasks`,
|
|
513
|
+
payload,
|
|
514
|
+
{ headers: this.headers }
|
|
515
|
+
);
|
|
516
|
+
return { success: true, ...response.data };
|
|
517
|
+
} catch (e) {
|
|
518
|
+
return {
|
|
519
|
+
success: false,
|
|
520
|
+
error: e.response?.data?.error || e.message
|
|
521
|
+
};
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
/**
|
|
525
|
+
* DeepResearch: Get task status
|
|
526
|
+
*/
|
|
527
|
+
async _deepresearchStatus(taskId) {
|
|
528
|
+
try {
|
|
529
|
+
const response = await import_axios.default.get(
|
|
530
|
+
`${this.baseUrl}/deepresearch/tasks/${taskId}/status`,
|
|
531
|
+
{ headers: this.headers }
|
|
532
|
+
);
|
|
533
|
+
return { success: true, ...response.data };
|
|
534
|
+
} catch (e) {
|
|
535
|
+
return {
|
|
536
|
+
success: false,
|
|
537
|
+
error: e.response?.data?.error || e.message
|
|
538
|
+
};
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
/**
|
|
542
|
+
* DeepResearch: Wait for task completion with polling
|
|
543
|
+
*/
|
|
544
|
+
async _deepresearchWait(taskId, options = {}) {
|
|
545
|
+
const pollInterval = options.pollInterval || 5e3;
|
|
546
|
+
const maxWaitTime = options.maxWaitTime || 36e5;
|
|
547
|
+
const startTime = Date.now();
|
|
548
|
+
while (true) {
|
|
549
|
+
const status = await this._deepresearchStatus(taskId);
|
|
550
|
+
if (!status.success) {
|
|
551
|
+
throw new Error(status.error);
|
|
523
552
|
}
|
|
524
|
-
if (options.
|
|
525
|
-
|
|
526
|
-
return {
|
|
527
|
-
success: false,
|
|
528
|
-
error: "dataMaxPrice must be a positive number"
|
|
529
|
-
};
|
|
530
|
-
}
|
|
553
|
+
if (options.onProgress) {
|
|
554
|
+
options.onProgress(status);
|
|
531
555
|
}
|
|
532
|
-
if (
|
|
533
|
-
return
|
|
534
|
-
success: false,
|
|
535
|
-
error: "Invalid startDate format. Must be YYYY-MM-DD"
|
|
536
|
-
};
|
|
556
|
+
if (status.status === "completed" || status.status === "failed" || status.status === "cancelled") {
|
|
557
|
+
return status;
|
|
537
558
|
}
|
|
538
|
-
if (
|
|
539
|
-
|
|
540
|
-
success: false,
|
|
541
|
-
error: "Invalid endDate format. Must be YYYY-MM-DD"
|
|
542
|
-
};
|
|
559
|
+
if (Date.now() - startTime > maxWaitTime) {
|
|
560
|
+
throw new Error("Maximum wait time exceeded");
|
|
543
561
|
}
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
562
|
+
await new Promise((resolve) => setTimeout(resolve, pollInterval));
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
/**
|
|
566
|
+
* DeepResearch: Stream real-time updates
|
|
567
|
+
*/
|
|
568
|
+
async _deepresearchStream(taskId, callback) {
|
|
569
|
+
let isComplete = false;
|
|
570
|
+
let lastMessageCount = 0;
|
|
571
|
+
while (!isComplete) {
|
|
572
|
+
try {
|
|
573
|
+
const status = await this._deepresearchStatus(taskId);
|
|
574
|
+
if (!status.success) {
|
|
575
|
+
if (callback.onError) {
|
|
576
|
+
callback.onError(new Error(status.error));
|
|
577
|
+
}
|
|
578
|
+
return;
|
|
552
579
|
}
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
error: "includedSources must be an array"
|
|
559
|
-
};
|
|
580
|
+
if (status.progress && callback.onProgress) {
|
|
581
|
+
callback.onProgress(
|
|
582
|
+
status.progress.current_step,
|
|
583
|
+
status.progress.total_steps
|
|
584
|
+
);
|
|
560
585
|
}
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
return {
|
|
566
|
-
success: false,
|
|
567
|
-
error: `Invalid includedSources format. Invalid sources: ${includedSourcesValidation.invalidSources.join(
|
|
568
|
-
", "
|
|
569
|
-
)}. Sources must be valid URLs, domains (with optional paths), or dataset identifiers in 'provider/dataset' format.`
|
|
570
|
-
};
|
|
586
|
+
if (status.messages && callback.onMessage) {
|
|
587
|
+
const newMessages = status.messages.slice(lastMessageCount);
|
|
588
|
+
newMessages.forEach((msg) => callback.onMessage(msg));
|
|
589
|
+
lastMessageCount = status.messages.length;
|
|
571
590
|
}
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
591
|
+
if (status.status === "completed") {
|
|
592
|
+
if (callback.onComplete) {
|
|
593
|
+
callback.onComplete(status);
|
|
594
|
+
}
|
|
595
|
+
isComplete = true;
|
|
596
|
+
} else if (status.status === "failed" || status.status === "cancelled") {
|
|
597
|
+
if (callback.onError) {
|
|
598
|
+
callback.onError(
|
|
599
|
+
new Error(status.error || `Task ${status.status}`)
|
|
600
|
+
);
|
|
601
|
+
}
|
|
602
|
+
isComplete = true;
|
|
579
603
|
}
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
error: `Invalid excludedSources format. Invalid sources: ${excludedSourcesValidation.invalidSources.join(
|
|
587
|
-
", "
|
|
588
|
-
)}. Sources must be valid URLs, domains (with optional paths), or dataset identifiers in 'provider/dataset' format.`
|
|
589
|
-
};
|
|
604
|
+
if (!isComplete) {
|
|
605
|
+
await new Promise((resolve) => setTimeout(resolve, 5e3));
|
|
606
|
+
}
|
|
607
|
+
} catch (error) {
|
|
608
|
+
if (callback.onError) {
|
|
609
|
+
callback.onError(error);
|
|
590
610
|
}
|
|
611
|
+
throw error;
|
|
591
612
|
}
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
/**
|
|
616
|
+
* DeepResearch: List all tasks
|
|
617
|
+
*/
|
|
618
|
+
async _deepresearchList(options) {
|
|
619
|
+
try {
|
|
620
|
+
const limit = options.limit || 10;
|
|
621
|
+
const response = await import_axios.default.get(
|
|
622
|
+
`${this.baseUrl}/deepresearch/listtasks?api_key_id=${options.apiKeyId}&limit=${limit}`,
|
|
623
|
+
{ headers: this.headers }
|
|
624
|
+
);
|
|
625
|
+
return { success: true, data: response.data };
|
|
626
|
+
} catch (e) {
|
|
627
|
+
return {
|
|
628
|
+
success: false,
|
|
629
|
+
error: e.response?.data?.error || e.message
|
|
630
|
+
};
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
/**
|
|
634
|
+
* DeepResearch: Add follow-up instruction
|
|
635
|
+
*/
|
|
636
|
+
async _deepresearchUpdate(taskId, instruction) {
|
|
637
|
+
try {
|
|
638
|
+
if (!instruction?.trim()) {
|
|
639
|
+
return {
|
|
640
|
+
success: false,
|
|
641
|
+
error: "instruction is required and cannot be empty"
|
|
642
|
+
};
|
|
643
|
+
}
|
|
644
|
+
const response = await import_axios.default.post(
|
|
645
|
+
`${this.baseUrl}/deepresearch/tasks/${taskId}/update`,
|
|
646
|
+
{ instruction },
|
|
647
|
+
{ headers: this.headers }
|
|
648
|
+
);
|
|
649
|
+
return { success: true, ...response.data };
|
|
650
|
+
} catch (e) {
|
|
651
|
+
return {
|
|
652
|
+
success: false,
|
|
653
|
+
error: e.response?.data?.error || e.message
|
|
654
|
+
};
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
/**
|
|
658
|
+
* DeepResearch: Cancel task
|
|
659
|
+
*/
|
|
660
|
+
async _deepresearchCancel(taskId) {
|
|
661
|
+
try {
|
|
662
|
+
const response = await import_axios.default.post(
|
|
663
|
+
`${this.baseUrl}/deepresearch/tasks/${taskId}/cancel`,
|
|
664
|
+
{},
|
|
665
|
+
{ headers: this.headers }
|
|
666
|
+
);
|
|
667
|
+
return { success: true, ...response.data };
|
|
668
|
+
} catch (e) {
|
|
669
|
+
return {
|
|
670
|
+
success: false,
|
|
671
|
+
error: e.response?.data?.error || e.message
|
|
672
|
+
};
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
/**
|
|
676
|
+
* DeepResearch: Delete task
|
|
677
|
+
*/
|
|
678
|
+
async _deepresearchDelete(taskId) {
|
|
679
|
+
try {
|
|
680
|
+
const response = await import_axios.default.delete(
|
|
681
|
+
`${this.baseUrl}/deepresearch/tasks/${taskId}/delete`,
|
|
682
|
+
{ headers: this.headers }
|
|
683
|
+
);
|
|
684
|
+
return { success: true, ...response.data };
|
|
685
|
+
} catch (e) {
|
|
686
|
+
return {
|
|
687
|
+
success: false,
|
|
688
|
+
error: e.response?.data?.error || e.message
|
|
595
689
|
};
|
|
596
|
-
|
|
597
|
-
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
/**
|
|
693
|
+
* DeepResearch: Toggle public flag
|
|
694
|
+
*/
|
|
695
|
+
async _deepresearchTogglePublic(taskId, isPublic) {
|
|
696
|
+
try {
|
|
697
|
+
const response = await import_axios.default.post(
|
|
698
|
+
`${this.baseUrl}/deepresearch/tasks/${taskId}/public`,
|
|
699
|
+
{ public: isPublic },
|
|
700
|
+
{ headers: this.headers }
|
|
701
|
+
);
|
|
702
|
+
return { success: true, ...response.data };
|
|
703
|
+
} catch (e) {
|
|
704
|
+
return {
|
|
705
|
+
success: false,
|
|
706
|
+
error: e.response?.data?.error || e.message
|
|
707
|
+
};
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
/**
|
|
711
|
+
* Get AI-powered answers using the Valyu Answer API
|
|
712
|
+
* @param query - The question or query string
|
|
713
|
+
* @param options - Answer configuration options
|
|
714
|
+
* @param options.structuredOutput - JSON Schema object for structured responses
|
|
715
|
+
* @param options.systemInstructions - Custom system-level instructions (max 2000 chars)
|
|
716
|
+
* @param options.searchType - Type of search: "web", "proprietary", "all", or "news"
|
|
717
|
+
* @param options.dataMaxPrice - Maximum spend (USD) for data retrieval
|
|
718
|
+
* @param options.countryCode - Country code filter for search results
|
|
719
|
+
* @param options.includedSources - List of specific sources to include
|
|
720
|
+
* @param options.excludedSources - List of URLs/domains to exclude from search results
|
|
721
|
+
* @param options.startDate - Start date filter (YYYY-MM-DD format)
|
|
722
|
+
* @param options.endDate - End date filter (YYYY-MM-DD format)
|
|
723
|
+
* @param options.fastMode - Fast mode for quicker but shorter results (default: false)
|
|
724
|
+
* @param options.streaming - Enable streaming mode (default: false)
|
|
725
|
+
* @returns Promise resolving to answer response, or AsyncGenerator for streaming
|
|
726
|
+
*/
|
|
727
|
+
async answer(query, options = {}) {
|
|
728
|
+
const validationError = this.validateAnswerParams(query, options);
|
|
729
|
+
if (validationError) {
|
|
730
|
+
if (options.streaming) {
|
|
731
|
+
return this.createErrorGenerator(validationError);
|
|
598
732
|
}
|
|
599
|
-
|
|
600
|
-
|
|
733
|
+
return { success: false, error: validationError };
|
|
734
|
+
}
|
|
735
|
+
const payload = this.buildAnswerPayload(query, options);
|
|
736
|
+
if (options.streaming) {
|
|
737
|
+
return this.streamAnswer(payload);
|
|
738
|
+
} else {
|
|
739
|
+
return this.fetchAnswer(payload);
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
/**
|
|
743
|
+
* Validate answer parameters
|
|
744
|
+
*/
|
|
745
|
+
validateAnswerParams(query, options) {
|
|
746
|
+
if (!query || typeof query !== "string" || query.trim().length === 0) {
|
|
747
|
+
return "Query is required and must be a non-empty string";
|
|
748
|
+
}
|
|
749
|
+
const providedSearchTypeString = options.searchType?.toLowerCase();
|
|
750
|
+
if (providedSearchTypeString !== void 0 && providedSearchTypeString !== "web" && providedSearchTypeString !== "proprietary" && providedSearchTypeString !== "all" && providedSearchTypeString !== "news") {
|
|
751
|
+
return "Invalid searchType provided. Must be one of: all, web, proprietary, news";
|
|
752
|
+
}
|
|
753
|
+
if (options.systemInstructions !== void 0) {
|
|
754
|
+
if (typeof options.systemInstructions !== "string") {
|
|
755
|
+
return "systemInstructions must be a string";
|
|
601
756
|
}
|
|
602
|
-
|
|
603
|
-
|
|
757
|
+
const trimmed = options.systemInstructions.trim();
|
|
758
|
+
if (trimmed.length === 0) {
|
|
759
|
+
return "systemInstructions cannot be empty when provided";
|
|
604
760
|
}
|
|
605
|
-
if (
|
|
606
|
-
|
|
761
|
+
if (trimmed.length > 2e3) {
|
|
762
|
+
return "systemInstructions must be 2000 characters or less";
|
|
607
763
|
}
|
|
608
|
-
|
|
609
|
-
|
|
764
|
+
}
|
|
765
|
+
if (options.dataMaxPrice !== void 0) {
|
|
766
|
+
if (typeof options.dataMaxPrice !== "number" || options.dataMaxPrice <= 0) {
|
|
767
|
+
return "dataMaxPrice must be a positive number";
|
|
610
768
|
}
|
|
611
|
-
|
|
612
|
-
|
|
769
|
+
}
|
|
770
|
+
if (options.startDate && !this.validateDateFormat(options.startDate)) {
|
|
771
|
+
return "Invalid startDate format. Must be YYYY-MM-DD";
|
|
772
|
+
}
|
|
773
|
+
if (options.endDate && !this.validateDateFormat(options.endDate)) {
|
|
774
|
+
return "Invalid endDate format. Must be YYYY-MM-DD";
|
|
775
|
+
}
|
|
776
|
+
if (options.startDate && options.endDate) {
|
|
777
|
+
const startDate = new Date(options.startDate);
|
|
778
|
+
const endDate = new Date(options.endDate);
|
|
779
|
+
if (startDate > endDate) {
|
|
780
|
+
return "startDate must be before endDate";
|
|
613
781
|
}
|
|
614
|
-
|
|
615
|
-
|
|
782
|
+
}
|
|
783
|
+
if (options.includedSources !== void 0) {
|
|
784
|
+
if (!Array.isArray(options.includedSources)) {
|
|
785
|
+
return "includedSources must be an array";
|
|
616
786
|
}
|
|
617
|
-
|
|
618
|
-
|
|
787
|
+
const validation = this.validateSources(options.includedSources);
|
|
788
|
+
if (!validation.valid) {
|
|
789
|
+
return `Invalid includedSources format. Invalid sources: ${validation.invalidSources.join(", ")}.`;
|
|
619
790
|
}
|
|
620
|
-
|
|
621
|
-
|
|
791
|
+
}
|
|
792
|
+
if (options.excludedSources !== void 0) {
|
|
793
|
+
if (!Array.isArray(options.excludedSources)) {
|
|
794
|
+
return "excludedSources must be an array";
|
|
622
795
|
}
|
|
623
|
-
const
|
|
624
|
-
|
|
796
|
+
const validation = this.validateSources(options.excludedSources);
|
|
797
|
+
if (!validation.valid) {
|
|
798
|
+
return `Invalid excludedSources format. Invalid sources: ${validation.invalidSources.join(", ")}.`;
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
return null;
|
|
802
|
+
}
|
|
803
|
+
/**
|
|
804
|
+
* Build payload for answer API
|
|
805
|
+
*/
|
|
806
|
+
buildAnswerPayload(query, options) {
|
|
807
|
+
const defaultSearchType = "all";
|
|
808
|
+
const providedSearchTypeString = options.searchType?.toLowerCase();
|
|
809
|
+
let finalSearchType = defaultSearchType;
|
|
810
|
+
if (providedSearchTypeString === "web" || providedSearchTypeString === "proprietary" || providedSearchTypeString === "all" || providedSearchTypeString === "news") {
|
|
811
|
+
finalSearchType = providedSearchTypeString;
|
|
812
|
+
}
|
|
813
|
+
const payload = {
|
|
814
|
+
query: query.trim(),
|
|
815
|
+
search_type: finalSearchType
|
|
816
|
+
};
|
|
817
|
+
if (options.dataMaxPrice !== void 0) payload.data_max_price = options.dataMaxPrice;
|
|
818
|
+
if (options.structuredOutput !== void 0) payload.structured_output = options.structuredOutput;
|
|
819
|
+
if (options.systemInstructions !== void 0) payload.system_instructions = options.systemInstructions.trim();
|
|
820
|
+
if (options.countryCode !== void 0) payload.country_code = options.countryCode;
|
|
821
|
+
if (options.includedSources !== void 0) payload.included_sources = options.includedSources;
|
|
822
|
+
if (options.excludedSources !== void 0) payload.excluded_sources = options.excludedSources;
|
|
823
|
+
if (options.startDate !== void 0) payload.start_date = options.startDate;
|
|
824
|
+
if (options.endDate !== void 0) payload.end_date = options.endDate;
|
|
825
|
+
if (options.fastMode !== void 0) payload.fast_mode = options.fastMode;
|
|
826
|
+
return payload;
|
|
827
|
+
}
|
|
828
|
+
/**
|
|
829
|
+
* Fetch answer (non-streaming mode)
|
|
830
|
+
*/
|
|
831
|
+
async fetchAnswer(payload) {
|
|
832
|
+
try {
|
|
833
|
+
const response = await fetch(`${this.baseUrl}/answer`, {
|
|
834
|
+
method: "POST",
|
|
835
|
+
headers: {
|
|
836
|
+
...this.headers,
|
|
837
|
+
"Accept": "text/event-stream"
|
|
838
|
+
},
|
|
839
|
+
body: JSON.stringify(payload)
|
|
625
840
|
});
|
|
626
|
-
if (!response.
|
|
841
|
+
if (!response.ok) {
|
|
842
|
+
const errorData = await response.json().catch(() => ({}));
|
|
627
843
|
return {
|
|
628
844
|
success: false,
|
|
629
|
-
error:
|
|
845
|
+
error: errorData.error || `HTTP Error: ${response.status}`
|
|
630
846
|
};
|
|
631
847
|
}
|
|
632
|
-
|
|
848
|
+
let fullContent = "";
|
|
849
|
+
let searchResults = [];
|
|
850
|
+
let finalMetadata = {};
|
|
851
|
+
const reader = response.body?.getReader();
|
|
852
|
+
const decoder = new TextDecoder();
|
|
853
|
+
let buffer = "";
|
|
854
|
+
if (reader) {
|
|
855
|
+
while (true) {
|
|
856
|
+
const { done, value } = await reader.read();
|
|
857
|
+
if (done) break;
|
|
858
|
+
buffer += decoder.decode(value, { stream: true });
|
|
859
|
+
const lines = buffer.split("\n");
|
|
860
|
+
buffer = lines.pop() || "";
|
|
861
|
+
for (const line of lines) {
|
|
862
|
+
if (!line.startsWith("data: ")) continue;
|
|
863
|
+
const dataStr = line.slice(6);
|
|
864
|
+
if (dataStr === "[DONE]") continue;
|
|
865
|
+
try {
|
|
866
|
+
const parsed = JSON.parse(dataStr);
|
|
867
|
+
if (parsed.search_results && !parsed.success) {
|
|
868
|
+
searchResults = [...searchResults, ...parsed.search_results];
|
|
869
|
+
} else if (parsed.choices) {
|
|
870
|
+
const content = parsed.choices[0]?.delta?.content || "";
|
|
871
|
+
if (content) fullContent += content;
|
|
872
|
+
} else if (parsed.success !== void 0) {
|
|
873
|
+
finalMetadata = parsed;
|
|
874
|
+
}
|
|
875
|
+
} catch {
|
|
876
|
+
continue;
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
if (finalMetadata.success) {
|
|
882
|
+
const finalSearchResults = finalMetadata.search_results || searchResults;
|
|
883
|
+
return {
|
|
884
|
+
success: true,
|
|
885
|
+
ai_tx_id: finalMetadata.ai_tx_id || "",
|
|
886
|
+
original_query: finalMetadata.original_query || payload.query,
|
|
887
|
+
contents: fullContent || finalMetadata.contents || "",
|
|
888
|
+
data_type: finalMetadata.data_type || "unstructured",
|
|
889
|
+
search_results: finalSearchResults,
|
|
890
|
+
search_metadata: finalMetadata.search_metadata || { tx_ids: [], number_of_results: 0, total_characters: 0 },
|
|
891
|
+
ai_usage: finalMetadata.ai_usage || { input_tokens: 0, output_tokens: 0 },
|
|
892
|
+
cost: finalMetadata.cost || { total_deduction_dollars: 0, search_deduction_dollars: 0, ai_deduction_dollars: 0 }
|
|
893
|
+
};
|
|
894
|
+
}
|
|
895
|
+
return {
|
|
896
|
+
success: false,
|
|
897
|
+
error: finalMetadata.error || "Unknown error occurred"
|
|
898
|
+
};
|
|
633
899
|
} catch (e) {
|
|
634
900
|
return {
|
|
635
901
|
success: false,
|
|
636
|
-
error: e.
|
|
902
|
+
error: e.message || "Request failed"
|
|
637
903
|
};
|
|
638
904
|
}
|
|
639
905
|
}
|
|
906
|
+
/**
|
|
907
|
+
* Stream answer using SSE
|
|
908
|
+
*/
|
|
909
|
+
async *streamAnswer(payload) {
|
|
910
|
+
try {
|
|
911
|
+
const response = await fetch(`${this.baseUrl}/answer`, {
|
|
912
|
+
method: "POST",
|
|
913
|
+
headers: {
|
|
914
|
+
...this.headers,
|
|
915
|
+
"Accept": "text/event-stream"
|
|
916
|
+
},
|
|
917
|
+
body: JSON.stringify(payload)
|
|
918
|
+
});
|
|
919
|
+
if (!response.ok) {
|
|
920
|
+
const errorData = await response.json().catch(() => ({}));
|
|
921
|
+
yield { type: "error", error: errorData.error || `HTTP Error: ${response.status}` };
|
|
922
|
+
return;
|
|
923
|
+
}
|
|
924
|
+
const reader = response.body?.getReader();
|
|
925
|
+
const decoder = new TextDecoder();
|
|
926
|
+
let buffer = "";
|
|
927
|
+
if (!reader) {
|
|
928
|
+
yield { type: "error", error: "No response body" };
|
|
929
|
+
return;
|
|
930
|
+
}
|
|
931
|
+
while (true) {
|
|
932
|
+
const { done, value } = await reader.read();
|
|
933
|
+
if (done) break;
|
|
934
|
+
buffer += decoder.decode(value, { stream: true });
|
|
935
|
+
const lines = buffer.split("\n");
|
|
936
|
+
buffer = lines.pop() || "";
|
|
937
|
+
for (const line of lines) {
|
|
938
|
+
if (!line.startsWith("data: ")) continue;
|
|
939
|
+
const dataStr = line.slice(6);
|
|
940
|
+
if (dataStr === "[DONE]") {
|
|
941
|
+
yield { type: "done" };
|
|
942
|
+
continue;
|
|
943
|
+
}
|
|
944
|
+
try {
|
|
945
|
+
const parsed = JSON.parse(dataStr);
|
|
946
|
+
if (parsed.search_results && parsed.success === void 0) {
|
|
947
|
+
yield { type: "search_results", search_results: parsed.search_results };
|
|
948
|
+
} else if (parsed.choices) {
|
|
949
|
+
const delta = parsed.choices[0]?.delta || {};
|
|
950
|
+
const content = delta.content || "";
|
|
951
|
+
const finishReason = parsed.choices[0]?.finish_reason;
|
|
952
|
+
if (content || finishReason) {
|
|
953
|
+
yield { type: "content", content, finish_reason: finishReason };
|
|
954
|
+
}
|
|
955
|
+
} else if (parsed.success !== void 0) {
|
|
956
|
+
yield {
|
|
957
|
+
type: "metadata",
|
|
958
|
+
ai_tx_id: parsed.ai_tx_id,
|
|
959
|
+
original_query: parsed.original_query,
|
|
960
|
+
data_type: parsed.data_type,
|
|
961
|
+
search_results: parsed.search_results,
|
|
962
|
+
search_metadata: parsed.search_metadata,
|
|
963
|
+
ai_usage: parsed.ai_usage,
|
|
964
|
+
cost: parsed.cost
|
|
965
|
+
};
|
|
966
|
+
}
|
|
967
|
+
} catch {
|
|
968
|
+
continue;
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
}
|
|
972
|
+
} catch (e) {
|
|
973
|
+
yield { type: "error", error: e.message || "Stream failed" };
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
/**
|
|
977
|
+
* Create an error generator for streaming errors
|
|
978
|
+
*/
|
|
979
|
+
async *createErrorGenerator(error) {
|
|
980
|
+
yield { type: "error", error };
|
|
981
|
+
}
|
|
640
982
|
};
|
|
641
983
|
// Annotate the CommonJS export names for ESM import in node:
|
|
642
984
|
0 && (module.exports = {
|