chore(server): fix more type errors

This commit is contained in:
Elian Doran 2025-05-28 19:57:55 +03:00
parent ba7c93967e
commit ff106e21cf
No known key found for this signature in database
15 changed files with 99 additions and 43 deletions

View File

@ -51,7 +51,7 @@ export function getLocales(): Locale[] {
} }
function getCurrentLanguage(): LOCALE_IDS { function getCurrentLanguage(): LOCALE_IDS {
let language: string; let language: string | null = null;
if (sql_init.isDbInitialized()) { if (sql_init.isDbInitialized()) {
language = options.getOptionOrNull("locale"); language = options.getOptionOrNull("locale");
} }

View File

@ -84,7 +84,7 @@ async function importOpml(taskContext: TaskContext, fileBuffer: string | Buffer,
} }
const outlines = xml.opml.body[0].outline || []; const outlines = xml.opml.body[0].outline || [];
let returnNote = null; let returnNote: BNote | null = null;
for (const outline of outlines) { for (const outline of outlines) {
const note = importOutline(outline, parentNote.noteId); const note = importOutline(outline, parentNote.noteId);

View File

@ -9,7 +9,7 @@ export interface Message {
content: string; content: string;
name?: string; name?: string;
tool_call_id?: string; tool_call_id?: string;
tool_calls?: ToolCall[]; tool_calls?: ToolCall[] | null;
sessionId?: string; // Optional session ID for WebSocket communication sessionId?: string; // Optional session ID for WebSocket communication
} }
@ -210,7 +210,7 @@ export interface ChatResponse {
stream?: (callback: (chunk: StreamChunk) => Promise<void> | void) => Promise<string>; stream?: (callback: (chunk: StreamChunk) => Promise<void> | void) => Promise<string>;
/** Tool calls from the LLM (if tools were used and the model supports them) */ /** Tool calls from the LLM (if tools were used and the model supports them) */
tool_calls?: ToolCall[]; tool_calls?: ToolCall[] | null;
} }
export interface AIService { export interface AIService {

View File

@ -22,20 +22,24 @@ export interface NoteEmbeddingContext {
title: string; title: string;
mime: string; mime: string;
}[]; }[];
backlinks?: { backlinks?: Backlink[];
sourceNoteId: string; relatedNotes?: RelatedNote[];
sourceTitle: string;
relationName: string;
}[];
relatedNotes?: {
targetNoteId: string;
targetTitle: string;
relationName: string;
}[];
labelValues?: Record<string, string>; labelValues?: Record<string, string>;
templateTitles?: string[]; templateTitles?: string[];
} }
export interface Backlink {
sourceNoteId: string;
sourceTitle: string;
relationName: string;
}
export interface RelatedNote {
targetNoteId: string;
targetTitle: string;
relationName: string;
}
/** /**
* Information about an embedding model's capabilities * Information about an embedding model's capabilities
*/ */

View File

