Jaspers Hub

jaspers / agents

pluginOfficialReviewed★ 0↓ 1

Research Agents: Lets you define research agents that chat and answer with citations from SEC filings, your documents, and the web, via Jaspers' research-store service.

1.9 KB
1import type { BackendContext } from '@jaspers-ai/sdk'
2import { AGENT_ID, agentIdOf, parseAgent, serializeAgent, type Agent, type AgentInput } from './agents.ts'
3import { errorText } from './errors.ts'
4
5// Agents on disk, in the plugin's data folder's defs/, one Markdown file each. The list is the live
6// value `agents`, which the view reads, published again whenever the folder changes.
7
8const FOLDER = 'defs'
9
10export async function loadAgents(ctx: BackendContext): Promise<Agent[]> {
11 const agents: Agent[] = []
12 for (const entry of await ctx.files.list(FOLDER)) {
13 const id = entry.dir ? null : agentIdOf(entry.path)
14 if (id === null) continue
15 try {
16 agents.push(parseAgent(id, await ctx.files.read(entry.path)))
17 } catch (err) {
18 // Gone between the listing and the read, or unreadable: listed with why, not a broken list.
19 agents.push({ ...parseAgent(id, ''), error: `could not be read: ${errorText(err, 'unreadable')}` })
20 }
21 }
22 return agents.sort((a, b) => a.name.localeCompare(b.name) || a.id.localeCompare(b.id))
23}
24
25export async function publishAgents(ctx: BackendContext): Promise<Agent[]> {
26 const agents = await loadAgents(ctx)
27 ctx.live.set('agents', agents)
28 return agents
29}
30
31/** Writes one agent, refusing what would not read back as a working one. */
32export async function saveAgent(ctx: BackendContext, input: AgentInput): Promise<void> {
33 const text = serializeAgent(input)
34 const checked = parseAgent(input.id, text)
35 if (checked.error) throw new Error(`Not saved: ${checked.error}.`)
36 await ctx.files.write(`${FOLDER}/${input.id}.md`, text)
37}
38
39export async function deleteAgent(ctx: BackendContext, id: string): Promise<void> {
40 if (!AGENT_ID.test(id)) throw new Error(`No agent ${id}.`)
41 await ctx.files.remove(`${FOLDER}/${id}.md`)
42}
43
44export function watchAgents(ctx: BackendContext): void {
45 ctx.files.watch(FOLDER, () => {
46 publishAgents(ctx).catch((err: unknown) => console.warn(`agents: ${errorText(err, 'failed')}`))
47 })
48}