@skald-labs/skald-node
v0.4.0
Published
Node.js client library for the Skald API
Readme
Skald Node SDK
Node.js client library for the Skald API.
Please note that Skald is evolving fast and we may ship breaking changes across minor versions.
Installation
npm install @skald-labs/skald-nodeRequirements
- Node 18.0.0 or higher
Usage
Initialize the client
import { Skald } from '@skald-labs/skald-node';
const skald = new Skald('your-api-key-here');Memo Management
Create a Memo
Create a new memo that will be automatically processed (summarized, tagged, chunked, and indexed for search):
const result = await skald.createMemo({
title: 'Meeting Notes',
content: 'Full content of the memo...',
metadata: {
type: 'notes',
author: 'John Doe'
},
reference_id: 'external-id-123',
tags: ['meeting', 'q1'],
source: 'notion',
expiration_date: '2024-12-31T23:59:59Z'
});
console.log(result); // { memo_uuid: '550e8400-e29b-41d4-a716-446655440000' }Required Fields:
title(string, max 255 chars) - The title of the memocontent(string) - The full content of the memo
Optional Fields:
project_id(string) - Project UUID (required when using Token Authentication)metadata(object) - Custom JSON metadatareference_id(string, max 255 chars) - An ID from your side that you can use to match Skald memo UUIDs with e.g. documents on your endtags(array of strings) - Tags for categorizationsource(string, max 255 chars) - An indication from your side of the source of this content, useful when building integrationsexpiration_date(string) - ISO 8601 timestamp for automatic memo expiration
Create a Memo from File Upload
Upload a document file (PDF, DOC, DOCX, PPTX) that will be processed asynchronously and converted into a memo:
import * as fs from 'fs';
const fileBuffer = fs.readFileSync('./document.pdf');
const result = await skald.createMemoFromFile({
file: fileBuffer,
filename: 'document.pdf',
metadata: {
type: 'report',
department: 'engineering'
},
tags: ['report', '2024'],
source: 'google-drive',
reference_id: 'external-file-123'
});
console.log(result); // { ok: true, memo_uuid: '550e8400-e29b-41d4-a716-446655440000' }
// Poll for processing status
const status = await skald.checkMemoStatus({ memoId: result.memo_uuid });
console.log(status.status); // 'processing' | 'processed' | 'error'Supported File Types:
- PDF (.pdf)
- Microsoft Word (.doc, .docx)
- Microsoft PowerPoint (.pptx)
- Maximum file size: 100MB
Required Fields:
file(Buffer | Blob) - The file contentfilename(string) - The name of the file including extension
Optional Fields:
reference_id(string, max 255 chars) - Your external reference IDmetadata(object) - Custom JSON metadatatags(array of strings) - Tags for categorizationsource(string, max 255 chars) - Source system identifier
Note: File processing is asynchronous. Use checkMemoStatus() to monitor the processing status.
Check Memo Processing Status
Monitor the processing status of a memo, especially useful after uploading files:
// Check status by UUID
const status = await skald.checkMemoStatus({ memoId: '550e8400-e29b-41d4-a716-446655440000' });
console.log(status.status); // 'processing' | 'processed' | 'error'
if (status.status === 'error') {
console.error('Processing failed:', status.error_reason);
}
// Check by reference ID
const status2 = await skald.checkMemoStatus({ memoId: 'external-id-123', idType: 'reference_id' });
// Poll until processing completes
while (true) {
const status = await skald.checkMemoStatus({ memoId: memoUuid });
if (status.status === 'processed') {
console.log('Processing complete!');
break;
} else if (status.status === 'error') {
console.error('Processing failed:', status.error_reason);
break;
}
// Wait 2 seconds before checking again
await new Promise(resolve => setTimeout(resolve, 2000));
}Status Values:
processing- The memo is currently being processed (parsed, summarized, chunked, indexed)processed- Processing completed successfully, memo is ready to useerror- An error occurred during processing, checkerror_reasonfor details
Parameters: Takes a request object with the following properties:
memoId(string, required) - The memo UUID or client reference IDidType(string, optional) - Either'memo_uuid'or'reference_id'(default:'memo_uuid')
Get a Memo
Retrieve a memo by its UUID or your reference ID:
// Get by UUID
const memo = await skald.getMemo({ memoId: '550e8400-e29b-41d4-a716-446655440000' });
// Get by reference ID
const memo = await skald.getMemo({ memoId: 'external-id-123', idType: 'reference_id' });
console.log(memo.title);
console.log(memo.content);
console.log(memo.summary);
console.log(memo.tags);
console.log(memo.chunks);The getMemo() method returns complete memo details including content, AI-generated summary, tags, and content chunks.
List Memos
List all memos with pagination:
// Get first page with default page size (20)
const memos = await skald.listMemos();
// Get specific page with custom page size
const memos = await skald.listMemos({ page: 2, page_size: 50 });
console.log(`Total memos: ${memos.count}`);
console.log(`Results: ${memos.results.length}`);
console.log(`Next page: ${memos.next}`);Parameters:
page(number, optional) - Page number (default: 1)page_size(number, optional) - Results per page (default: 20, max: 100)
Update a Memo
Update an existing memo by UUID or reference ID:
// Update by UUID
await skald.updateMemo({
memoId: '550e8400-e29b-41d4-a716-446655440000',
updateData: {
title: 'Updated Title',
metadata: { status: 'reviewed' }
}
});
// Update by reference ID and trigger reprocessing
await skald.updateMemo({
memoId: 'external-id-123',
updateData: {
content: 'New content that will be reprocessed'
},
idType: 'reference_id'
});Note: When you update the content field, the memo will be automatically reprocessed (summary, tags, and chunks regenerated).
Updatable Fields:
title(string)content(string)metadata(object)client_reference_id(string)source(string)expiration_date(string)
Delete a Memo
Permanently delete a memo and all associated data:
// Delete by UUID
await skald.deleteMemo({ memoId: '550e8400-e29b-41d4-a716-446655440000' });
// Delete by reference ID
await skald.deleteMemo({ memoId: 'external-id-123', idType: 'reference_id' });Warning: This operation permanently deletes the memo and all related data (content, summary, tags, chunks) and cannot be undone.
Search Memos
Search through your memos using semantic search. Returns :
// Basic semantic search
const results = await skald.search({
query: 'quarterly goals',
limit: 10
});
// Search with filters
const filtered = await skald.search({
query: 'python tutorial',
filters: [
{
field: 'source',
operator: 'eq',
value: 'notion',
filter_type: 'native_field'
},
{
field: 'level',
operator: 'eq',
value: 'beginner',
filter_type: 'custom_metadata'
}
]
});
console.log(`Found ${filtered.results.length} results`);
filtered.results.forEach(memo => {
console.log(`- ${memo.title} (distance: ${memo.distance})`);
});Search Parameters
query(string, required) - The search querylimit(integer, optional) - Maximum results to return (1-50, default 10)filters(array, optional) - Array of filter objects to narrow results (see Filters section below)
Search Response
interface SearchResponse {
results: Array<{
memo_uuid: string;
chunk_uuid: string;
memo_title: string;
memo_summary: string;
content_snippet: string;
distance: number | null;
}>;
}memo_uuid- Unique identifier for the memomemo_uuid- Unique identifier for the chunkmemo_title- Memo titlememo_summary- Auto-generated summary for the memocontent_snippet- A snippet containing the beginning of the chunk content.distance- A decimal from 0 to 2 determining how close the result was deemed to be to the query when using semantic search (chunk_vector_search). The closer to 0 the more related the content is to the query.nullif usingtitle_containsortitle_startswith.
Chat with Your Knowledge Base
Ask questions about your memos using an AI agent. The agent retrieves relevant context and generates answers with inline citations.
Non-Streaming Chat
const result = await skald.chat({
query: 'What were the main points discussed in the Q1 meeting?'
});
console.log(result.response);
// "The main points discussed in the Q1 meeting were:
// 1. Revenue targets [[1]]
// 2. Hiring plans [[2]]
// 3. Product roadmap [[1]][[3]]"
console.log(result.ok); // true
console.log(result.chat_id); // '550e8400-e29b-41d4-a716-446655440000'
// Continue the conversation by passing the chat_id
const followUp = await skald.chat({
query: 'What were the revenue targets?',
chat_id: result.chat_id // Maintains conversation context
});
console.log(followUp.response);
// "Based on the Q1 meeting notes, the revenue targets were... [[1]]"Streaming Chat
For real-time responses, use streaming chat:
let chatId;
const stream = skald.streamedChat({
query: 'What are our quarterly goals?'
});
for await (const event of stream) {
if (event.type === 'token') {
// Write each token as it arrives
process.stdout.write(event.content);
} else if (event.type === 'done') {
// Capture the chat_id for continuing the conversation
chatId = event.chat_id;
console.log('\nDone!');
}
}
// Continue the conversation with the captured chat_id
const followUpStream = skald.streamedChat({
query: 'Can you elaborate on the first goal?',
chat_id: chatId // Maintains conversation context
});
for await (const event of followUpStream) {
if (event.type === 'token') {
process.stdout.write(event.content);
} else if (event.type === 'done') {
console.log('\nDone!');
}
}Chat Parameters
query(string, required) - The question to askchat_id(string, optional) - Chat ID to continue an existing conversation. When provided, the AI will have context from previous messages in the same conversationsystem_prompt(string, optional) - A system prompt to guide the AI's behaviorfilters(array, optional) - Array of filter objects to focus chat context on specific sources (see Filters section below)rag_config(object, optional) - Advanced RAG (Retrieval-Augmented Generation) configuration to customize the search and retrieval behavior (see RAG Configuration section below)project_id(string, optional) - Project UUID (required when using Token Authentication)
Chat Response
Non-Streaming Response:
Non-streaming responses include:
ok(boolean) - Success statusresponse(string) - The AI's answer with inline citations in format[[N]](e.g.,[[1]],[[2]])chat_id(string) - Unique identifier for this conversation. Use this to continue the conversation with follow-up questionsintermediate_steps(array) - Steps taken by the agent (for debugging)references(object, optional) - Mapping of citation numbers to memo information (only included whenrag_config.references.enabledistrue)
Streaming Response:
Streaming responses yield events:
{ type: 'token', content: string }- Each text token as it's generated{ type: 'references', content: string }- JSON string containing the references object (only sent whenrag_config.references.enabledistrue){ type: 'done', chat_id: string }- Indicates the stream has finished and includes the chat_id for continuing the conversation
Understanding References
When you enable references in your RAG config (rag_config.references.enabled: true), the chat response will include inline citations and a references object that maps citation numbers to the source memos.
Citation Format:
The AI's response will include citations in the format [[N]] where N is a number (e.g., [[1]], [[2]], [[3]]). These citations appear inline in the response text to indicate which source memos support specific statements.
References Object Structure:
interface References {
[key: string]: {
memo_uuid: string; // UUID of the referenced memo
memo_title: string; // Title of the referenced memo
};
}Non-Streaming Example with References:
const result = await skald.chat({
query: 'What is the main topic discussed in the documentation?',
rag_config: {
references: {
enabled: true
}
}
});
console.log(result.response);
// "Based on the documentation, the main topic is about API authentication
// and authorization. The system uses API keys for authentication [[1]],
// and supports role-based access control [[2]]. For more details on
// implementation, see the security guide [[3]]."
console.log(result.references);
// {
// "1": {
// "memo_uuid": "123e4567-e89b-12d3-a456-426614174000",
// "memo_title": "API Authentication Guide"
// },
// "2": {
// "memo_uuid": "223e4567-e89b-12d3-a456-426614174001",
// "memo_title": "Role-Based Access Control"
// },
// "3": {
// "memo_uuid": "323e4567-e89b-12d3-a456-426614174002",
// "memo_title": "Security Best Practices"
// }
// }Streaming Example with References:
let fullResponse = '';
let references = {};
const stream = skald.streamedChat({
query: 'What are our security best practices?',
rag_config: {
references: {
enabled: true
}
}
});
for await (const event of stream) {
if (event.type === 'token') {
// Accumulate response text with citations
fullResponse += event.content;
process.stdout.write(event.content);
} else if (event.type === 'references') {
// Parse references object
references = JSON.parse(event.content);
console.log('\nReferences:', references);
} else if (event.type === 'done') {
console.log('\nChat ID:', event.chat_id);
}
}
// Example output:
// fullResponse: "Our security practices include regular audits [[1]],
// encryption at rest [[2]], and multi-factor authentication [[1]][[3]]."
//
// references: {
// "1": {
// "memo_uuid": "123e4567-...",
// "memo_title": "Security Audit Procedures"
// },
// "2": {
// "memo_uuid": "223e4567-...",
// "memo_title": "Data Encryption Standards"
// },
// "3": {
// "memo_uuid": "323e4567-...",
// "memo_title": "Authentication Setup Guide"
// }
// }Filters
Filters allow you to narrow down results based on memo metadata. You can filter by native fields or custom metadata fields. Filters are supported in search(), chat(), generateDoc(), and their streaming variants.
Filter Structure
interface Filter {
field: string; // Field name to filter on
operator: FilterOperator; // Comparison operator
value: string | string[]; // Value(s) to compare against
filter_type: 'native_field' | 'custom_metadata';
}Native Fields
Native fields are built-in memo properties:
title- Memo titlesource- Source system (e.g., "notion", "confluence")client_reference_id- Your external reference IDtags- Memo tags (array)
Custom Metadata Fields
You can filter on any field from the metadata object you provided when creating the memo.
Filter Operators
eq- Equals (exact match)neq- Not equalscontains- Contains substring (case-insensitive)startswith- Starts with prefix (case-insensitive)endswith- Ends with suffix (case-insensitive)in- Value is in array (requires array value)not_in- Value is not in array (requires array value)
Filter Examples
// Filter by source
{
field: 'source',
operator: 'eq',
value: 'notion',
filter_type: 'native_field'
}
// Filter by multiple tags
{
field: 'tags',
operator: 'in',
value: ['security', 'compliance'],
filter_type: 'native_field'
}
// Filter by title containing text
{
field: 'title',
operator: 'contains',
value: 'meeting',
filter_type: 'native_field'
}
// Filter by custom metadata field
{
field: 'department',
operator: 'eq',
value: 'engineering',
filter_type: 'custom_metadata'
}
// Exclude specific sources
{
field: 'source',
operator: 'not_in',
value: ['draft', 'archive'],
filter_type: 'native_field'
}Combining Multiple Filters
When you provide multiple filters, they are combined with AND logic (all filters must match):
const results = await skald.search({
query: 'security best practices',
filters: [
{
field: 'source',
operator: 'eq',
value: 'security-docs',
filter_type: 'native_field'
},
{
field: 'tags',
operator: 'in',
value: ['approved', 'current'],
filter_type: 'native_field'
},
{
field: 'status',
operator: 'neq',
value: 'draft',
filter_type: 'custom_metadata'
}
]
});Filters with Chat
Focus chat context on specific sources:
const result = await skald.chat({
query: 'What are our security practices?',
filters: [
{
field: 'tags',
operator: 'in',
value: ['security', 'compliance'],
filter_type: 'native_field'
}
]
});Filters with Document Generation
Control which memos are used for document generation:
const doc = await skald.generateDoc({
prompt: 'Create an API integration guide',
rules: 'Use technical language with code examples',
filters: [
{
field: 'source',
operator: 'in',
value: ['api-docs', 'technical-specs'],
filter_type: 'native_field'
},
{
field: 'document_type',
operator: 'eq',
value: 'specification',
filter_type: 'custom_metadata'
}
]
});RAG Configuration
The rag_config parameter allows you to customize the Retrieval-Augmented Generation (RAG) behavior for chat operations. This gives you fine-grained control over how documents are retrieved, ranked, and used to generate responses.
RAG Config Structure
interface RAGConfig {
llmProvider?: 'openai' | 'anthropic' | 'groq';
queryRewrite?: {
enabled: boolean;
};
vectorSearch?: {
topK: number; // 1-200
similarityThreshold: number; // 0.0-1.0
};
reranking?: {
enabled: boolean;
topK: number; // 1-100
};
references?: {
enabled: boolean;
};
}RAG Config Options
llmProvider (string, optional)
- Specifies which LLM provider to use for generating responses
- Options:
'openai','anthropic','groq' - Defaults to your project's configured provider
queryRewrite (object, optional)
enabled(boolean) - Whether to rewrite the user's query for better retrieval- Query rewriting can improve search results by reformulating vague queries
- Default:
false
vectorSearch (object, optional)
topK(number, 1-200) - How many chunks to retrieve from vector searchsimilarityThreshold(number, 0.0-1.0) - Minimum similarity score (0 = most similar)- Lower similarity thresholds are more restrictive
- Default:
topK: 100,similarityThreshold: 0.8
reranking (object, optional)
enabled(boolean) - Whether to rerank search results for better relevancetopK(number, 1-100) - How many top results to keep after reranking (must be ≤ vectorSearch.topK)- Reranking uses a more sophisticated model to order results by relevance
- Default:
enabled: true,topK: 50
references (object, optional)
enabled(boolean) - Whether to include inline citations in the response (e.g.,[[1]],[[2]])- Default:
false
Basic RAG Config Examples
Enable References with Citations:
const result = await skald.chat({
query: 'What are our security best practices?',
rag_config: {
references: {
enabled: true
}
}
});
console.log(result.response);
// "Our security practices include: 1) Regular audits [[1]],
// 2) Encryption at rest [[2]], and 3) Multi-factor authentication [[1]][[3]]"Customize Vector Search Parameters:
const result = await skald.chat({
query: 'Tell me about our product roadmap',
rag_config: {
vectorSearch: {
topK: 150, // Retrieve more chunks
similarityThreshold: 0.7 // Be less restrictive
},
reranking: {
enabled: true,
topK: 30 // Keep top 30 after reranking
}
}
});Use a Specific LLM Provider:
const result = await skald.chat({
query: 'Summarize our Q4 goals',
rag_config: {
llmProvider: 'anthropic', // Use Claude
references: {
enabled: true
}
}
});Enable Query Rewriting for Better Results:
const result = await skald.chat({
query: 'how do we handle that thing with customers?', // Vague query
rag_config: {
queryRewrite: {
enabled: true // AI will reformulate this into a clearer query
},
vectorSearch: {
topK: 100,
similarityThreshold: 0.8
}
}
});Disable Reranking for Faster Responses:
const result = await skald.chat({
query: 'What is our company mission?',
rag_config: {
reranking: {
enabled: false, // Skip reranking for faster response
topK: 50
}
}
});Advanced RAG Config Examples
Fine-tune All RAG Parameters:
const result = await skald.chat({
query: 'What security measures do we have in place?',
system_prompt: 'You are a security expert. Provide detailed, technical answers.',
rag_config: {
llmProvider: 'anthropic',
queryRewrite: {
enabled: true
},
vectorSearch: {
topK: 200, // Maximum retrieval
similarityThreshold: 0.6 // Cast a wider net
},
reranking: {
enabled: true,
topK: 50 // Keep top 50 most relevant
},
references: {
enabled: true // Include citations
}
},
filters: [
{
field: 'tags',
operator: 'in',
value: ['security', 'compliance'],
filter_type: 'native_field'
}
]
});Streaming Chat with RAG Config:
const stream = skald.streamedChat({
query: 'Explain our data processing pipeline',
rag_config: {
llmProvider: 'groq', // Use Groq for fast streaming
vectorSearch: {
topK: 120,
similarityThreshold: 0.75
},
reranking: {
enabled: true,
topK: 40
},
references: {
enabled: true
}
}
});
for await (const event of stream) {
if (event.type === 'token') {
process.stdout.write(event.content);
} else if (event.type === 'done') {
console.log('\nChat ID:', event.chat_id);
}
}Optimize for Precision (Narrow, Focused Results):
const result = await skald.chat({
query: 'What is the exact version number of our API?',
rag_config: {
vectorSearch: {
topK: 50, // Fewer chunks
similarityThreshold: 0.9 // Very strict matching
},
reranking: {
enabled: true,
topK: 10 // Only keep top 10
}
}
});Optimize for Recall (Broad, Comprehensive Results):
const result = await skald.chat({
query: 'Tell me everything about our customer onboarding process',
rag_config: {
vectorSearch: {
topK: 200, // Maximum chunks
similarityThreshold: 0.5 // More permissive
},
reranking: {
enabled: true,
topK: 80 // Keep more results
}
}
});RAG Config Best Practices
Start with defaults: The default settings work well for most use cases. Only customize when you have specific needs.
Enable references for transparency: If you need to verify information or provide source attribution, enable
references.enabled: true.Balance topK values:
- Higher
vectorSearch.topK= more comprehensive but slower - Ensure
reranking.topK≤vectorSearch.topK - Typical range: vectorSearch 80-150, reranking 30-60
- Higher
Adjust similarity threshold based on need:
- Strict matching (0.9-1.0): Use when you need exact information
- Balanced (0.7-0.8): Good default for most queries
- Broad matching (0.5-0.6): Use for exploratory or vague queries
Use query rewriting for user-facing applications: Enable
queryRewrite.enabled: truewhen users might provide unclear or ambiguous queries.Choose LLM provider based on requirements:
anthropic(Claude): Great for nuanced understanding and longer contextopenai(GPT): Fast and reliable for most use casesgroq: Optimized for speed with streaming responses
TypeScript Support for RAG Config
import { Skald, RAGConfig, LLMProvider } from '@skald-labs/skald-node';
const ragConfig: RAGConfig = {
llmProvider: 'anthropic' as LLMProvider,
queryRewrite: {
enabled: true
},
vectorSearch: {
topK: 150,
similarityThreshold: 0.75
},
reranking: {
enabled: true,
topK: 50
},
references: {
enabled: true
}
};
const result = await skald.chat({
query: 'What are our company values?',
rag_config: ragConfig
});Error Handling
try {
const result = await skald.createMemo({
title: 'My Memo',
content: 'Content here'
});
console.log('Success:', result);
} catch (error) {
console.error('Error:', error.message);
}TypeScript Support
This package includes TypeScript type definitions out of the box.
import {
Skald,
MemoData,
CreateMemoResponse,
MemoFileData,
CreateMemoFromFileResponse,
MemoStatus,
MemoStatusResponse,
Memo,
ListMemosResponse,
UpdateMemoData,
UpdateMemoResponse,
DeleteMemoResponse,
IdType,
GetMemoRequest,
UpdateMemoRequest,
DeleteMemoRequest,
CheckMemoStatusRequest,
Filter,
FilterOperator,
FilterType,
SearchRequest,
SearchResponse,
ChatRequest,
ChatResponse,
ChatStreamEvent,
RAGConfig,
LLMProvider,
QueryRewriteConfig,
VectorSearchConfig,
RerankingConfig,
ReferencesConfig,
MemoReference,
References
} from '@skald-labs/skald-node';
const skald = new Skald('your-api-key-here');
// Create a memo with types
const memoData: MemoData = {
title: 'My Memo',
content: 'Content here',
tags: ['tag1', 'tag2'],
metadata: { department: 'engineering' }
};
const createResponse: CreateMemoResponse = await skald.createMemo(memoData);
// Get memo with types
const memo: Memo = await skald.getMemo({ memoId: '550e8400-e29b-41d4-a716-446655440000' });
const memoByRef: Memo = await skald.getMemo({ memoId: 'external-id-123', idType: 'reference_id' as IdType });
// List memos with types
const memos: ListMemosResponse = await skald.listMemos({ page: 1, page_size: 20 });
// Update memo with types
const updateData: UpdateMemoData = {
title: 'Updated Title',
metadata: { status: 'reviewed' }
};
const updateResponse: UpdateMemoResponse = await skald.updateMemo({
memoId: '550e8400-e29b-41d4-a716-446655440000',
updateData
});
// Delete memo
await skald.deleteMemo({ memoId: '550e8400-e29b-41d4-a716-446655440000' });
// Upload a file
import * as fs from 'fs';
const fileBuffer = fs.readFileSync('./document.pdf');
const fileData: MemoFileData = {
file: fileBuffer,
filename: 'document.pdf',
metadata: { type: 'report' },
tags: ['document'],
source: 'local'
};
const uploadResponse: CreateMemoFromFileResponse = await skald.createMemoFromFile(fileData);
// Check processing status
const statusResponse: MemoStatusResponse = await skald.checkMemoStatus({ memoId: uploadResponse.memo_uuid });
const status: MemoStatus = statusResponse.status; // 'processing' | 'processed' | 'error'
// Search with filters and types
const filters: Filter[] = [
{
field: 'source',
operator: 'eq' as FilterOperator,
value: 'notion',
filter_type: 'native_field' as FilterType
},
{
field: 'department',
operator: 'eq' as FilterOperator,
value: 'engineering',
filter_type: 'custom_metadata' as FilterType
}
];
const searchRequest: SearchRequest = {
query: 'quarterly goals',
limit: 10,
filters
};
const searchResponse: SearchResponse = await skald.search(searchRequest);
// Chat with filters and types
const chatResponse: ChatResponse = await skald.chat({
query: 'What are our quarterly goals?',
filters
});
// Streaming chat with types
const stream = skald.streamedChat({
query: 'What are our quarterly goals?',
filters
});
for await (const event of stream) {
const typedEvent: ChatStreamEvent = event;
if (typedEvent.type === 'token') {
process.stdout.write(typedEvent.content || '');
}
}
// Chat with references and types
const chatWithRefs: ChatResponse = await skald.chat({
query: 'What are our security best practices?',
rag_config: {
references: {
enabled: true
}
}
});
console.log(chatWithRefs.response); // Response with [[1]], [[2]], etc.
if (chatWithRefs.references) {
const refs: References = chatWithRefs.references;
Object.entries(refs).forEach(([num, ref]) => {
const memoRef: MemoReference = ref;
console.log(`[${num}] ${memoRef.memo_title} (${memoRef.memo_uuid})`);
});
}
// Streaming chat with references and types
let fullResponse = '';
let streamedRefs: References | undefined;
const streamWithRefs = skald.streamedChat({
query: 'Explain our authentication system',
rag_config: {
references: {
enabled: true
}
}
});
for await (const event of streamWithRefs) {
const typedEvent: ChatStreamEvent = event;
if (typedEvent.type === 'token') {
fullResponse += typedEvent.content || '';
process.stdout.write(typedEvent.content || '');
} else if (typedEvent.type === 'references') {
streamedRefs = JSON.parse(typedEvent.content || '{}') as References;
console.log('\nReferences received:', Object.keys(streamedRefs).length);
} else if (typedEvent.type === 'done') {
console.log('\nChat completed:', typedEvent.chat_id);
}
}
