obsidian-cyber-utils
Version:
Utility functions for developing Obsidian plugins, focused on cyber security note-taking.
927 lines (902 loc) • 34.1 kB
text/typescript
import { Plugin, WorkspaceLeaf, TFile, App, PluginManifest, TAbstractFile, Editor, SuggestModal, Modal, Vault, Workspace, ButtonComponent } from 'obsidian';
import { EventEmitter } from 'events';
import { Worker } from 'tesseract.js';
declare const VT_SEARCH = "https://virustotal.com/gui/search/%s";
declare const IPDB_SEARCH = "https://abuseipdb.com/check/%s";
declare const GOOGLE_SEARCH = "https://google.com/search?q=\"%s\"";
declare const DDG_SEARCH = "https://duckduckgo.com/?q=\"%s\"";
declare const URLSCAN_SEARCH = "https://urlscan.io/search/#%s";
declare const SPUR_SEARCH = "https://app.spur.us/context?q=%s";
declare const SHODAN_SEARCH = "https://www.shodan.io/host/%s";
declare const CENSYS_SEARCH = "https://search.censys.io/hosts/%s";
interface SearchSite {
name: string;
shortName: string;
description?: string;
site: string;
ip: boolean;
ipv6?: boolean;
hash: boolean;
domain: boolean;
multisearch: boolean;
urlEncodeSearchTerm?: boolean;
separator?: string;
enabled: boolean;
}
declare const vtSearch: SearchSite;
declare const ipdbSearch: SearchSite;
declare const ddgSearch: SearchSite;
declare const googleSearch: SearchSite;
declare const urlscanSearch: SearchSite;
declare const shodanSearch: SearchSite;
declare const censysSearch: SearchSite;
declare const spurSearch: SearchSite;
declare const IP_EXCLUSIONS: string[];
declare const DOMAIN_EXCLUSIONS: string[];
declare const defaultSites: SearchSite[];
type IndicatorExclusion = string | RegExp;
interface Indicator {
value: string;
type: IndicatorType;
source?: IndicatorSource;
metadata?: Record<string, any>;
}
type GroupedIndicators = {
[key in IndicatorSource]: {
[key in IndicatorType]: Indicator[];
};
};
declare enum IndicatorType {
IPv4 = "ipv4",
PRIVATE_IPv4 = "private_ipv4",
IPv6 = "ipv6",
PRIVATE_IPv6 = "private_ipv6",
DOMAIN = "domain",
HASH = "hash",
EMAIL = "email"
}
declare enum IndicatorSource {
TEXT = "text",
OCR = "ocr"
}
interface ParsedIndicators {
title: string;
items: string[];
sites?: SearchSite[];
exclusions?: IndicatorExclusion[];
}
/**
* Filter a list of indicators based on the provided exclusions.
* @param items a list of indicators
* @param exclusions a list of indicator exclusions
* @returns the list of indicators with exclusions filtered
*/
declare function filterExclusions(items: string[], exclusions: IndicatorExclusion[]): string[];
declare function groupIndicators(indicators: Indicator[]): GroupedIndicators;
interface IOcrProcessor {
readonly id: string;
processImage(job: OcrJobData): Promise<void>;
setEventEmitter?(emitter: IEventEmitter<OcrProviderEvent>): void;
shutdown?(): Promise<void>;
}
declare abstract class BaseOcrProcessor implements IOcrProcessor {
readonly id: string;
private isDebugging;
protected emitter: IEventEmitter<OcrProviderEvent> | null;
private jobQueue;
private activeTasks;
private maxConcurrency;
constructor(id: string, maxConcurrency?: number, enableDebug?: boolean);
setEventEmitter(emitter: IEventEmitter<OcrProviderEvent>): void;
processImage(job: OcrJobData): Promise<void>;
protected abstract _performOcr(job: OcrJobData): Promise<string>;
private _tryProcessNext;
protected emitProgress(fileId: string, status: OcrProgressPayload['status'], progressPercent?: number, message?: string): void;
setDebugging(enabled: boolean): void;
protected debug(...args: any[]): void;
shutdown(): Promise<void>;
}
interface OcrJobData {
fileId: string;
imageData: Buffer;
}
interface OcrProgressPayload {
fileId: string;
processorId: string;
status: 'queued' | 'processing' | 'retrying';
progressPercent?: number;
message?: string;
}
interface OcrCompletePayload {
fileId: string;
processorId: string;
extractedText: string;
}
interface OcrErrorPayload {
fileId: string;
processorId: string;
error: string;
canRetry?: boolean;
}
type OcrProviderEvent = {
type: 'ocr-progress';
payload: OcrProgressPayload;
} | {
type: 'ocr-complete';
payload: OcrCompletePayload;
} | {
type: 'ocr-error';
payload: OcrErrorPayload;
};
type OcrCacheChecker = (fileId: string, processorId: string) => boolean;
interface IEventEmitter<TEvent extends {
type: string;
payload: unknown;
}> {
on<K extends TEvent['type']>(event: K, listener: (payload: Extract<TEvent, {
type: K;
}>['payload']) => void): void;
emit<K extends TEvent['type']>(event: K, payload: Extract<TEvent, {
type: K;
}>['payload']): void;
}
interface IOcrProvider {
readonly emitter: IEventEmitter<OcrProviderEvent>;
processAttachments(fileId: string, attachments: OcrJobData[]): Promise<void>;
addProcessor(processor: IOcrProcessor): void;
setDebugging(enabled: boolean): void;
}
declare class OcrProvider implements IOcrProvider {
readonly emitter: IEventEmitter<OcrProviderEvent>;
private activeJobs;
private isDebugging;
private processors;
private processorEventEmitter;
private cacheChecker;
constructor(processors: IOcrProcessor[], cacheChecker: OcrCacheChecker, enableDebug?: boolean);
private setupEventListeners;
processAttachments(parentNoteFileId: string, attachments: OcrJobData[]): Promise<void>;
addProcessor(processor: IOcrProcessor): void;
setDebugging(enabled: boolean): void;
protected debug(...args: any[]): void;
private getJobId;
}
interface CyberPluginSettings {
validTld: string[];
searchSites: SearchSite[];
}
interface IndicatorExclusions {
ipv4Exclusions: IndicatorExclusion[];
ipv6Exclusions: IndicatorExclusion[];
hashExclusions: IndicatorExclusion[];
domainExclusions: IndicatorExclusion[];
}
type CyberPluginEvent = 'settings-change' | 'file-opened' | 'file-modified' | 'attachments-changed' | 'indicators-changed';
/**
* An Obsidian plugin class focused on Cybersecurity use cases.
*/
declare class CyberPlugin extends Plugin {
private isDebugging;
settings: CyberPluginSettings | undefined;
validTld: string[] | null | undefined;
sidebarContainers: Map<string, WorkspaceLeaf> | undefined;
protected emitter: EventEmitter;
protected indicators: Indicator[];
protected ocrIndicators: Indicator[] | null;
protected ocrCache: Map<string, Map<string, Indicator[]>>;
protected exclusions: IndicatorExclusions;
private fileOpenRef;
private fileModifyRef;
private vaultCacheRef;
protected activeFile: TFile | null;
protected activeFileContent: string | null;
protected activeFileAttachments: TFile[] | null;
protected ocrProvider: IOcrProvider | null;
private ocrProcessingEmitter;
protected uiNotifier: IEventEmitter<{
type: CyberPluginEvent;
payload: unknown;
}>;
private ocrProgressRef?;
private ocrCompleteRef?;
private ocrErrorRef?;
protected worker: Tesseract.Worker | null;
constructor(app: App, manifest: PluginManifest, enableDebug?: boolean);
onload(): Promise<void>;
refreshIndicators(): Promise<void>;
getFileContent(): string | null;
getFileAttachments(): TFile[];
getIocExclusions(): IndicatorExclusions;
/**
* Compare attachments for the current file against the plugin's attachment list.
* @param file the file to evaluate
* @returns true if attachments are unchanged, false if attachments have changed
*/
private compareAttachments;
registerObsidianListeners(): void;
handleFileOpen(file: TFile | null): Promise<void>;
handleFileModify(file: TAbstractFile): Promise<void>;
handleMetadataResolve(file: TFile): Promise<void>;
protected triggerOcrProcessing(): Promise<void>;
/**
* Add search sites to a set of ParsedIndicators.
*/
protected applySearchSites(indicators: ParsedIndicators[]): ParsedIndicators[];
/**
* Validate that domains end with a valid TLD
*/
protected validateDomains(indicators: ParsedIndicators[]): ParsedIndicators[];
protected processExclusions(indicators: ParsedIndicators[]): ParsedIndicators[];
initializeOcrSystem(): Promise<void>;
hasCachedOcrResult(fileId: string, processorId: string): boolean;
setupOcrEventListeners(): void;
handleOcrComplete(payload: OcrCompletePayload): Promise<void>;
handleOcrError(payload: OcrErrorPayload): void;
handleOcrProgress(payload: OcrProgressPayload): void;
/**
* Activate a view of the given type in the right sidebar.
* @param type a view type
*/
activateView(type: string): Promise<void>;
on(event: CyberPluginEvent, callback: (...args: any[]) => void): () => EventEmitter<[never]>;
saveSettings(): Promise<void>;
onunload(): Promise<void>;
setDebugging(enabled: boolean): void;
protected debug(...args: any[]): void;
}
/**
* remove a collection of elements
* as commonly returned by `getElementsByClassName`
* @param els a collection of HTML elements
*/
declare function removeElements(els: HTMLCollectionOf<Element>): void;
/**
* Open a collection of Details elements
* @param els the collection of elements to be opened
*/
declare function openDetails(els: HTMLCollectionOf<HTMLDetailsElement>): void;
/**
* Add a date picker "setting"
* @param parentEl the parent element to which the date picker will be added
* @param value the default value of the date picker (optional)
* @param name the display name for the date picker element (optional)
* @returns the date picker element
*/
declare function datePickerSettingEl(parentEl: HTMLElement, value?: string, name?: string): HTMLInputElement;
/**
* Transforms the text selected by the user.
* @param editor
* @param func the function to perform on the text
* @returns the transformed text
*/
declare function transformSelectedText(editor: Editor, func: Function): any;
/**
* Append content to the end of a file, and scroll to view it.
* @param app the current Obsidian App instance
* @param file the current note
* @param text the text to be appended
*/
declare function appendToEnd(app: App, file: TFile, text: string): void;
declare const PATTERN_KEYS: string[];
type PatternKey = typeof PATTERN_KEYS[number];
declare class Matcher {
private static readonly Patterns;
static getAvailablePatterns(): readonly PatternKey[];
static getExactMatcher(pattern: PatternKey): RegExp;
static getGlobalMatcher(pattern: PatternKey): RegExp;
static findAll(text: string, pattern: PatternKey): string[];
static isMatch(text: string, pattern: PatternKey): boolean;
static findFirst(text: string, pattern: PatternKey): string | null;
}
/**
* Extract IOCs from the given file content.
* @param fileContent content from which to extract IOCs
* @returns an array of ParsedIndicators objects for each IOC type
*/
declare function getMatches(fileContent: string): ParsedIndicators[];
declare function getIndicatorMatches(fileContent: string, source?: IndicatorSource, metadata?: Record<string, any>): Indicator[];
/**
* Process exclusions for a list of IOCs.
* @param plugin a CyberPlugin
* @param indicators a list of parsed indicators
* @returns indicators with exclusions applied
*/
declare function processExclusions(iocs: ParsedIndicators[], plugin: CyberPlugin | undefined): ParsedIndicators[];
interface SupportedMacro {
name: string;
macroRegex: RegExp[];
valueRegex: RegExp;
}
declare const supportedMacros: SupportedMacro[];
interface Code {
content: string;
lang: string;
icon?: string;
}
declare class ScriptObject {
code: Code;
dated: boolean;
baseTimestamp?: number;
fromTime?: number;
toTime?: number;
macros: string[];
replacedCode: string;
constructor(code: Code, dated?: boolean);
replaceMacros(replacements: Map<string, string>): void;
}
type Class<CodeModal> = new (...args: any[]) => CodeModal;
declare class CodeListModal extends SuggestModal<string> {
content: Map<string, Code>;
macros: SupportedMacro[];
codeModal: Class<CodeModal>;
constructor(app: App, content: Map<string, Code>, macros?: SupportedMacro[], codeModal?: Class<CodeModal>);
getSuggestions(query: string): string[] | Promise<string[]>;
renderSuggestion(value: string, el: HTMLElement): void;
onChooseSuggestion(item: string, evt: MouseEvent | KeyboardEvent): void;
}
declare class InputModal extends Modal {
content: ScriptObject;
replacements: Map<string, string>;
supportedMacros: SupportedMacro[];
codeModal: Class<CodeModal>;
datePicker: boolean;
constructor(app: App, content: ScriptObject, passedMacros?: SupportedMacro[] | null, codeModal?: Class<CodeModal>);
addMacros(activeNote: string | null, contentEl: HTMLElement): void;
addDatePicker(contentEl: HTMLElement): void;
onOpen(): Promise<void>;
onClose(): void;
}
declare class ErrorModal extends Modal {
text: string;
constructor(app: App, text: string);
onOpen(): void;
onClose(): void;
}
declare class CodeModal extends Modal {
code: ScriptObject;
constructor(app: App, code: ScriptObject);
onOpen(): void;
onClose(): void;
}
declare function ocr(app: App, file: TFile | null, worker: Worker | null): Promise<string | null>;
declare function initializeWorker(): Promise<Worker>;
declare function ocrMultiple(app: App, files: TFile[] | string[] | null, worker: Worker | null): Promise<Map<string, string> | null>;
declare const IP_REGEX: RegExp;
declare const IPv6_REGEX: RegExp;
declare const LOCAL_IP_REGEX: RegExp;
declare const MACRO_REGEX: RegExp;
declare const DOMAIN_REGEX: RegExp;
declare const HASH_REGEX: RegExp;
declare const SHA256_REGEX: RegExp;
declare const MD5_REGEX: RegExp;
declare const SHA1_REGEX: RegExp;
declare const FILE_REGEX: RegExp;
/**
* Encrypt a string using the Electron safe storage API.
* @param val the string to be encrypted.
* @returns the base64-encoded, encrypted string, or an empty string.
*/
declare function encryptString(val: string): string;
/**
* Decrypt a string using the Electron safe storage API.
* @param val an encrypted value.
* @returns the decrypted value, or an empty string.
*/
declare function decryptString(val: string): string;
/**
* Save private data to privateData.json.
* @param plugin an Obsidian plugin
* @param data the private data to save
*/
declare function savePrivateData(plugin: Plugin, data: Object): Promise<void>;
/**
* Load private data from privateData.json.
* @param plugin an Obsidian plugin
* @returns the plugin data contained in privateData.json
*/
declare function loadPrivateData(plugin: Plugin): Promise<Object | null>;
declare const TLD_URL = "https://data.iana.org/TLD/tlds-alpha-by-domain.txt";
/**
* Get a list of valid top-level domains from IANA.
* @returns a promise with the list of valid strings, or null if failed.
*/
declare function getValidTld(): Promise<string[] | null>;
/**
* @returns current local date as a string in format YYYY-MM-DD
*/
declare function todayLocalDate(): string;
/**
* @returns the local date/time in format `YYYY-MM-DD HH:SS`
*/
declare function localDateTime(): string;
interface folderPrefs {
year: boolean;
month: boolean;
quarter: boolean;
day: boolean;
}
/**
* Returns a string array with the folder structure for the current date based on user preferences
* Format: `YYYY/YYYY-QQ/YYYY-MM/YYYY-MM-DD`
*
* @param prefs booleans specifying whether to include certain portions in the structure
* @returns the folder structure for the current date
*/
declare function todayFolderStructure(prefs: folderPrefs): Array<string>;
/**
* Defangs IP addresses, e.g. `8.8.8.8` becomes `8.8.8[.]8`
* @param text a string containing IP addresses
* @returns input string with IP addresses defanged
*/
declare function defangIp(text: string): string;
/**
* Defangs domains preceded with http(s), e.g. `https://google.com`
* becomes `hxxps[://]google[.]com`
* @param text a string containing domain names
* @returns input string with domains defanged
*/
declare function defangDomain(text: string): string;
/**
* Defangs email addresses
* @param text a string containing email addresses
* @returns input string with email addresses defanged
*/
declare function defangEmail(text: string): string;
/**
* refang an IOC (domain, URL, IP, email address)
* @param text a string with defanged IOC(s)
* @returns the string with IOCs re-fanged
*/
declare function refangIoc(text: string): string;
/**
* Converts SHA256 hashes (or any 64 character hex string) to lowercase
* @param text a string
* @returns input string with SHA256 hashes converted to lowercase
*/
declare function lowerSha256(hash: string): string;
/**
* Converts MD5 hashes (or any 32 character hex string) to lowercase
* @param text a string
* @returns input string with MD5 hashes converted to lowercase
*/
declare function lowerMd5(text: string): string;
declare const dateTimeRegex: RegExp;
/**
* Converts a datetime string in the format `YYYY-MM-DD HH:MM:SS UTC`
* to the following: `YYYY-MM-DD at HH:MM:SS UTC`
* @returns input string with datetimes converted to "{date} at {time}"
*/
declare function friendlyDatetime(text: string): string;
/**
* Find the first match of a regex in the given string.
* @param text the text to search
* @param regex the regular expression to match
* @returns first match of a regex in the given string
*/
declare function findFirstByRegex(text: string, regex: RegExp): string | null;
/**
* Put a template around the given content.
* Supported macros:
* - {{title}} the note title
* - {{date}} the date in format YYYY-MM-DD
* - {{time}} the time in format HH:SS
* - {{content}} the content you want to replace'
* @param template the template
* @param content the content
* @param note the note to which it will be inserted
* @param contentMacro the string to replace content with @default "{{content}}"
*/
declare function replaceTemplateText(template: string, content: string, note: TFile, contentMacro?: string): string;
/**
* Extract macros in the format {{macro}}
* @param text
* @returns a unique list of macros in the text
*/
declare function extractMacros(text: string): string[];
/**
* Extracts matches for all of the given regular expressions.
* @param text the text to check against
* @param pattern the regex pattern(s) to evaluate
* @returns an array of strings that matched the given regex
*/
declare function extractMatches(text: string, pattern: RegExp | RegExp[]): string[];
/**
* Replace (1:1) keys with their associated values in the provided text.
* @param text the text in which to replace
* @param replacements the map of keys to values
* @returns the input with replaced text
*/
declare function replaceMacros(text: string, replacements: Map<string, string>): string;
/**
* Add unique values from the passed RegExpMatchArray to the given array of strings
* @param array an array of strings
* @param values a set of regex matches
* @returns the passed array with unique values added
*/
declare function addUniqueValuesToArray(array: string[], values: IterableIterator<RegExpMatchArray>): string[];
/**
* Parse code blocks and the headers before them
* @param content file content
* @returns a mapping of headers to code block content
*/
declare function parseCodeBlocks(content: string): Map<string, Code>;
declare const macroSeparator = "(?:\\s*[:=]\\s*|\\s+)";
declare const macroValue = "(((?:[^}\\s]*\\w[^}\\s]*)+))";
/**
* Constructs a regular expression to match values in the note based on the passed values
* and separator constants above
* @param macroRegex the macro name (like file, user, etc)
* @returns the constructed regular expression
*/
declare function constructMacroRegex(macroRegex: string | RegExp): RegExp;
/**
* Validate a domain against a list of valid top-level domains (TLD)
* @param domain the domain to validate
* @param validTld an array of valid TLD strings in uppercase
* @returns the boolean representation of the domain's validity
*/
declare function validateDomain(domain: string, validTld: string[]): boolean;
/**
* Removes duplicates from the passed array.
* @param array an array of strings
* @returns the array with duplicates removed
*/
declare function removeArrayDuplicates(array: string[]): string[];
declare function convertTime(timeString: string): number;
/**
* Validate a list of domains against a list of valid top-level domains (TLD)
* @param domains a list of domains to validate
* @param validTld a list of valid TLDs
* @returns domains with valid TLDs
*/
declare function validateDomains(domains: string[], validTld: string[]): string[];
/**
* Checks an IP address is local/private per RFC 1918
* @param ip an IPv4 address
* @returns a boolean representing whether the IP is local or not
*/
declare function isLocalIpv4(ip: string): boolean;
type IocType = 'hash' | 'ip' | 'domain';
/**
* Get the type of an IOC (hash, IP, domain)
* @param val an IOC value
* @returns a string representation of the IOC type (hash, ip, domain) or null
*/
declare function getIocType(val: string): IocType | null;
/**
* Check if a given folder exists
* @param rootPath the folder to start searching from
* @returns folder name, blank if not exists
*/
declare function checkFolderExistsRecursive(vault: Vault, folderName: string): Promise<string>;
/**
* Remove .obsidian config folder, .DS_Store file from a list of file/folder names
* @param files an array of file/folder names
* @returns the array with unnecessary files removed
*/
declare function removeDotObsidian(files: string[]): string[];
/**
* Creates a folder if it does not already exist.
* @param vault
*/
declare function createFolderIfNotExists(vault: Vault, folderName: string): Promise<void>;
/**
* Creates a note within the given vault.
* @param vault
* @param folderName
* @param noteTitle
* @returns the newly created note
*/
declare function createNote(vault: Vault, folderName: string, noteTitle: string): Promise<TFile>;
/**
* Get an array of the unresolved backlinks in a note.
* @param notePath the note to check
* @param app the current App class instance
* @param resolved whether or not you want resolved links
* @returns an array of strings
*/
declare function getBacklinks(notePath: string, app: App, resolved?: boolean): Array<string>;
/**
* Get an array of linked non-markdown (presumably attachment) files in a note.
* @param notePath the path of the note to check for attachment links
* @param app the current App class instance
*/
declare function getAttachments(notePath: string, app: App): Array<TFile>;
/**
* Get an array of linked file objects from a note.
* @param note the note to check for linked attachment files
* @param app the current App class instance
*/
declare function getAttachmentFiles(note: TFile, app: App): TFile[];
/**
* Append to the end of a note
* @param vault the current vault
* @param note the note to append to
* @param content the content to append
* @returns the modified content
*/
declare function noteAppend(vault: Vault, note: TFile, content: string): Promise<string>;
/**
* Replace content in a note by regular expression
* @param vault the current vault
* @param note the note to append to
* @param regex the pattern to match for replacement
* @param content the content to replace with
* @returns the modified content
*/
declare function noteReplace(vault: Vault, note: TFile, regex: RegExp, content: string): Promise<string>;
/**
* Opens the note in a new tab
* @param app the current App class instance
* @param note the file you would like to open
*/
declare function openNote(app: App, note: TFile): void;
declare function addButtonContainer(workspace: Workspace, file: TFile, className: string, rootFolder?: string): HTMLDivElement | undefined;
declare function addButtonToContainer(el: HTMLElement, buttonText: string): ButtonComponent;
declare function getActiveNoteContent(app: App): Promise<string | null>;
declare function virusTotalRequest(val: string, key: string, template?: string): Promise<string | null>;
interface GeminiRequest {
contents: {
parts: GeminiMessagePart[];
}[];
}
interface GeminiMessagePart {
text?: string;
inline_data?: {
mime_type: string;
data: string;
};
role?: string;
}
interface GeminiConfig {
baseUrl?: string;
model?: string;
apiKey: string;
}
declare class GeminiClient {
protected baseUrl: string;
protected model: string;
protected apiKey: string;
constructor(config: GeminiConfig);
generateContentRequest(requestBody: GeminiRequest): Promise<string>;
/**
*
* @param prompt prompt
* @param image an array of base64-encoded image
* @returns the model response
*/
imageRequest(prompt: string, images: string[]): Promise<string>;
}
type Role = 'system' | 'user' | 'assistant' | 'developer' | 'tool';
interface ToolCall {
id: string;
type: string;
function: {
name: string;
arguments: string;
};
}
interface Message {
role: Role;
content?: string;
tool_call_id?: string;
tool_calls?: ToolCall[];
}
interface Tool {
type: 'function';
function: FunctionConfig;
}
interface FunctionConfig {
name: string;
description?: string;
parameters: {
type: "object";
properties: Record<string, unknown>;
};
required?: Array<string>;
}
interface ChatCompletionRequest {
model?: string;
messages: Array<Message>;
tools?: Array<Tool>;
}
interface ChatCompletionResponse {
id: string;
object: string;
created: number;
model: string;
choices: Array<{
index: number;
message: {
role: Role;
content?: string;
tool_calls?: Array<ToolCall>;
};
}>;
}
interface OpenAiClientConfig {
baseUrl?: string;
model?: string;
apiKey?: string;
headers?: Record<string, string>;
systemMessage?: string;
tools?: Tool[];
}
/**
* An OpenAI-compatible API client leveraging Obsidian's built-in request function.
*/
declare class OpenAICompatibleClient {
protected baseURL: string;
protected apiKey: string;
protected headers: Record<string, string>;
protected model: string;
private messageHistory;
private systemMessage?;
private tools?;
constructor(config: OpenAiClientConfig);
/**
* Send a user role message to the assistant.
* @param content the contents of the message
* @returns a ChatCompletionResponse object
*/
chat(content: string): Promise<ChatCompletionResponse>;
/**
* Make a conversation request with the current message history.
* @returns a ChatCompletionResponse object
*/
private conversationRequest;
/**
* Clear the current chat history.
*/
clearHistory(): void;
/**
* Get the current chat history.
* @returns an array of messages
*/
getHistory(): Message[];
/**
* Set the system message prompt
* @param message the system message prompt
*/
setSystemPrompt(message: string): void;
/**
* Set the client base URL
* @param url an OpenAI-compatible API base URL
*/
setBaseUrl(url: string): void;
/**
* Add an HTTP header to be sent with requests
* @param key header key
* @param value header value
*/
addHeader(key: string, value: string): void;
/**
* Remove an HTTP header
* @param key header key to be removed
*/
removeHeader(key: string): void;
/**
* Add a tool to the client
* @param func a FunctionConfig object
*/
addTool(func: FunctionConfig): void;
/**
* Provide the assistant with a tool response
* @param id a tool_call_id
* @param content the contents of the tool response
* @returns a ChatCompletionRequest object
*/
toolResponse(id: string, content: string): Promise<ChatCompletionResponse>;
}
interface OllamaBaseRequest {
model: string;
stream?: boolean;
keep_alive?: string;
}
interface OllamaGenerationRequest extends OllamaBaseRequest {
prompt: string;
images?: string[];
suffix?: string;
}
interface OllamaChatCompletionRequest extends OllamaBaseRequest {
messages: OllamaMessage[];
}
interface OllamaBaseResponse {
model: string;
created_at: string;
done: boolean;
total_duration?: number;
load_duration?: number;
prompt_eval_count?: number;
prompt_eval_duration?: number;
eval_count?: number;
eval_duration?: number;
}
interface OllamaGenerationResponse extends OllamaBaseResponse {
response: string;
}
interface OllamaChatCompletionResponse extends OllamaBaseResponse {
message: OllamaMessage;
}
interface OllamaMessage {
role: 'assistant' | 'user' | 'system' | 'tool';
content: string;
images?: string[];
}
interface OllamaConfig {
baseUrl?: string;
model?: string;
stream?: boolean;
systemMessage?: string;
}
/**
* An Ollama API client leveraging Obsidian's built-in request function.
*/
declare class OllamaClient {
protected baseUrl: string;
protected model: string;
private stream;
private messageHistory;
private systemMessage?;
constructor(config: OllamaConfig);
/**
* Send a user role message to the assistant.
* @param content the contents of the message
* @returns an OllamaChatCompletionResponse object
*/
chat(content: string, images?: string[]): Promise<OllamaChatCompletionResponse>;
/**
* Make a single generation request with a text prompt.
* @param prompt prompt
* @param suffix an optional suffix to the model's response
* @returns an OllamaGenerationResponse object
*/
generate(prompt: string, suffix?: string): Promise<OllamaGenerationResponse>;
/**
* Make a single generation request with image(s).
* @param prompt prompt
* @param images an array of base64-encoded images
* @returns an OllamaGenerationResponse object
*/
generateWithImages(prompt: string, images: string[]): Promise<OllamaGenerationResponse>;
/**
* Make a conversation request with the current message history.
* @returns an OllamaChatCompletionResponse object
*/
private conversationRequest;
/**
* Make a generation request with the provided prompt and optional images.
* @returns an OllamaChatCompletionResponse object
*/
private generationRequest;
/**
* Clear the current chat history.
*/
clearHistory(): void;
}
declare class GeminiOcrProcessor extends BaseOcrProcessor {
private client;
constructor(key: string, enableDebug?: boolean);
protected _performOcr(job: OcrJobData): Promise<string>;
}
declare class TesseractOcrProcessor extends BaseOcrProcessor {
private worker;
constructor(worker: Worker, enableDebug?: boolean);
protected _performOcr(job: OcrJobData): Promise<string>;
shutdown(): Promise<void>;
}
/**
* Reads the contents of an image file into a Buffer.
* @param app Obsidian app instance
* @param file an Obsidian TFile
* @returns the image in a Buffer format
*/
declare function readImageFile(app: App, file: TFile): Promise<Buffer>;
/**
* base64 encodes an image file
* @param app Obsidian app instance
* @param file an Obsidian TFile
* @returns the base64-encoded image
*/
declare function encodeImageFile(app: App, file: TFile): Promise<string>;
export { BaseOcrProcessor, CENSYS_SEARCH, type ChatCompletionRequest, type ChatCompletionResponse, type Code, CodeListModal, CodeModal, CyberPlugin, type CyberPluginEvent, type CyberPluginSettings, DDG_SEARCH, DOMAIN_EXCLUSIONS, DOMAIN_REGEX, ErrorModal, FILE_REGEX, type FunctionConfig, GOOGLE_SEARCH, GeminiClient, type GeminiConfig, GeminiOcrProcessor, type GroupedIndicators, HASH_REGEX, type IEventEmitter, type IOcrProcessor, type IOcrProvider, IPDB_SEARCH, IP_EXCLUSIONS, IP_REGEX, IP_REGEX as IPv4_REGEX, IPv6_REGEX, type Indicator, type IndicatorExclusion, type IndicatorExclusions, IndicatorSource, IndicatorType, InputModal, type IocType, LOCAL_IP_REGEX, MACRO_REGEX, MD5_REGEX, Matcher, type Message, type OcrCacheChecker, type OcrCompletePayload, type OcrErrorPayload, type OcrJobData, type OcrProgressPayload, OcrProvider, type OcrProviderEvent, type OllamaChatCompletionRequest, type OllamaChatCompletionResponse, OllamaClient, type OllamaGenerationRequest, type OllamaGenerationResponse, OpenAICompatibleClient, type OpenAiClientConfig, PATTERN_KEYS, type ParsedIndicators, type PatternKey, type Role, SHA1_REGEX, SHA256_REGEX, SHODAN_SEARCH, SPUR_SEARCH, ScriptObject, type SearchSite, type SupportedMacro, TLD_URL, TesseractOcrProcessor, type Tool, type ToolCall, URLSCAN_SEARCH, VT_SEARCH, addButtonContainer, addButtonToContainer, addUniqueValuesToArray, appendToEnd, censysSearch, checkFolderExistsRecursive, constructMacroRegex, convertTime, createFolderIfNotExists, createNote, datePickerSettingEl, dateTimeRegex, ddgSearch, decryptString, defangDomain, defangEmail, defangIp, defaultSites, encodeImageFile, encryptString, extractMacros, extractMatches, filterExclusions, findFirstByRegex, type folderPrefs, friendlyDatetime, getActiveNoteContent, getAttachmentFiles, getAttachments, getBacklinks, getIndicatorMatches, getIocType, getMatches, getValidTld, googleSearch, groupIndicators, initializeWorker, ipdbSearch, isLocalIpv4, loadPrivateData, localDateTime, lowerMd5, lowerSha256, macroSeparator, macroValue, noteAppend, noteReplace, ocr, ocrMultiple, openDetails, openNote, parseCodeBlocks, processExclusions, readImageFile, refangIoc, removeArrayDuplicates, removeDotObsidian, removeElements, replaceMacros, replaceTemplateText, savePrivateData, shodanSearch, spurSearch, supportedMacros, todayFolderStructure, todayLocalDate, transformSelectedText, urlscanSearch, validateDomain, validateDomains, virusTotalRequest, vtSearch };