@ -8,6 +8,14 @@ import entityChangesService from "../../../services/entity_changes.js";
import type { EntityChange } from "../../../services/entity_changes_interface.js"; import type { EntityChange } from "../../../services/entity_changes_interface.js";
import { EMBEDDING_CONSTANTS } from "../constants/embedding_constants.js"; import { EMBEDDING_CONSTANTS } from "../constants/embedding_constants.js";
import { SEARCH_CONSTANTS } from '../constants/search_constants.js'; import { SEARCH_CONSTANTS } from '../constants/search_constants.js';
interface Similarity {
noteId: string;
similarity: number;
contentType: string;
bonuses?: Record<string, number>; // Optional for debugging
}
/** /**
* Creates or updates an embedding for a note * Creates or updates an embedding for a note
*/ */
@ -434,7 +442,7 @@ async function processEmbeddings(queryEmbedding: Float32Array, embeddings: any[]
return { bonuses, totalBonus }; return { bonuses, totalBonus };
} }
const similarities = []; const similarities: Similarity[] = [];
try { try {
// Try to extract the original query text if it was added to the metadata // Try to extract the original query text if it was added to the metadata

View File

@ -7,6 +7,21 @@ import { getAnthropicOptions } from './providers.js';
import log from '../../log.js'; import log from '../../log.js';
import Anthropic from '@anthropic-ai/sdk'; import Anthropic from '@anthropic-ai/sdk';
import { SEARCH_CONSTANTS } from '../constants/search_constants.js'; import { SEARCH_CONSTANTS } from '../constants/search_constants.js';
import type { ToolCall } from '../tools/tool_interfaces.js';
interface AnthropicMessage extends Omit<Message, "content"> {
content: MessageContent[] | string;
}
interface MessageContent {
type: "text" | "tool_use" | "tool_result";
text?: string;
id?: string;
name?: string;
content?: string;
tool_use_id?: string;
input?: string | Record<string, unknown>;
}
export class AnthropicService extends BaseAIService { export class AnthropicService extends BaseAIService {
private client: any = null; private client: any = null;
@ -130,7 +145,7 @@ export class AnthropicService extends BaseAIService {
.join(''); .join('');
// Process tool calls if any are present in the response // Process tool calls if any are present in the response
let toolCalls = null; let toolCalls: ToolCall[] | null = null;
if (response.content) { if (response.content) {
const toolBlocks = response.content.filter((block: any) => const toolBlocks = response.content.filter((block: any) =>
block.type === 'tool_use' || block.type === 'tool_use' ||
@ -157,7 +172,7 @@ export class AnthropicService extends BaseAIService {
return null; return null;
}).filter(Boolean); }).filter(Boolean);
log.info(`Extracted ${toolCalls.length} tool calls from Anthropic response`); log.info(`Extracted ${toolCalls?.length} tool calls from Anthropic response`);
} }
} }
@ -406,8 +421,8 @@ export class AnthropicService extends BaseAIService {
/** /**
* Format messages for the Anthropic API * Format messages for the Anthropic API
*/ */
private formatMessages(messages: Message[]): any[] { private formatMessages(messages: Message[]): AnthropicMessage[] {
const anthropicMessages: any[] = []; const anthropicMessages: AnthropicMessage[] = [];
// Process each message // Process each message
for (const msg of messages) { for (const msg of messages) {
@ -424,7 +439,7 @@ export class AnthropicService extends BaseAIService {
// Assistant messages need special handling for tool_calls // Assistant messages need special handling for tool_calls
if (msg.tool_calls && msg.tool_calls.length > 0) { if (msg.tool_calls && msg.tool_calls.length > 0) {
// Create content blocks array for tool calls // Create content blocks array for tool calls
const content = []; const content: MessageContent[] = [];
// Add text content if present // Add text content if present
if (msg.content) { if (msg.content) {

View File

@ -181,7 +181,7 @@ export async function updateEmbeddingProviderConfig(
} }
// Build update query parts // Build update query parts
const updates = []; const updates: string[] = [];
const params: any[] = []; const params: any[] = [];
if (priority !== undefined) { if (priority !== undefined) {

View File

@ -8,6 +8,26 @@ import type { Tool, ToolHandler } from './tool_interfaces.js';
import log from '../../log.js'; import log from '../../log.js';
import becca from '../../../becca/becca.js'; import becca from '../../../becca/becca.js';
interface CodeBlock {
code: string;
language?: string;
}
interface Heading {
text: string;
level: number; // 1 for H1, 2 for H2, etc.
}
interface List {
type: "unordered" | "ordered";
items: string[];
}
interface Table {
headers: string[];
rows: string[][];
}
/** /**
* Definition of the content extraction tool * Definition of the content extraction tool
*/ */
@ -137,8 +157,8 @@ export class ContentExtractionTool implements ToolHandler {
/** /**
* Extract lists from HTML content * Extract lists from HTML content
*/ */
private extractLists(content: string): Array<{ type: string, items: string[] }> { private extractLists(content: string): List[] {
const lists = []; const lists: List[] = [];
// Extract unordered lists // Extract unordered lists
const ulRegex = /<ul[^>]*>([\s\S]*?)<\/ul>/gi; const ulRegex = /<ul[^>]*>([\s\S]*?)<\/ul>/gi;
@ -179,7 +199,7 @@ export class ContentExtractionTool implements ToolHandler {
* Extract list items from list content * Extract list items from list content
*/ */
private extractListItems(listContent: string): string[] { private extractListItems(listContent: string): string[] {
const items = []; const items: string[] = [];
const itemRegex = /<li[^>]*>([\s\S]*?)<\/li>/gi; const itemRegex = /<li[^>]*>([\s\S]*?)<\/li>/gi;
let itemMatch; let itemMatch;
@ -196,15 +216,15 @@ export class ContentExtractionTool implements ToolHandler {
/** /**
* Extract tables from HTML content * Extract tables from HTML content
*/ */
private extractTables(content: string): Array<{ headers: string[], rows: string[][] }> { private extractTables(content: string): Table[] {
const tables = []; const tables: Table[] = [];
const tableRegex = /<table[^>]*>([\s\S]*?)<\/table>/gi; const tableRegex = /<table[^>]*>([\s\S]*?)<\/table>/gi;
let tableMatch; let tableMatch: RegExpExecArray | null;
while ((tableMatch = tableRegex.exec(content)) !== null) { while ((tableMatch = tableRegex.exec(content)) !== null) {
const tableContent = tableMatch[1]; const tableContent = tableMatch[1];
const headers = []; const headers: string[] = [];
const rows = []; const rows: string[][] = [];
// Extract table headers // Extract table headers
const headerRegex = /<th[^>]*>([\s\S]*?)<\/th>/gi; const headerRegex = /<th[^>]*>([\s\S]*?)<\/th>/gi;
@ -218,7 +238,7 @@ export class ContentExtractionTool implements ToolHandler {
let rowMatch; let rowMatch;
while ((rowMatch = rowRegex.exec(tableContent)) !== null) { while ((rowMatch = rowRegex.exec(tableContent)) !== null) {
const rowContent = rowMatch[1]; const rowContent = rowMatch[1];
const cells = []; const cells: string[] = [];
const cellRegex = /<td[^>]*>([\s\S]*?)<\/td>/gi; const cellRegex = /<td[^>]*>([\s\S]*?)<\/td>/gi;
let cellMatch; let cellMatch;
@ -246,7 +266,7 @@ export class ContentExtractionTool implements ToolHandler {
* Extract headings from HTML content * Extract headings from HTML content
*/ */
private extractHeadings(content: string): Array<{ level: number, text: string }> { private extractHeadings(content: string): Array<{ level: number, text: string }> {
const headings = []; const headings: Heading[] = [];
for (let i = 1; i <= 6; i++) { for (let i = 1; i <= 6; i++) {
const headingRegex = new RegExp(`<h${i}[^>]*>([\\s\\S]*?)<\/h${i}>`, 'gi'); const headingRegex = new RegExp(`<h${i}[^>]*>([\\s\\S]*?)<\/h${i}>`, 'gi');
@ -270,7 +290,7 @@ export class ContentExtractionTool implements ToolHandler {
* Extract code blocks from HTML content * Extract code blocks from HTML content
*/ */
private extractCodeBlocks(content: string): Array<{ language?: string, code: string }> { private extractCodeBlocks(content: string): Array<{ language?: string, code: string }> {
const codeBlocks = []; const codeBlocks: CodeBlock[] = [];
// Look for <pre> and <code> blocks // Look for <pre> and <code> blocks
const preRegex = /<pre[^>]*>([\s\S]*?)<\/pre>/gi; const preRegex = /<pre[^>]*>([\s\S]*?)<\/pre>/gi;

View File

@ -9,6 +9,7 @@ import log from '../../log.js';
import becca from '../../../becca/becca.js'; import becca from '../../../becca/becca.js';
import notes from '../../notes.js'; import notes from '../../notes.js';
import attributes from '../../attributes.js'; import attributes from '../../attributes.js';
import type { BNote } from '../../backend_script_entrypoint.js';
/** /**
* Definition of the note creation tool * Definition of the note creation tool
@ -89,7 +90,7 @@ export class NoteCreationTool implements ToolHandler {
log.info(`Executing create_note tool - Title: "${title}", Type: ${type}, ParentNoteId: ${parentNoteId || 'root'}`); log.info(`Executing create_note tool - Title: "${title}", Type: ${type}, ParentNoteId: ${parentNoteId || 'root'}`);
// Validate parent note exists if specified // Validate parent note exists if specified
let parent = null; let parent: BNote | null = null;
if (parentNoteId) { if (parentNoteId) {
parent = becca.notes[parentNoteId]; parent = becca.notes[parentNoteId];
if (!parent) { if (!parent) {

View File

@ -10,6 +10,14 @@ import becca from '../../../becca/becca.js';
import attributes from '../../attributes.js'; import attributes from '../../attributes.js';
import aiServiceManager from '../ai_service_manager.js'; import aiServiceManager from '../ai_service_manager.js';
import { SEARCH_CONSTANTS } from '../constants/search_constants.js'; import { SEARCH_CONSTANTS } from '../constants/search_constants.js';
import type { Backlink, RelatedNote } from '../embeddings/embeddings_interface.js';
interface Suggestion {
targetNoteId: string;
targetTitle: string;
similarity: number;
suggestedRelation: string;
}
/** /**
* Definition of the relationship tool * Definition of the relationship tool
@ -180,7 +188,7 @@ export class RelationshipTool implements ToolHandler {
.filter((attr: any) => attr.type === 'relation') .filter((attr: any) => attr.type === 'relation')
.slice(0, limit); .slice(0, limit);
const outgoingRelations = []; const outgoingRelations: RelatedNote[] = [];
for (const attr of outgoingAttributes) { for (const attr of outgoingAttributes) {
const targetNote = becca.notes[attr.value]; const targetNote = becca.notes[attr.value];
@ -196,7 +204,7 @@ export class RelationshipTool implements ToolHandler {
// Get incoming relationships (where this note is the target) // Get incoming relationships (where this note is the target)
// Since becca.findNotesWithRelation doesn't exist, use attributes to find notes with relation // Since becca.findNotesWithRelation doesn't exist, use attributes to find notes with relation
const incomingRelations = []; const incomingRelations: Backlink[] = [];
// Find all attributes of type relation that point to this note // Find all attributes of type relation that point to this note
const relationAttributes = sourceNote.getTargetRelations(); const relationAttributes = sourceNote.getTargetRelations();
@ -321,7 +329,7 @@ export class RelationshipTool implements ToolHandler {
const sourceContent = await sourceNote.getContent(); const sourceContent = await sourceNote.getContent();
// Prepare suggestions // Prepare suggestions
const suggestions = []; const suggestions: Suggestion[] = [];
for (const relatedNote of relatedResult.relatedNotes) { for (const relatedNote of relatedResult.relatedNotes) {
try { try {

View File

@ -755,7 +755,7 @@ function updateNoteData(noteId: string, content: string, attachments: Attachment
function undeleteNote(noteId: string, taskContext: TaskContext) { function undeleteNote(noteId: string, taskContext: TaskContext) {
const noteRow = sql.getRow<NoteRow>("SELECT * FROM notes WHERE noteId = ?", [noteId]); const noteRow = sql.getRow<NoteRow>("SELECT * FROM notes WHERE noteId = ?", [noteId]);
if (!noteRow.isDeleted) { if (!noteRow.isDeleted || !noteRow.deleteId) {
log.error(`Note '${noteId}' is not deleted and thus cannot be undeleted.`); log.error(`Note '${noteId}' is not deleted and thus cannot be undeleted.`);
return; return;
} }

View File

@ -118,7 +118,7 @@ function getParams(params?: ScriptParams) {
} }
function getScriptBundleForFrontend(note: BNote, script?: string, params?: ScriptParams) { function getScriptBundleForFrontend(note: BNote, script?: string, params?: ScriptParams) {
let overrideContent = null; let overrideContent: string | null = null;
if (script) { if (script) {
overrideContent = `return (${script}\r\n)(${getParams(params)})`; overrideContent = `return (${script}\r\n)(${getParams(params)})`;
@ -170,7 +170,7 @@ function getScriptBundle(note: BNote, root: boolean = true, scriptEnv: string |
includedNoteIds.push(note.noteId); includedNoteIds.push(note.noteId);
const modules = []; const modules: BNote[] = [];
for (const child of note.getChildNotes()) { for (const child of note.getChildNotes()) {
const childBundle = getScriptBundle(child, false, scriptEnv, includedNoteIds); const childBundle = getScriptBundle(child, false, scriptEnv, includedNoteIds);

View File

@ -294,11 +294,11 @@ function getExpression(tokens: TokenData[], searchContext: SearchContext, level
valueExtractor: ValueExtractor; valueExtractor: ValueExtractor;
direction: string; direction: string;
}[] = []; }[] = [];
let limit; let limit: number | undefined = undefined;
if (tokens[i].token === "orderby") { if (tokens[i].token === "orderby") {
do { do {
const propertyPath = []; const propertyPath: string[] = [];
let direction = "asc"; let direction = "asc";
do { do {

View File

@ -36,7 +36,7 @@ function searchFromNote(note: BNote): SearchNoteResult {
const searchScript = note.getRelationValue("searchScript"); const searchScript = note.getRelationValue("searchScript");
const searchString = note.getLabelValue("searchString") || ""; const searchString = note.getLabelValue("searchString") || "";
let error = null; let error: string | null = null;
if (searchScript) { if (searchScript) {
searchResultNoteIds = searchFromRelation(note, "searchScript"); searchResultNoteIds = searchFromRelation(note, "searchScript");

View File

@ -43,7 +43,7 @@ export default class Shaca {
} }
getNotes(noteIds: string[], ignoreMissing = false) { getNotes(noteIds: string[], ignoreMissing = false) {
const filteredNotes = []; const filteredNotes: SNote[] = [];
for (const noteId of noteIds) { for (const noteId of noteIds) {
const note = this.notes[noteId]; const note = this.notes[noteId];