
桌面应用【免费下载链接】QOwnNotesQOwnNotes is a plain-text file notepad and todo-list manager with Markdown support and Nextcloud / ownCloud integration.项目地址https://gitcode.com/gh_mirrors/qo/QOwnNotes点击查看免费下载本指南以 QOwnNotes 官方脚本文档中的 Hooks 章节为核心系统讲解 QOwnNotes 脚本引擎暴露的全部 22 个事件钩子Hook。这些钩子以约定的 QML 函数名形式存在脚本引擎会在笔记存储、笔记打开、媒体插入、标签增删、Markdown 预览生成、文本加密、AI 后端配置加载等关键节点自动回调脚本。读完本文你将掌握每个 Hook 的准确函数签名、参数语义、返回值约定以及如何借助docs/scripting/examples/下的官方示例快速实现自定义笔记工作流。一、Hooks 机制与脚本定义方式QOwnNotes 的脚本基于 QMLQt Meta Language脚本文件以.qml结尾通常以import QtQml 2.0和import QOwnNotesTypes 1.0开头主体是一个QtObject或Script对象。所谓 Hook就是在脚本对象中定义一个名字固定的函数脚本引擎会在特定事件发生时通过反射机制调用它。从源码实现看脚本引擎的调用逻辑集中在 src/services/scriptingservice.cpp引擎通过methodExistsForObject(object, hookName(参数签名))检测脚本对象是否定义了对应函数例如onNoteStored(QVariant)、noteOpenedHook(QVariant)检测通过后使用QMetaObject::invokeMethod()反射调用脚本函数并传入QVariant类型的参数每次调用都会经过logScriptHookTiming()记录耗时便于在脚本日志中排查性能问题。因此只要在脚本对象中按文档约定定义同名函数即可被自动识别无需注册或声明。需要注意的是Hook 名称及其参数个数是约定好的定义错误如参数数量不匹配将导致methodExistsForObject检测失败、该脚本的 Hook 静默失效。二、笔记生命周期 Hooks这类 Hook 覆盖笔记从创建、打开、存储到在列表中显示名称的完整生命周期。onNoteStored笔记被写入磁盘后调用。文档明确指出你不能在此修改已存储的笔记——因为你很可能正在同时手工编辑它们修改会造成混乱。/** * This function is called when a note gets stored to disk * You cannot modify stored notes, that would be a mess since * you are most likely editing them by hand at the same time * * param {NoteApi} note - the note object of the stored note */ function onNoteStored(note);典型用法是日志记录或触发后续动作。参见示例 on-note-opened.qml以及 example.qml 中对note.id、note.name、note.fileName和note.tagNames()的打印演示。noteOpenedHook笔记被打开之后调用常用于读取笔记内容、注册通知等。/** * This function is called after a note was opened * * param {NoteApi} note - the note object that was opened */ function noteOpenedHook(note);示例 on-note-opened.qml 展示了通过note.fullNoteFilePath记录笔记完整路径的做法。源码中该 Hook 的调用见 src/services/scriptingservice.cpp 中noteOpenedHook(QVariant)的检测与分发逻辑。noteDoubleClickedHook笔记列表中的笔记被双击之后调用典型场景是把双击行为重定向到外部编辑器。/** * This function is called after a note was double clicked * * param {NoteApi} note - the note object that was clicked */ function noteDoubleClickedHook(note);示例 external-note-open.qml 实现了完整的双击用外部编辑器打开流程它通过settingsVariables注册一个executablePath设置项然后在 Hook 内调用script.startDetachedProcess(executablePath, [note.fullNoteFilePath])启动外部程序。handleNoteNameHook决定笔记在列表中显示名称时调用允许修改展示名称。/** * This function is called when the note name is determined for a note * * It allows you to modify the name of the note that is viewed * * Return an empty string if the name of the note should not be modified * * param {NoteApi} note - the note object of the stored note * return {string} the name of the note */ function handleNoteNameHook(note);文档提示该名称主要用于列表展示如果开启了使用文件名作为笔记名的设置则不建议使用此 Hook。源码侧ScriptingService::handleNoteNameHookExists()见 src/services/scriptingservice.cpp被 src/managers/noteindexmanager.cpp 用来决定索引构建时是否调用该 Hook。示例 example.qml 中简单返回note.name some text演示了追加文本的效果。handleNewNoteHeadlineHook新笔记创建之前调用用于修改标题是实现笔记模板的核心 Hook。/** * This function is called before a note is created * * It allows you to modify the headline of the note before it is created * Note that you have to take care about a unique note name, otherwise * the new note will not be created, it will just be found in the note list * * You can use this function for creating note templates * * param headline text that would be used to create the headline * return {string} the headline of the note */ function handleNewNoteHeadlineHook(headline);文档特别警告你需要自己保证笔记名唯一否则新笔记不会真正创建只会出现在笔记列表中。示例 custom-new-note-headline.qml 演示了在原标题后追加自定义文本并生成下划线Markdown H1 的 Setext 写法的模板效果。handleNoteTextFileNameHook在启用允许笔记文件名与标题不同设置时笔记存储到磁盘前调用用于自定义文件名。/** * This function is called when a note gets stored to disk if * Allow note file name to be different from headline is enabled * in the settings * * It allows you to modify the name of the note file * Keep in mind that you have to care about duplicate names yourself! * * Return an empty string if the file name of the note should * not be modified * * param {NoteApi} note - the note object of the stored note * return {string} the file name of the note */ function handleNoteTextFileNameHook(note);同样需要自己处理重名问题。示例 use-tag-names-in-filename.qml 展示了完整实战以笔记首行作为文件名基础再把note.tagNames()得到的标签名拼接为[tag1] [tag2]后缀并用script.noteExistsByFileName(fileName .md, note.id)检测重名。源码实现见 src/services/scriptingservice.cpp 中handleNoteTextFileNameHook(QVariant)的调用分支。三、内容插入与剪贴板 Hooks这类 Hook 在向当前笔记插入媒体、附件、粘贴内容时触发。insertMediaHook媒体文件插入当前笔记时调用可改写最终写入笔记的 Markdown 文本。若多个脚本都定义了此函数第一个返回非空字符串的脚本胜出。/** * param fileName string the file path of the source media file before it was copied to the media folder * param markdownText string the markdown text of the media file, e.g. my-image * return string the new markdown text of the media file */ function insertMediaHook(fileName, markdownText);示例见 example.qml。源码中通过insertMediaHook(QVariant,QVariant)签名检测后逐个脚本调用见 src/services/scriptingservice.cpp。insertAttachmentHook附件文件插入当前笔记时调用规则与insertMediaHook相同多个脚本定义时首个返回非空字符串者优先。/** * param fileName string the file path of the source attachment file before it was copied to the attachment folder * param markdownText string the markdown text of the attachment file, e.g. my-file.txt * return string the new markdown text of the attachment file */ function insertAttachmentHook(fileName, markdownText);示例见 example.qml。insertingFromMimeDataHook使用Ctrl Shift V向笔记粘贴 HTML 或媒体文件时调用用于把剪贴板内容转换为自定义文本插入。/** * This function is called when html or a media file is pasted to a note with Ctrl Shift V * * param text text of the QMimeData object * param html html of the QMimeData object * returns the string that should be inserted instead of the text from the QMimeData object */ function insertingFromMimeDataHook(text, html);返回的字符串将替换QMimeData对象中的原始文本。两个典型示例insert-headline-with-link-from-github-url.qml检测剪贴板中的 GitHub Issue URL用script.downloadUrlToString(text)抓取页面并解析标题拼装成## 标题 链接的 Markdown 后返回note-text-from-5pm-mail.qml处理 5pm 邮件文本的格式化粘贴。fetchUrlTitleHook在链接对话框中QOwnNotes 尝试抓取网页标题之前调用。多脚本定义时首个返回非空字符串者优先。/** * param url string the URL whose title should be fetched * return string the title for the URL, or an empty string to let QOwnNotes fetch it */ function fetchUrlTitleHook(url);返回空字符串表示交给 QOwnNotes 自己去抓取。示例 fetch-url-title-with-kanboard-cli.qml 是一个完整的第三方集成案例它注册kanboardCliPath与kanbanUrlPrefixes两个设置变量通过正则从配置的前缀 URL 中提取 Kanboard 任务 ID再调用script.startSynchronousProcess(kanboardCliPath, [--json, task, get, taskId])获取 JSON 并解析出任务标题返回。四、Markdown 预览与导出 Hooks这类 Hook 围绕Markdown → HTML转换管线工作分别作用于转换前与转换后且都支持区分预览与导出场景。preNoteToMarkdownHtmlHookMarkdown 转 HTML之前调用允许修改送入转换器的 Markdown 内容。多脚本可配合使用例如把 LaTeX 数学公式或 mermaid 图渲染成预览用的图形表示。注意此过程不会改动笔记本身。/** * This function is called before the markdown html of a note is generated * * It allows you to modify what is passed to the markdown to html converter * * The function can for example be used in multiple scripts to render code (like LaTeX math or mermaid) * to its graphical representation for the preview * * The note will not be changed in this process * * param {NoteApi} note - the note object * param {string} markdown - the markdown that is about to being converted to html * param {bool} forExport - true if the html is used for an export, false for the preview * return {string} the modified markdown or an empty string if nothing should be modified */ function preNoteToMarkdownHtmlHook(note, markdown, forExport);示例 preview-styling.qml 中简单用markdown.replace(- special text, - something else)演示了文本改写。源码侧该 Hook 同时兼容两参数旧签名preNoteToMarkdownHtmlHook(note, markdown)与三参数新签名若检测到旧签名会输出qWarning提示改用新签名见 src/services/scriptingservice.cpp。noteToMarkdownHtmlHookMarkdown 转 HTML之后、渲染之前调用允许修改最终 HTML。这是定制预览样式的主要入口。/** * This function is called when the markdown html of a note is generated * * It allows you to modify this html * This is for example called before by the note preview * * The function can be used in multiple scripts to modify the html of the preview * * param {NoteApi} note - the note object * param {string} html - the html that is about to being rendered * param {bool} forExport - true if the html is used for an export, false for the preview * return {string} the modified html or an empty string if nothing should be modified */ function noteToMarkdownHtmlHook(note, html, forExport);预览所支持的 CSS 样式子集受 Qt 富文本引擎限制完整支持列表见 Qt 官方 Supported HTML Subset 文档。两个示例preview-styling.qml根据forExport分别注入不同 CSS预览用红色缩进、导出用蓝色缩进到/style之前example.qml在body之后插入自定义 H1 标题和分隔线。源码实现同样兼容旧签名noteToMarkdownHtmlHook(note, html)并在使用旧签名时输出qWarning提示升级为noteToMarkdownHtmlHook(note, html, forExport)见 src/services/scriptingservice.cpp。五、加密 Hook自定义加解密方案encryptionHook文本需要加密或解密时调用允许用任意算法或对接外部程序实现自定义加密。/** * This function is called when text has to be encrypted or decrypted * * param text string the text to encrypt or decrypt * param password string the password * param decrypt bool if false encryption is demanded, if true decryption is demanded * return the encrypted decrypted text */ function encryptionHook(text, password, decrypt);三个官方示例覆盖了不同思路encryption-keybase.qml调用 Keybase 外部程序完成加解密encryption-pgp.qml对接 PGP/GPG 工具链encryption-rot13.qml纯 JS 实现 ROT13 变换并在init()中调用script.encryptionDisablePassword()禁用密码对话框——注意 ROT13 不依赖密码所以 password 参数可以忽略。六、标签系统 Hooks自定义笔记标签机制QOwnNotes 允许你用脚本完全接管标签的增删改查例如在笔记文本中使用tag1、tag2、tag3这样的特殊文本作为标签。noteTaggingHook在标签被添加、移除、重命名或需要列出笔记标签时调用。只要任意已激活脚本实现了该函数笔记标签处理就会交给它接管。/** * Handles note tagging for a note * * This function is called when tags are added to, removed from or renamed in * a note or the tags of a note should be listed * * param note * param action can be add, remove, rename or list * param tagName tag name to be added, removed or renamed * param newTagName tag name to be renamed to if action rename * return note text string or string-list of tag names (if action list) */ function noteTaggingHook(note, action, tagName, newTagName);文档明确了接管后的 UI 行为细节初次从笔记中导入tag形式的标签并覆盖当前标签分配时不会丢失标签树只是失去旧的标签↔笔记关联标签仍可移动进其他标签若标签树中有多个同名标签将分配第一个命中的标签给笔记添加标签 向笔记文本追加该标签从笔记移除标签 从文本中删除该标签在标签列表中删除标签会从所有相关笔记中删除在标签列表中重命名标签会同步更新笔记文本笔记列表中的批量打标签 / 批量移除标签都会作用于笔记文本在标签面板中移动标签时应用会对所有选中标签及其子标签在所有笔记上触发一系列add/remove动作。完整实现见 note-tagging.qmllist动作用正则\B([^\s,])提取标签名并去重add动作检查标签不存在后追加\ntagNameremove/rename用转义后的正则替换文本。::: warning 务必让list动作足够快——每次笔记文件夹或标签树重载时它都会对每一条笔记执行一次也就是说每当你发现mainwindow.cpp中出现reloadTagTree调用见 src/mainwindow.cpp 中MainWindow::reloadTagTree()及其调用点时list都会被批量触发。 :::noteTaggingByObjectHook与noteTaggingHook类似但不局限于标签树根部的标签名——你可以使用整棵标签树而不是只能操作一个标签列表。区别在于参数从标签名变为TagApi对象list动作需要返回标签 ID 列表而非标签名列表这意味着你需要在list中自行创建缺失的标签才能返回已存在的标签 ID。/** * Handles note tagging for a note * * This function is called when tags are added to, removed from or renamed in * a note or the tags of a note should be listed * * param note * param action can be add, remove, rename or list * param tag to be added, removed or renamed * param newTagName tag name to be renamed to if action rename * return note text string or string-list of tag ids (if action list) */ function noteTaggingByObjectHook(note, action, tag, newTagName);示例 note-tagging-by-object.qml 展示了进阶用法list动作中通过script.getTagByNameBreadcrumbList([level1a, level2b, level3b])按面包屑路径查找标签对象再用tag.fetchByName(tagName)解析文本中的tag并收集tag.idtagId 0表示标签不存在示例中以TODO: create tag注释提示需要自行创建。源码中ScriptingService::noteTaggingHookExists()同时检测noteTaggingHook与noteTaggingByObjectHook任一存在见 src/services/scriptingservice.cpp而 src/managers/tagmanager.cpp 中大量分支如第 477 行先尝试noteTaggingByObjectHook据此决定走脚本标签引擎还是内置标签引擎。七、编辑器增强 HooksautocompletionHook自动补全被触发时例如按下Ctrl Space调用返回要追加到补全列表的字符串列表。/** * Calls the autocompletionHook function for all script components * This function is called when autocompletion is invoked in a note * * return QStringList of text for the autocomplete list */ function callAutocompletionHook();示例 autocompletion.qml 实现了输入前缀时补全标签的实用功能通过script.noteTextEditCurrentWord(true)获取当前单词含再调用script.searchTagsByName(word.substr(1))做子串搜索并返回标签列表。highlightingHook语法高亮期间对编辑器的每个文本块调用允许实现超越静态正则规则的、动态且上下文感知的高亮。::: warning 此 Hook 调用极其频繁每次按键都会对所有可见文本块执行实现必须保持高效。如果只需要静态正则高亮请优先使用addHighlightingRule见 webpage/src/scripting/methods-and-objects.md#adding-a-highlighting-rule-for-the-editor或支持自定义颜色与样式的addHighlightingRule变体。 :::/** * This function is called for each text block during syntax highlighting. * It allows context-aware, dynamic highlighting. * * param text {QString} the text of the current block being highlighted * param previousBlockState {int} the highlighter state of the previous block * (-1 if this is the first block) * return {Array} an array of highlight range objects, each with: * start {int} - start position in the text * length {int} - number of characters to highlight * state {int} - the HighlighterState to use (optional, -1 for custom only) * foregroundColor {string} - foreground color name or hex (optional) * backgroundColor {string} - background color name or hex (optional) * bold {bool} - bold font weight (optional) * italic {bool} - italic font style (optional) * underline {bool} - underline the text (optional) * fontSize {int} - font point size (optional) */ function highlightingHook(text, previousBlockState) { var highlights []; // Example: highlight all occurrences of FIXME with red bold underline var re /FIXME/g; var match; while ((match re.exec(text)) ! null) { highlights.push({ start: match.index, length: match[0].length, foregroundColor: #ff0000, underline: true, bold: true, }); } return highlights; }返回数组中的每个对象描述一个高亮区间start/length定位区间state可复用内置高亮状态-1表示仅用自定义格式其余字段为可选的自定义颜色、字重、斜体、下划线与字号。源码侧src/helpers/qownnotesmarkdownhighlighter.cpp 在每个文本块高亮时调用该 Hook仅当highlightingHookExists()为真而该存在性标志在脚本引擎加载时被缓存以避免重复反射检测见 src/services/scriptingservice.cpp 中_highlightingHookExists的初始化。两个示例highlighting.qml同时演示静态规则addHighlightingRule包括自定义颜色映射foregroundColor/backgroundColor/bold/italic与动态 Hook高亮所有FIXMEcustom-highlighting.qml进一步的自定义高亮示例。八、外部集成与窗口/布局/进程 HookswebsocketRawDataHook浏览器扩展 QOwnNotes Web Companion 通过浏览器上下文菜单发送数据时调用。/** * param requestType can be page or selection * param pageUrl the url of the webpage where the request was made * param pageTitle the page title of the webpage where the request was made * param rawData the data that was transmitted, html for requestType page or plain text for requestType selection * param screenshotDataUrl the data url of the screenshot of the webpage where the request was made * return true if data was handled by a hook */ function callHandleWebsocketRawDataHook(requestType, pageUrl, pageTitle, rawData, screenshotDataUrl);返回true表示数据已被某个 Hook 处理。示例 websocket-raw-data-selection-in-note.qml 只处理selection请求用script.noteTextEditWrite(rawData)把网页选中文本写入当前笔记后返回truelayouts.qml 则演示了与窗口布局的联动。源码调用入口为ScriptingService::callHandleWebsocketRawDataHook()见 src/services/scriptingservice.cpp。onDetachedProcessCallback通过startDetachedProcess启动的后台外部进程脚本线程执行完毕时回调。详见 webpage/src/scripting/methods-and-objects.md#starting-an-external-program-in-the-background。/** * This function is called when a script thread is done executing. * Hint: thread[1]0 helps to determine if a bulk of started processes for a certain identifier is done. * * param {QString} callbackIdentifier - the provided id when calling startDetachedProcess() * param {QString} resultSet - the result of the process * param {QVariantList} cmd - the entire command array [0-executablePath, 1-parameters, 2-exitCode] * param {QVariantList} thread - the thread information array [0-passed callbackParameter, 1-remaining threads for this identifier] */ function onDetachedProcessCallback(callbackIdentifier, resultSet, cmd, thread);关键提示thread[1]表示同一callbackIdentifier下剩余未完成的线程数thread[1] 0可用来判断一批进程是否全部执行完毕。示例 callback.qml 在init()中批量启动 100 个sleep进程全部使用callback-example标识符在回调中通过thread[1]追踪批次进度、thread[0]取回传入的callbackParameter、cmd[1]读取进程参数。该 Hook 的调用位于 src/services/scriptingservice.cpp 中onDetachedProcessCallback(QVariant,QVariant,QVariant,QVariant)的分发分支。windowStateChangedHook窗口状态变化事件触发后调用。/** * This function is called after a WindowStateChange event was triggered * * param {QString} windowState - the new window state, parameter value can be minimized, maximized, fullscreen, active or nostate */ function windowStateChangedHook(windowState);windowState可取minimized、maximized、fullscreen、active或nostate。示例 window-state-changed.qml 仅打印状态字符串。layoutSwitchedHook窗口布局Layout切换时调用。/** * This function is called when layouts are switched * * param oldUuid old uuid of layout * param newUuid new uuid of layout */ function layoutSwitchedHook(oldUuid, newUuid);参数为切换前后的布局 UUID。示例见 layouts.qml。源码检测签名为layoutSwitchedHook(QVariant,QVariant)见 src/services/scriptingservice.cpp。openAiBackendsHookOpenAI 服务配置被重载时调用例如脚本引擎重载时也会触发。它用于为自定义 OpenAI 后端提供配置——包括自建 OpenAI API 兼容的 LLM如 ChatGPT、Claude或 Ollama 这类本地推理系统。/** * This function is called when the OpenAI service config is reloaded * It returns a list of objects with config parameters for new OpenAI backends */ function openAiBackendsHook() { return [ { id: my-custom-ai, name: My Custom AI, baseUrl: http://localhost:5000, apiKey: kDFJkjk3asdm, models: [gpt-3.5-turbo, gpt-4.0-turbo], }, { id: my-custom-ai2, name: My Custom AI 2, baseUrl: http://localhost:5001, apiKey: lOikf7eNdb9, models: [gpt-3.5-turbo2, gpt-4.0-turbo2], }, ]; }每个后端对象包含id、name、baseUrl、apiKey与models列表。文档提示可以使用注册脚本设置变量机制把后端配置存入脚本设置实现可配置化——参见 webpage/src/scripting/methods-and-objects.md#registering-script-settings-variables。完整示例 custom-openai-backends.qml 额外演示了对接 Groq 云服务的https://api.groq.com/openai/v1/chat/completions后端。源码检测签名为openAiBackendsHook()无参数见 src/services/scriptingservice.cpp。九、Hooks 使用约定与性能注意点综合全部 22 个 Hook可以总结出 QOwnNotes 脚本引擎的统一约定返回空字符串表示不做任何修改/不接管insertMediaHook、insertAttachmentHook、fetchUrlTitleHook、handleNoteTextFileNameHook、handleNoteNameHook、preNoteToMarkdownHtmlHook、noteToMarkdownHtmlHook、noteTaggingHook等均遵循此约定第一个返回非空字符串者胜出的竞争规则insertMediaHook、insertAttachmentHook、fetchUrlTitleHook在多脚本场景下由首个非空返回值决定结果Hook 被激活即整体接管如noteTaggingHook一旦有脚本实现标签处理就切换到脚本引擎websocketRawDataHook返回true即表示数据已被处理性能敏感场景noteTaggingHook的list动作在每次笔记文件夹/标签树重载时对所有笔记执行必须够快highlightingHook在每次按键时对所有可见文本块执行应尽量精简逻辑静态规则优先用addHighlightingRule。从源码实现src/services/scriptingservice.cpp看所有 Hook 都经由统一的反射检测与分发框架处理并记录每次调用的耗时——这既是脚本引擎稳定性的保证也为脚本作者排查哪个 Hook 拖慢了界面提供了日志依据。参考示例速查Hook官方示例docs/scripting/examples/onNoteStored / noteOpenedHookon-note-opened.qml、example.qmlnoteDoubleClickedHookexternal-note-open.qmlinsertMediaHook / insertAttachmentHook / insertingFromMimeDataHookexample.qml、insert-headline-with-link-from-github-url.qml、note-text-from-5pm-mail.qmlfetchUrlTitleHookfetch-url-title-with-kanboard-cli.qmlhandleNoteTextFileNameHookuse-tag-names-in-filename.qmlhandleNewNoteHeadlineHookcustom-new-note-headline.qmlpreNoteToMarkdownHtmlHook / noteToMarkdownHtmlHookpreview-styling.qml、example.qmlencryptionHookencryption-keybase.qml、encryption-pgp.qml、encryption-rot13.qmlnoteTaggingHooknote-tagging.qmlnoteTaggingByObjectHooknote-tagging-by-object.qmlautocompletionHookautocompletion.qmlhighlightingHookhighlighting.qml、custom-highlighting.qmlwebsocketRawDataHookwebsocket-raw-data-selection-in-note.qml、layouts.qmlonDetachedProcessCallbackcallback.qmlwindowStateChangedHookwindow-state-changed.qmllayoutSwitchedHooklayouts.qmlopenAiBackendsHookcustom-openai-backends.qmlHook 之外的脚本方法如startDetachedProcess、addHighlightingRule、设置变量注册、NoteApi/TagApi对象属性等可进一步查阅 methods-and-objects.md 与 classes.md配合本文的 Hook 清单即可组合出完整的自定义脚本功能。赞分享桌面应用【免费下载链接】QOwnNotesQOwnNotes is a plain-text file notepad and todo-list manager with Markdown support and Nextcloud / ownCloud integration.项目地址https://gitcode.com/gh_mirrors/qo/QOwnNotes点击查看免费下载相关推荐Qtile 内置钩子Built-in Hooks完全指南订阅机制、全部事件与实战示例Qtile 内置钩子Built in Hooks完全指南订阅机制、全部事件与实战示例 本文围绕 Qtile 事件钩子系统展开系统讲解 Qtile 内置的桌面应用操作系统Kimi Code CLI Hooks 钩子机制实战指南事件驱动脚本扩展与安全拦截Kimi Code CLI Hooks 钩子机制实战指南事件驱动脚本扩展与安全拦截 导读 Hooks钩子是 Kimi Code CLI 提供的自动化触发机AI Agent代码智能体人工智能大模型CLIchangedetection.io事件系统钩子函数与回调机制changedetection.io事件系统钩子函数与回调机制 引言实时监控背后的技术核心 你是否曾经遇到过这样的场景需要实时监控网站内容变化但传统轮询后端AI 应用网页爬虫创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。