2
2
3
3
import fs from 'fs' ;
4
4
import path from 'path' ;
5
- import { TrieveSDK , Topic , ChunkMetadata } from 'trieve-ts-sdk' ;
5
+ import {
6
+ TrieveSDK ,
7
+ Topic ,
8
+ ChunkMetadata ,
9
+ UpdateDatasetReqPayload ,
10
+ } from 'trieve-ts-sdk' ;
6
11
import { program } from 'commander' ;
7
12
import chalk from 'chalk' ;
8
13
import inquirer from 'inquirer' ;
@@ -108,6 +113,10 @@ function getConfigOrEnv(key: string, envVar: string): string | undefined {
108
113
function ensureTrieveConfig ( ) {
109
114
const apiKey = getConfigOrEnv ( 'TRIEVE_API_KEY' , 'TRIEVE_API_KEY' ) ;
110
115
const datasetId = getConfigOrEnv ( 'TRIEVE_DATASET_ID' , 'TRIEVE_DATASET_ID' ) ;
116
+ const organizationId = getConfigOrEnv (
117
+ 'TRIEVE_ORGANIZATION_ID' ,
118
+ 'TRIEVE_ORGANIZATION_ID' ,
119
+ ) ;
111
120
112
121
if ( ! apiKey ) {
113
122
console . error (
@@ -125,7 +134,15 @@ function ensureTrieveConfig() {
125
134
console . log ( chalk . cyan ( 'trieve-cli configure' ) ) ;
126
135
process . exit ( 1 ) ;
127
136
}
128
- return { apiKey, datasetId } ;
137
+ if ( ! organizationId ) {
138
+ console . error (
139
+ chalk . red ( 'Error: TRIEVE_ORGANIZATION_ID is not set in env or config.' ) ,
140
+ ) ;
141
+ console . log ( chalk . yellow ( 'Run the following command to set it:' ) ) ;
142
+ console . log ( chalk . cyan ( 'trieve-cli configure' ) ) ;
143
+ process . exit ( 1 ) ;
144
+ }
145
+ return { apiKey, datasetId, organizationId } ;
129
146
}
130
147
131
148
const uploadFile = async (
@@ -217,10 +234,11 @@ async function checkFileUploadStatus(
217
234
groupTrackingId : string ,
218
235
) : Promise < boolean > {
219
236
try {
220
- const { apiKey, datasetId } = ensureTrieveConfig ( ) ;
237
+ const { apiKey, datasetId, organizationId } = ensureTrieveConfig ( ) ;
221
238
const trieveClient : TrieveSDK = new TrieveSDK ( {
222
239
apiKey,
223
240
datasetId,
241
+ organizationId,
224
242
} ) ;
225
243
226
244
const response = await trieveClient . getChunksGroupByTrackingId ( {
@@ -388,7 +406,6 @@ async function askQuestion(question: string): Promise<void> {
388
406
'default-user-' + Math . random ( ) . toString ( 36 ) . substring ( 2 , 15 ) ;
389
407
390
408
const topicData = await trieveClient . createTopic ( {
391
- first_user_message : question ,
392
409
name : topicName ,
393
410
owner_id : ownerId ,
394
411
} ) ;
@@ -411,7 +428,7 @@ async function askQuestion(question: string): Promise<void> {
411
428
let fullResponse = '' ;
412
429
let parsedChunks : ChunkMetadata [ ] = [ ] ;
413
430
let isCollapsed = true ;
414
- let isChunkSection = true ; // Initially assume we're receiving chunks
431
+ let isChunkSection = false ; // Initially assume we're receiving chunks
415
432
let actualAnswer = '' ;
416
433
417
434
// Set up keyboard interaction for collapsible chunks
@@ -425,12 +442,22 @@ async function askQuestion(question: string): Promise<void> {
425
442
key : { name : string ; ctrl ?: boolean ; sequence ?: string } ,
426
443
) => {
427
444
// Handle both key.name and raw sequence for better compatibility
428
- if ( key . name === 'j' || key . sequence === 'j' ) {
445
+ if ( str === 'j' || key . name === 'j' || key . sequence === 'j' ) {
429
446
isCollapsed = ! isCollapsed ;
430
447
// Clear console and redisplay with updated collapse state
431
448
console . clear ( ) ;
432
449
433
450
if ( parsedChunks . length > 0 ) {
451
+ // Show the answer first (if available)
452
+ if ( actualAnswer ) {
453
+ console . log ( actualAnswer ) ;
454
+ }
455
+
456
+ // Add a separator between answer and chunks
457
+ console . log (
458
+ chalk . dim ( '─' . repeat ( 40 ) + ' References ' + '─' . repeat ( 40 ) ) ,
459
+ ) ;
460
+
434
461
if ( isCollapsed ) {
435
462
console . log (
436
463
chalk . cyan (
@@ -440,12 +467,7 @@ async function askQuestion(question: string): Promise<void> {
440
467
} else {
441
468
console . log ( formatChunksCollapsible ( parsedChunks ) ) ;
442
469
}
443
-
444
- // Add a separator between chunks and answer
445
- console . log ( chalk . dim ( '─' . repeat ( 40 ) + ' Answer ' + '─' . repeat ( 40 ) ) ) ;
446
- }
447
-
448
- if ( actualAnswer ) {
470
+ } else if ( actualAnswer ) {
449
471
console . log ( actualAnswer ) ;
450
472
}
451
473
} else if ( key . name === 'c ' && key . ctrl ) {
@@ -475,21 +497,8 @@ async function askQuestion(question: string): Promise<void> {
475
497
if ( chunksJson ) {
476
498
parsedChunks = JSON . parse ( chunksJson ) ;
477
499
478
- // Only show a collapsed summary initially
479
- if ( isCollapsed ) {
480
- console . log (
481
- chalk . cyan (
482
- `📚 Found ${ parsedChunks . length } reference chunks (press 'j' to expand)` ,
483
- ) ,
484
- ) ;
485
- } else {
486
- console . log ( formatChunksCollapsible ( parsedChunks ) ) ;
487
- }
488
-
489
- // Add a separator between chunks and answer
490
- console . log (
491
- chalk . dim ( '─' . repeat ( 40 ) + ' Answer ' + '─' . repeat ( 40 ) ) ,
492
- ) ;
500
+ // Don't display chunks immediately, we'll show them after the answer
501
+ // Just save them for later display
493
502
}
494
503
} catch ( e ) {
495
504
console . error ( chalk . red ( '❌ Error parsing chunks:' ) , e ) ;
@@ -519,11 +528,18 @@ async function askQuestion(question: string): Promise<void> {
519
528
console . log ( chalk . green ( '✅ Response complete' ) ) ;
520
529
521
530
if ( parsedChunks . length > 0 ) {
531
+ // Add a separator between answer and chunks at the end
532
+ console. log ( chalk . dim ( '─' . repeat ( 40 ) + ' References ' + '─' . repeat ( 40 ) ) ) ;
522
533
console . log (
523
534
chalk . blue (
524
535
`📚 ${ parsedChunks . length } reference chunks used (press 'j' to ${ isCollapsed ? 'expand' : 'collapse' } )` ,
525
536
) ,
526
537
) ;
538
+
539
+ // If not collapsed, show the chunks again
540
+ if ( ! isCollapsed ) {
541
+ console . log ( formatChunksCollapsible ( parsedChunks ) ) ;
542
+ }
527
543
}
528
544
529
545
console . log (
@@ -601,6 +617,66 @@ program
601
617
}
602
618
} ) ;
603
619
620
+ // -t "Always use the search tool here when the user asks a question about some information you're supposed to have or some files."
621
+ // -q "Write this as a maximum 5 word query with the keywords you think would be useful"
622
+
623
+ program
624
+ . command ( 'update-tool-config' )
625
+ . description ( 'Update the tool configuration for a dataset' )
626
+ . requiredOption (
627
+ '-t, --tool-description <toolDescription>' ,
628
+ 'Description that tells the LLM when it should use the search tool to retrieve information from your dataset' ,
629
+ "Always use the search tool here when the user asks a question about some information you're supposed to have or some files." ,
630
+ )
631
+ . requiredOption (
632
+ '-q, --query-description <queryDescription>' ,
633
+ 'Description of how the LLM should write its search queries to retrieve relevant information from your dataset' ,
634
+ 'Write this as a maximum 5 word query with the keywords you think would be useful' ,
635
+ )
636
+ . action ( async ( options ) => {
637
+ try {
638
+ console . log ( chalk . blue ( '🔧 Updating tool configuration...' ) ) ;
639
+
640
+ const { apiKey, datasetId, organizationId } = ensureTrieveConfig ( ) ;
641
+
642
+ // Initialize SDK with apiKey and datasetId from config
643
+ const trieveClient : TrieveSDK = new TrieveSDK ( {
644
+ apiKey,
645
+ datasetId,
646
+ organizationId,
647
+ } ) ;
648
+
649
+ const updatePayload : UpdateDatasetReqPayload = {
650
+ dataset_id : datasetId ,
651
+ server_configuration : {
652
+ TOOL_CONFIGURATION : {
653
+ query_tool_options : {
654
+ tool_description : options . toolDescription ,
655
+ query_parameter_description : options . queryDescription ,
656
+ price_filter_description :
657
+ 'The price or page range filter to use for the search' ,
658
+
659
+ max_price_option_description :
660
+ 'The maximum price or page to filter by' ,
661
+
662
+ min_price_option_description :
663
+ 'The minimum price or page to filter by' ,
664
+ } ,
665
+ } ,
666
+ } ,
667
+ } ;
668
+
669
+ await trieveClient . updateDataset ( updatePayload ) ;
670
+
671
+ console . log ( chalk . green ( '✅ Tool configuration updated successfully!' ) ) ;
672
+ } catch ( error ) {
673
+ console . error (
674
+ chalk . red ( '❌ Failed to update tool configuration:' ) ,
675
+ error instanceof Error ? error . message : error ,
676
+ ) ;
677
+ }
678
+ } ) ;
679
+
604
680
program
605
681
. command ( 'configure' )
606
682
. description ( 'Set up or update your Trieve CLI configuration' )
@@ -618,6 +694,12 @@ program
618
694
message : 'Enter your TRIEVE_DATASET_ID:' ,
619
695
default : ( config . get ( 'TRIEVE_DATASET_ID' ) as string ) || '' ,
620
696
} ,
697
+ {
698
+ type : 'input' ,
699
+ name : 'TRIEVE_ORGANIZATION_ID' ,
700
+ message : 'Enter your TRIEVE_ORGANIZATION_ID:' ,
701
+ default : ( config . get ( 'TRIEVE_ORGANIZATION_ID' ) as string ) || '' ,
702
+ } ,
621
703
{
622
704
type : 'input' ,
623
705
name : 'userId' ,
@@ -627,6 +709,7 @@ program
627
709
] ) ;
628
710
config . set ( 'TRIEVE_API_KEY' , answers . TRIEVE_API_KEY ) ;
629
711
config . set ( 'TRIEVE_DATASET_ID' , answers . TRIEVE_DATASET_ID ) ;
712
+ config . set ( 'TRIEVE_ORGANIZATION_ID' , answers . TRIEVE_ORGANIZATION_ID ) ;
630
713
config . set ( 'userId' , answers . userId ) ;
631
714
console . log ( chalk . green ( '✅ Configuration saved!' ) ) ;
632
715
} ) ;
@@ -685,6 +768,7 @@ ${chalk.yellow('Examples:')}
685
768
$ ${ chalk . green ( 'trieve-cli check-upload-status --tracking-id <tracking-id>' ) }
686
769
$ ${ chalk . green ( 'trieve-cli ask "What is the capital of France?"' ) }
687
770
$ ${ chalk . green ( 'trieve-cli ask' ) }
771
+ $ ${ chalk . green ( 'trieve-cli update-tool-config -t "Use this tool to search for information about our products and services" -q "Write specific search queries to find relevant information from our knowledge base"' ) }
688
772
` ,
689
773
) ;
690
774
0 commit comments