Skip to main content
Tiro Notes Blog

An agnostic AI assistant into Tiro Notes

One of the most interesting features that I wanted to implement in Tiro is the idea of having an AI assistant available on mobile and desktop.

Final result, you can test it using the command line npx tiro-notes@0.30.99.12

User experience #

The main problem I saw with current solutions was the friction between the writing process and the AI assistance at the user experience level. I don't use AI assistants because of that friction required to use them (Opening a new tab, copy/pasting text 2 times etc.). It creates a certain level of steps under which I'd just rather use search engines or do it myself.

My first attempt was to add an AI assistant throught command line using the Tiro command line manager custom tag called Commander, but I quickly realized that the integration still required too much steps to be usable in real-life scenarios, especially the copy/pasting part which is really tedious on mobile. So I gave up in using AI assistance inside Tiro that way.

Initial AI integration attempt using the commander custom tag

My second attempt, which I will describe here, was to get as close as possible to the user experience offered by Microsoft's Copilot or Notion's AI system.

The goal was to reduce the number of steps needed to get an answer:

The objective is also to respect a certain open source philosophy by offering the choice to users to use different AI engines, including open source ones in the future. The solution is designed to be easily interchangeable from the user settings.

New settings options for AI assistant. The AI system used can be modified

Technical implementation #

On the coding side, it happened to be quite easy to implement it. The main logic was :

The code is visible at that link, I will probably refactor it latest to its own manager file

I am using two api functions:

getApi(api => {
  let cmd = api.userSettings.get("ui_editor_ai_command")
  cmd = cmd.replace("", selectionTxt)
  genTextAt(genParams())
  api.command.stream(cmd, streamChunk => {
    if (streamChunk.isError) isError = true
    // if it is an error, display it in a popup
    if (isError) {
      api.ui.notification.emit({
        content: `[AI] Error from CLI <br/> "${cmd}" <br/>=> <br/>${streamChunk.text}`,
        options: {hideAfter: -1 }
      })
      genTextAt({...genParams(), textUpdate:"", isLast: true})
    } else {
      // else insert it
      genTextAt({...genParams(), textUpdate:streamChunk.textTot, isLast: streamChunk.isLast})
    }
  })
})

You can test that AI assistant by downloading Tiro Notes from the command line npx tiro-notes@0.30.99.12