首页
/ 3步打造专属AI助手:Jan插件开发实战指南

3步打造专属AI助手:Jan插件开发实战指南

2026-02-05 05:48:49作者:裘晴惠Vivianne

你是否曾想过给离线AI助手Jan添加个性化功能?比如让它自动整理聊天记录,或者根据你的工作习惯定制回复风格?本文将通过实战案例,带你从零构建一个"智能笔记助手"插件,让Jan成为你独一无二的AI工作伙伴。

插件开发前的准备工作

在开始编写代码前,我们需要先了解Jan的插件系统架构。Jan采用模块化设计,所有功能都通过插件实现,目前已有多个官方插件可供参考:

  • assistant-extension:提供助手的增删改查功能,核心实现位于src/index.ts
  • conversational-extension:处理消息和对话状态管理,聊天逻辑在src/index.ts
  • llamacpp-extension:本地模型推理支持,通过llama.cpp实现离线运行

Jan插件架构

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']
})

第二步:实现插件核心功能

现在我们开始编写插件的核心代码。我们的"智能笔记助手"需要实现以下功能:

  1. 在对话中检测需要记录的重要信息
  2. 自动将检测到的信息整理成结构化笔记
  3. 提供手动触发笔记保存的命令
  4. 在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提供了多种插件调试方式:

  1. 日志输出:使用console.log输出调试信息
  2. 事件监听:在控制台中监听插件事件
    window.core.events.on('note:created', (note) => console.log('New note:', note))
    
  3. 检查已加载插件:通过以下代码查看所有已加载的插件
    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插件开发的全过程,包括:

  • 插件目录结构和配置文件
  • 核心功能实现和事件处理
  • 设置界面创建
  • 插件构建和测试

这个基础插件可以进一步扩展,添加更多高级功能:

  1. 笔记分类与标签:实现笔记的分类管理和标签功能
  2. 富文本支持:添加格式化笔记内容的能力
  3. 笔记导出:支持将笔记导出为Markdown或PDF格式
  4. AI增强摘要:使用Jan的AI能力自动生成笔记摘要
  5. 笔记搜索:实现本地笔记全文搜索功能

Jan的插件系统设计灵活,几乎可以扩展应用的任何方面。无论是添加新的AI模型支持、实现特定领域功能,还是集成外部服务,插件都能满足你的需求。

希望这个教程能帮助你开启Jan插件开发之旅。如有任何问题,欢迎查阅官方文档或参与社区讨论。Happy coding!

登录后查看全文
热门项目推荐
相关项目推荐