-
Eimi is an LLM UI with tree comments design.
eimiApi.getSessionMessagesreturns all messages in current session, not just one chain.- But
request.messagesis the ancestor path, root to request message.
-
Eimi Script is addon-like JS script.
- Can be added by user in UI.
- Ran in
Session.sveltepage context. - Have access to
eimiApifunctions. - Ran in order of user specified script name (convention is
01 ..,02 ..), which can be important if multiple scripts interact. - Can expose slash commands via
static commandsfor in-input actions. - Can store data using
customDatain a message. - Can create windows with custom UI.
- A script can be a companion to another script, so not necessary using hooks, but have methods for other scripts to use. E.g. tool call script -> scans script instances -> collects tools from other scripts.
- Define
static commands = [{ name, run() }]on the script class. - Commands are typed as
/name ...in the input line; matching is per enabled scripts order. runcan mutate the message and return{next: 'gen'}to trigger generation.runcan return{replaceLine: '...'}to replace the current command line.runargs:{command, args, message, line, lineStart, lineEnd, cursor, text}
class EimiScriptMyCmd {
static commands = [{
name: 'tldr',
run: async function({args, message, line, lineStart, lineEnd, text}) {
// note `this` still works
const match = line?.match(/^\/tldr\s+(https?:\/\/[^\s]+)/) || (`/tldr ${args}`.trim()).match(/^\/tldr\s+(https?:\/\/[^\s]+)/)
if (!match) throw Error('Usage: /tldr <url>')
const prompt = `%%readurl(${match[1]})\n\n------\n\nWrite a summary.`
return {next: 'gen', replaceLine: prompt}
}
}]
}
return EimiScriptMyCmd/**
* @typedef {Object} EimiApi
* @property {function({messageId: string, params?: Object}): Promise<{newMessage: Object, request: Object}>} genResponse - Generate a response for a specific message ID with optional request params
* @property {function(): string} getSessionId - Get the current session ID
* @property {function(): Object} getSessionInfo - Get current session data, reactive to field changes like `title` or `parameters`
* @property {function(): Array} getSessionMessages - Get all messages in the current session (includes multiple subtrees, filter accordingly)
* @property {function(Object): void} createEmptyWindow - Create a new empty window with optional configuration
* @param {Object} options - Configuration options for the new window
* @param {function} [options.onReady] - Callback when the window content is ready, receives {el, closeWindow, ...} as parameter
* @param {function} [options.onWindowClose] - Callback when the window is closed
* @property {function(Object): Object} createMessage - Create a new message with provided values, patches defaults
* @param {Object} values - Message properties to override defaults (more in Session.svelte)
* @param {string} [values.parentId] - Parent message ID
* @param {string} [values.role] - Message role ('user', 'assistant', 'system')
* @param {string} [values.content] - Message content
* @param {Array} [values.customData] - Custom data fields for the message
* @returns {Object} The created message object
* @property {function(string): Array} customDataGetAll - Get all custom data entries for a message
* @property {function(string, string): Object} customDataGet - Get a custom data entry by key
* @property {function(string, string, any): Object} customDataSet - Set a custom data entry value by key
* @property {function(string, string): Object} customDataRemove - Remove a custom data entry by key
* @property {function(): Object} getSessionScriptInstances - Get script instances map by script id
* @property {function(): Array} getSessionScripts - Get loaded scripts
*/
class EimiScriptMyExample { // Must start with `class EimiScript`
constructor({eimiApi}) {
/**
* @type {EimiApi}
*/
this.eimiApi = eimiApi
// Script instantiated per session, handling multiple callback calls
}
async onRequest(request, newMessage, messages) {
// `request` search for `const request = {` in Session.svelte to see full request structure.
// `request.messages` is OpenAI-like chain of messages sent to LLM, `.content` is always a list.
// * note to get original session message you need to take id from `_id` and search in eimiApi.getSessionMessages()
// `newMessage` is going to contain LLM output.
// `messages` is a full list of messages in a session, including unrelated subtrees.
// Modify request before it's sent to the LLM
}
async onPostRequest(request, newMessage) {
// Process response after it's received from the LLM
}
onDestroy() {
// Cleanup when script is unloaded
}
}
return EimiScriptMyExample // Must return the class