* chore: enable shortcut zoom (#5261) * chore: enable shortcut zoom * chore: update shortcut setting * fix: thinking block (#5263) * Merge pull request #5262 from menloresearch/chore/sync-new-hub-data chore: sync new hub data * ✨enhancement: model run improvement (#5268) * fix: mcp tool error handling * fix: error message * fix: trigger download from recommend model * fix: can't scroll hub * fix: show progress * ✨enhancement: prompt users to increase context size * ✨enhancement: rearrange action buttons for a better UX * 🔧chore: clean up logics --------- Co-authored-by: Faisal Amir <urmauur@gmail.com> * fix: glitch download from onboarding (#5269) * ✨enhancement: Model sources should not be hard coded from frontend (#5270) * 🐛fix: default onboarding model should use recommended quantizations (#5273) * 🐛fix: default onboarding model should use recommended quantizations * ✨enhancement: show context shift option in provider settings * 🔧chore: wording * 🔧 config: add to gitignore * 🐛fix: Jan-nano repo name changed (#5274) * 🚧 wip: disable showSpeedToken in ChatInput * 🐛 fix: commented out the wrong import * fix: masking value MCP env field (#5276) * ✨ feat: add token speed to each message that persist * ♻️ refactor: to follow prettier convention * 🐛 fix: exclude deleted field * 🧹 clean: all the missed console.log * ✨enhancement: out of context troubleshooting (#5275) * ✨enhancement: out of context troubleshooting * 🔧refactor: clean up * ✨enhancement: add setting chat width container (#5289) * ✨enhancement: add setting conversation width * ✨enahncement: cleanup log and change improve accesibility * ✨enahcement: move const beta version * 🐛fix: optional additional_information gpu (#5291) * 🐛fix: showing release notes for beta and prod (#5292) * 🐛fix: showing release notes for beta and prod * ♻️refactor: make an utils env * ♻️refactor: hide MCP for production * ♻️refactor: simplify the boolean expression fetch release note --------- Co-authored-by: Faisal Amir <urmauur@gmail.com> Co-authored-by: LazyYuuki <huy2840@gmail.com> Co-authored-by: Bui Quang Huy <34532913+LazyYuuki@users.noreply.github.com>
102 lines
3.5 KiB
TypeScript
102 lines
3.5 KiB
TypeScript
import { Assistant, AssistantExtension, fs, joinPath } from '@janhq/core'
|
||
export default class JanAssistantExtension extends AssistantExtension {
|
||
async onLoad() {
|
||
if (!(await fs.existsSync('file://assistants'))) {
|
||
await fs.mkdir('file://assistants')
|
||
}
|
||
const assistants = await this.getAssistants()
|
||
if (assistants.length === 0) {
|
||
await this.createAssistant(this.defaultAssistant)
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Called when the extension is unloaded.
|
||
*/
|
||
onUnload(): void {}
|
||
|
||
async getAssistants(): Promise<Assistant[]> {
|
||
if (!(await fs.existsSync('file://assistants')))
|
||
return [this.defaultAssistant]
|
||
const assistants = await fs.readdirSync('file://assistants')
|
||
const assistantsData: Assistant[] = []
|
||
for (const assistant of assistants) {
|
||
const assistantPath = await joinPath([
|
||
'file://assistants',
|
||
assistant,
|
||
'assistant.json',
|
||
])
|
||
if (!(await fs.existsSync(assistantPath))) {
|
||
console.warn(`Assistant file not found: ${assistantPath}`)
|
||
continue
|
||
}
|
||
try {
|
||
const assistantData = JSON.parse(await fs.readFileSync(assistantPath))
|
||
assistantsData.push(assistantData as Assistant)
|
||
} catch (error) {
|
||
console.error(`Failed to read assistant ${assistant}:`, error)
|
||
}
|
||
}
|
||
return assistantsData
|
||
}
|
||
|
||
async createAssistant(assistant: Assistant): Promise<void> {
|
||
const assistantPath = await joinPath([
|
||
'file://assistants',
|
||
assistant.id,
|
||
'assistant.json',
|
||
])
|
||
const assistantFolder = await joinPath(['file://assistants', assistant.id])
|
||
if (!(await fs.existsSync(assistantFolder))) {
|
||
await fs.mkdir(assistantFolder)
|
||
}
|
||
await fs.writeFileSync(assistantPath, JSON.stringify(assistant, null, 2))
|
||
}
|
||
|
||
async deleteAssistant(assistant: Assistant): Promise<void> {
|
||
const assistantPath = await joinPath([
|
||
'file://assistants',
|
||
assistant.id,
|
||
'assistant.json',
|
||
])
|
||
if (await fs.existsSync(assistantPath)) {
|
||
await fs.rm(assistantPath)
|
||
}
|
||
}
|
||
|
||
private defaultAssistant: Assistant = {
|
||
avatar: '👋',
|
||
thread_location: undefined,
|
||
id: 'jan',
|
||
object: 'assistant',
|
||
created_at: Date.now() / 1000,
|
||
name: 'Jan',
|
||
description:
|
||
'Jan is a helpful desktop assistant that can reason through complex tasks and use tools to complete them on the user’s behalf.',
|
||
model: '*',
|
||
instructions:
|
||
'You have access to a set of tools to help you answer the user’s question. You can use only one tool per message, and you’ll receive the result of that tool in the user’s next response. To complete a task, use tools step by step—each step should be guided by the outcome of the previous one.\nTool Usage Rules:\n1. Always provide the correct values as arguments when using tools. Do not pass variable names—use actual values instead.\n2. You may perform multiple tool steps to complete a task.\n3. Avoid repeating a tool call with exactly the same parameters to prevent infinite loops.',
|
||
tools: [
|
||
{
|
||
type: 'retrieval',
|
||
enabled: false,
|
||
useTimeWeightedRetriever: false,
|
||
settings: {
|
||
top_k: 2,
|
||
chunk_size: 1024,
|
||
chunk_overlap: 64,
|
||
retrieval_template: `Use the following pieces of context to answer the question at the end.
|
||
----------------
|
||
CONTEXT: {CONTEXT}
|
||
----------------
|
||
QUESTION: {QUESTION}
|
||
----------------
|
||
Helpful Answer:`,
|
||
},
|
||
},
|
||
],
|
||
file_ids: [],
|
||
metadata: undefined,
|
||
}
|
||
}
|