3步打造专属AI助手:Jan插件开发实战指南
你是否曾想过给离线AI助手Jan添加个性化功能?比如让它自动整理聊天记录,或者根据你的工作习惯定制回复风格?本文将通过实战案例,带你从零构建一个"智能笔记助手"插件,让Jan成为你独一无二的AI工作伙伴。
插件开发前的准备工作
在开始编写代码前,我们需要先了解Jan的插件系统架构。Jan采用模块化设计,所有功能都通过插件实现,目前已有多个官方插件可供参考:
- assistant-extension:提供助手的增删改查功能,核心实现位于src/index.ts
- conversational-extension:处理消息和对话状态管理,聊天逻辑在src/index.ts
- llamacpp-extension:本地模型推理支持,通过llama.cpp实现离线运行
Jan插件本质上是一个独立的模块,遵循特定的目录结构和接口规范。所有插件代码都放在项目的extensions目录下,每个插件拥有自己的文件夹和完整的功能实现。
开发环境搭建
首先确保你的开发环境满足以下要求:
- Node.js 16+ 和 yarn 包管理器
- TypeScript 基础知识
- 对Jan项目结构的基本了解
创建插件前,建议先克隆Jan项目代码库:
git clone https://gitcode.com/GitHub_Trending/ja/jan.git
cd jan
yarn install
第一步:创建插件基础结构
我们将创建一个名为note-assistant-extension的插件,用于实现智能笔记功能。按照Jan的插件规范,我们需要先建立标准的目录结构。
创建目录和配置文件
在extensions目录下新建插件文件夹并初始化:
cd extensions
mkdir note-assistant-extension
cd note-assistant-extension
yarn init -y
现在,让我们创建插件所需的基本文件:
# 创建源代码目录
mkdir -p src
touch src/index.ts
# 创建配置文件
touch package.json
touch rolldown.config.mjs
配置package.json
package.json是插件的核心配置文件,定义了插件的名称、版本、入口文件和依赖关系。编辑该文件如下:
{
"name": "@janhq/note-assistant-extension",
"version": "0.1.0",
"main": "dist/index.js",
"scripts": {
"build": "rolldown -c",
"dev": "rolldown -c -w"
},
"dependencies": {
"@janhq/core": "*"
},
"devDependencies": {
"rolldown": "^0.7.3",
"typescript": "^5.2.2"
}
}
配置构建工具
Jan使用Rolldown作为模块打包工具,我们需要创建rolldown.config.mjs配置文件:
import { defineConfig } from 'rolldown'
export default defineConfig({
input: 'src/index.ts',
output: {
dir: 'dist',
format: 'esm',
entryFileNames: 'index.js'
},
external: ['@janhq/core']
})
第二步:实现插件核心功能
现在我们开始编写插件的核心代码。我们的"智能笔记助手"需要实现以下功能:
- 在对话中检测需要记录的重要信息
- 自动将检测到的信息整理成结构化笔记
- 提供手动触发笔记保存的命令
- 在UI中显示笔记列表
创建插件主类
Jan插件的入口点是src/index.ts文件,我们需要在这里定义一个继承自Extension的类,并实现必要的生命周期方法。
import { Extension, events } from '@janhq/core'
export default class NoteAssistantExtension extends Extension {
// 插件ID,必须唯一
readonly id = 'note-assistant'
// 插件加载时执行
async onLoad(): Promise<void> {
console.log('Note Assistant Extension loaded!')
// 注册服务,供其他部分调用
this.registerService('noteAssistant', {
createNote: (content: string, title?: string) => this.createNote(content, title),
getNotes: () => this.getNotes()
})
// 监听对话消息事件
this.setupEventListeners()
}
// 插件卸载时执行
async onUnload(): Promise<void> {
console.log('Note Assistant Extension unloaded!')
// 清理资源和事件监听器
}
// 设置事件监听器
private setupEventListeners() {
// 监听新消息事件
this.on('message:created', (message) => {
this.analyzeMessageForNotes(message)
})
}
// 分析消息内容,检测是否需要创建笔记
private async analyzeMessageForNotes(message: any) {
// 只处理AI发送的消息
if (message.role !== 'assistant') return
// 简单的关键词检测,实际应用中可以使用NLP模型
const content = message.content
if (content.includes('重要') || content.includes('记住') || content.includes('注意')) {
await this.createNote(content)
}
}
// 创建笔记
private async createNote(content: string, title?: string) {
const note = {
id: Date.now().toString(),
title: title || `笔记 ${new Date().toLocaleString()}`,
content: content,
createdAt: new Date().toISOString()
}
// 保存笔记到本地存储
const notes = this.getNotes()
notes.push(note)
localStorage.setItem('noteAssistantNotes', JSON.stringify(notes))
// 触发笔记创建事件,供UI层监听
events.emit('note:created', note)
return note
}
// 获取所有笔记
private getNotes(): any[] {
const notesStr = localStorage.getItem('noteAssistantNotes')
return notesStr ? JSON.parse(notesStr) : []
}
}
理解插件基础类
上述代码中,我们的插件类继承自Jan核心提供的Extension基类。这个基类定义了插件的生命周期和核心功能,位于core/src/browser/extension.ts。
Extension类提供了以下关键方法和属性:
onLoad(): 插件加载时调用,用于初始化onUnload(): 插件卸载时调用,用于资源清理registerService(name, service): 注册服务供其他插件调用on(event, handler): 监听事件emit(event, data): 触发事件registerSettings(settings): 注册插件设置项到UI
第三步:添加设置界面和用户交互
一个完整的插件通常需要提供用户设置界面,让用户可以自定义插件行为。我们将为笔记助手添加一些可配置选项。
注册插件设置
修改onLoad方法,添加设置项注册代码:
async onLoad(): Promise<void> {
console.log('Note Assistant Extension loaded!')
// 注册设置项
this.registerSettings([
{
key: 'auto_detect',
title: '自动检测笔记内容',
description: '是否自动检测对话中的重要信息并创建笔记',
type: 'boolean',
controllerProps: {
value: true,
recommended: true
}
},
{
key: 'note_keywords',
title: '笔记关键词',
description: '用于触发自动笔记的关键词,用逗号分隔',
type: 'text',
controllerProps: {
value: '重要,记住,注意,总结',
recommended: '重要,记住,注意,总结'
}
}
])
// 其他初始化代码...
}
加载和应用用户设置
修改analyzeMessageForNotes方法,使用用户自定义的关键词设置:
private async analyzeMessageForNotes(message: any) {
// 检查是否启用了自动检测
const autoDetect = await this.getSetting<boolean>('auto_detect', true)
if (!autoDetect) return
// 获取用户设置的关键词
const keywordsStr = await this.getSetting<string>('note_keywords', '重要,记住,注意')
const keywords = keywordsStr.split(',').map(k => k.trim())
// 检查消息是否包含任何关键词
const content = message.content.toLowerCase()
const shouldCreateNote = keywords.some(keyword =>
content.includes(keyword.toLowerCase())
)
if (shouldCreateNote) {
await this.createNote(content)
}
}
添加手动创建笔记的命令
除了自动检测,我们还可以添加一个手动创建笔记的命令,供用户通过快捷键或UI按钮触发:
// 在onLoad方法中注册命令
async onLoad(): Promise<void> {
// ...其他代码
// 注册命令
this.registerCommand('note-assistant.createNote', async (args: { content: string, title?: string }) => {
return this.createNote(args.content, args.title)
})
}
插件的构建、测试与调试
完成代码编写后,我们需要构建插件并在Jan应用中测试它。
构建插件
cd extensions/note-assistant-extension
yarn build
构建成功后,会在插件目录下生成dist文件夹,包含打包后的代码。
在Jan中加载插件
要在Jan应用中测试插件,需要将插件添加到配置文件中。编辑项目根目录下的extensions/package.json,添加我们的插件:
{
"name": "@janhq/extensions",
"private": true,
"workspaces": [
"assistant-extension",
"conversational-extension",
"download-extension",
"llamacpp-extension",
"rag-extension",
"vector-db-extension",
"note-assistant-extension" // 添加这一行
]
}
然后在项目根目录执行:
yarn install
yarn dev
Jan应用会启动并加载我们的新插件。你可以通过开发者工具的控制台查看插件输出的日志信息。
调试插件
Jan提供了多种插件调试方式:
- 日志输出:使用
console.log输出调试信息 - 事件监听:在控制台中监听插件事件
window.core.events.on('note:created', (note) => console.log('New note:', note)) - 检查已加载插件:通过以下代码查看所有已加载的插件
console.log(window.core.extensions)
根据extensions/CONTRIBUTING.md文档中的建议,插件开发中常见问题及解决方法:
- 插件不加载:检查package.json中的name格式是否为
@janhq/extension-name,确保onLoad方法没有抛出错误 - 事件不触发:检查事件名称拼写是否正确,确保监听器在onLoad方法中设置
- 服务不可用:确认服务注册代码是否正确,服务名是否唯一
插件发布与分享
当你的插件开发完成并测试通过后,可以考虑将其分享给其他Jan用户。根据Jan的插件分发机制,有两种主要方式:
提交到官方仓库
如果你的插件具有通用性,可以按照CONTRIBUTING.md中的指南,提交PR将插件合并到Jan的官方仓库中。
独立分发
你也可以将插件作为独立项目发布,其他用户可以通过以下方式安装:
# 克隆插件仓库
git clone <你的插件仓库URL>
cd jan/extensions
ln -s <插件路径> note-assistant-extension
# 安装依赖并构建
cd ..
yarn install
yarn build:extensions
总结与进阶方向
恭喜!你已经成功创建了一个功能完整的Jan插件。通过这个"智能笔记助手"插件,我们学习了Jan插件开发的全过程,包括:
- 插件目录结构和配置文件
- 核心功能实现和事件处理
- 设置界面创建
- 插件构建和测试
这个基础插件可以进一步扩展,添加更多高级功能:
- 笔记分类与标签:实现笔记的分类管理和标签功能
- 富文本支持:添加格式化笔记内容的能力
- 笔记导出:支持将笔记导出为Markdown或PDF格式
- AI增强摘要:使用Jan的AI能力自动生成笔记摘要
- 笔记搜索:实现本地笔记全文搜索功能
Jan的插件系统设计灵活,几乎可以扩展应用的任何方面。无论是添加新的AI模型支持、实现特定领域功能,还是集成外部服务,插件都能满足你的需求。
希望这个教程能帮助你开启Jan插件开发之旅。如有任何问题,欢迎查阅官方文档或参与社区讨论。Happy coding!
Kimi-K2.5Kimi K2.5 是一款开源的原生多模态智能体模型,它在 Kimi-K2-Base 的基础上,通过对约 15 万亿混合视觉和文本 tokens 进行持续预训练构建而成。该模型将视觉与语言理解、高级智能体能力、即时模式与思考模式,以及对话式与智能体范式无缝融合。Python00- QQwen3-Coder-Next2026年2月4日,正式发布的Qwen3-Coder-Next,一款专为编码智能体和本地开发场景设计的开源语言模型。Python00
xw-cli实现国产算力大模型零门槛部署,一键跑通 Qwen、GLM-4.7、Minimax-2.1、DeepSeek-OCR 等模型Go06
PaddleOCR-VL-1.5PaddleOCR-VL-1.5 是 PaddleOCR-VL 的新一代进阶模型,在 OmniDocBench v1.5 上实现了 94.5% 的全新 state-of-the-art 准确率。 为了严格评估模型在真实物理畸变下的鲁棒性——包括扫描伪影、倾斜、扭曲、屏幕拍摄和光照变化——我们提出了 Real5-OmniDocBench 基准测试集。实验结果表明,该增强模型在新构建的基准测试集上达到了 SOTA 性能。此外,我们通过整合印章识别和文本检测识别(text spotting)任务扩展了模型的能力,同时保持 0.9B 的超紧凑 VLM 规模,具备高效率特性。Python00
KuiklyUI基于KMP技术的高性能、全平台开发框架,具备统一代码库、极致易用性和动态灵活性。 Provide a high-performance, full-platform development framework with unified codebase, ultimate ease of use, and dynamic flexibility. 注意:本仓库为Github仓库镜像,PR或Issue请移步至Github发起,感谢支持!Kotlin07
VLOOKVLOOK™ 是优雅好用的 Typora/Markdown 主题包和增强插件。 VLOOK™ is an elegant and practical THEME PACKAGE × ENHANCEMENT PLUGIN for Typora/Markdown.Less00
