@mushinjs/plugin-agent 0.2.0-next.20261112165327 → 0.2.0-next.20261113103537

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 Setobox
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Setobox
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
21
  SOFTWARE.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import {\r\n type ActionInfo, Context, field, fromToolName, MushinError, randomId, segmentsToText, Service, toToolName, z,\r\n} from '@mushinjs/core'\r\nimport type { LlmMessage, LlmResult, ToolCall, ToolDefinition } from '@mushinjs/plugin-providers'\r\nimport type {} from '@mushinjs/plugin-storage'\r\nimport { contextNote, type SceneInfo, skillBlock, SYSTEM_PROMPT, type TurnContext } from './prompt'\r\nimport {\r\n type AgentSettings, defaultPolicy, formatSkillMarkdown, parseSkillMarkdown, policyInput, profileInput, SCENE_KEYS, type SceneProfile, today,\r\n type TokenUsage, type ToolPolicy,\r\n} from './settings'\r\nimport { type AgentSkill, BUILTIN_SKILLS, type SkillDefinition, skillFields, skillInput } from './skills'\r\n\r\nexport * from './prompt'\r\nexport * from './settings'\r\nexport * from './skills'\r\n\r\ndeclare module '@mushinjs/core' {\r\n interface Context {\r\n agent: Agent\r\n }\r\n\r\n interface Events {\r\n 'agent/event'(event: AgentEvent): void\r\n /** Skills, page profiles or tool policies changed. */\r\n 'agent/changed'(): void\r\n }\r\n}\r\n\r\nexport type AgentEvent = { session: string } & (\r\n | { type: 'start' }\r\n | { type: 'delta'; text: string }\r\n | { type: 'tool-call'; id: string; action: string; input: unknown; risk: string }\r\n | { type: 'confirm'; id: string; action: string; input: unknown }\r\n | { type: 'tool-result'; id: string; ok: boolean; result?: unknown; error?: string }\r\n | { type: 'done'; text: string; usage?: { inputTokens: number; outputTokens: number } }\r\n /** `code` is `max_steps` when the turn ran out of tool rounds, so the dashboard can offer to go on. */\r\n | { type: 'error'; error: string; code?: 'max_steps' }\r\n)\r\n\r\n/**\r\n * A stored message; `display` holds the user's own words when the content carries a context note,\r\n * and `skills` the names of the skills picked for it.\r\n */\r\nexport type AgentMessage = LlmMessage & {\r\n display?: string\r\n skills?: string[]\r\n /** A chat quoted into the message, as the dashboard shows it: who said what, and where. */\r\n quote?: QuotedChat\r\n at: number\r\n}\r\n\r\n/** Messages of a bot's chat quoted into an Agent message, around one picked message. */\r\nexport interface QuotedChat {\r\n bot: string\r\n botName: string\r\n channel: { type: 'group' | 'private'; id: string; name?: string }\r\n /** The picked message's record id; a sample for flows.test and flows.preview. */\r\n focus: string\r\n lines: { id: string; direction: 'in' | 'out'; user: string; userId: string; text: string; at: number }[]\r\n}\r\n\r\n/** Where a conversation was started, for the history list. */\r\nexport interface SessionScene {\r\n key: string\r\n label?: string\r\n page?: string\r\n}\r\n\r\nexport interface AgentSession {\r\n id: string\r\n title: string\r\n createdAt: number\r\n updatedAt: number\r\n /** Tool list frozen at creation, so every request in the session sends identical tools. */\r\n tools: ToolDefinition[]\r\n messages: AgentMessage[]\r\n /** The page the conversation was started on. */\r\n scene?: SessionScene\r\n /** What it touched, for search: `scene:<key>`, `skill:<id>`, `command:<name>`, `resource:<kind>:<id>`. */\r\n tags?: string[]\r\n}\r\n\r\nexport interface SendOptions {\r\n /** Dashboard connection id; client actions such as ui.navigate are routed back to it. */\r\n client?: string\r\n page?: string\r\n /** The page as the dashboard describes it; its hint and state go into the context note. */\r\n scene?: SceneInfo\r\n /** Ids of skills whose instructions go into this message. */\r\n skills?: string[]\r\n /** A message of a bot's chat to quote, with a few messages around it. */\r\n quote?: { bot: string; channel: string; id: string; before?: number; after?: number }\r\n}\r\n\r\n/** Commands the dashboard runs itself, without asking the model. */\r\nexport const BUILTIN_COMMANDS = [\r\n { name: 'new', description: 'Start a new conversation', 'zh-CN': '开始新对话' },\r\n { name: 'history', description: 'Open the full conversation history', 'zh-CN': '打开完整历史' },\r\n { name: 'model', description: 'Switch the Agent\\'s model', 'zh-CN': '切换模型' },\r\n { name: 'status', description: 'Show how much context this conversation uses', 'zh-CN': '查看上下文用量' },\r\n { name: 'clear', description: 'Clear the input and close the conversation', 'zh-CN': '清空当前对话视图' },\r\n { name: 'help', description: 'Show what you can type', 'zh-CN': '查看可用的指令和技能' },\r\n]\r\n\r\nconst SETTINGS_KEY = 'agent/settings/main'\r\nconst USAGE_KEY = 'agent/settings/usage'\r\n\r\nconst MAX_RESULT_CHARS = 16_000\r\n\r\nexport const Config = z.object({\r\n provider: z.string().optional().meta(field('Provider', 'Provider or model profile for the Agent; empty uses the default provider', {\r\n 'zh-CN': { title: '提供商', description: '智能体使用的提供商或配置方案;留空使用默认提供商' },\r\n }, { choices: 'providers.choices' })),\r\n model: z.string().optional().meta(field('Model', 'Model for the Agent; empty uses the provider\\'s default', {\r\n 'zh-CN': { title: '模型', description: '智能体使用的模型;留空使用提供商默认模型' },\r\n })),\r\n maxSteps: z.number().int().min(1).max(50).default(20).meta(field('Max steps', 'Most tool-calling rounds in one reply', {\r\n 'zh-CN': { title: '最大步数', description: '一次回复中最多调用工具的轮数' },\r\n })),\r\n confirmTimeout: z.number().int().min(10).default(600).meta(field('Approval timeout', 'Seconds to wait for approval of a dangerous action', {\r\n 'zh-CN': { title: '确认超时', description: '等待用户批准危险操作的秒数' },\r\n })),\r\n dailyTokens: z.number().int().min(0).default(0).meta(field('Daily token budget', 'Input and output tokens the Agent may use per day; 0 means no limit', {\r\n 'zh-CN': { title: '每日 Token 预算', description: '智能体每天最多使用的输入和输出 Token;0 表示不限制' },\r\n })),\r\n})\r\n\r\nexport type Config = z.infer<typeof Config>\r\n\r\ninterface Running {\r\n abort: AbortController\r\n confirms: Map<string, (approved: boolean) => void>\r\n /** Tokens of every request in this turn. */\r\n usage: { inputTokens: number; outputTokens: number }\r\n /** Failed calls per tool in this turn, to tell the model to stop guessing. */\r\n failures: Map<string, number>\r\n}\r\n\r\n/** The turn used every tool round it may; the dashboard offers to continue. */\r\nclass StepLimit extends Error {\r\n constructor(steps: number) {\r\n super(`Stopped after ${steps} tool rounds; send another message to continue`)\r\n }\r\n}\r\n\r\n/** After this many failures of one tool in a turn, its errors ask the model to change course. */\r\nconst FAILURE_HINT_AFTER = 3\r\n\r\n/** Runs conversations in which the LLM operates Mushin.js through the action registry. */\r\nexport class Agent extends Service {\r\n static inject = ['actions', 'llm', 'storage']\r\n static Config = Config\r\n\r\n private home: Context\r\n private running = new Map<string, Running>()\r\n private pluginSkills = new Map<string, AgentSkill>()\r\n private settingsCache?: AgentSettings\r\n\r\n constructor(ctx: Context, public config: Config) {\r\n super(ctx, 'agent')\r\n this.home = ctx\r\n }\r\n\r\n *[Service.init]() {\r\n yield* this.defineActions()\r\n yield () => {\r\n for (const id of this.running.keys()) this.cancel(id)\r\n }\r\n }\r\n\r\n /** Tools offered to the model: every action except the Agent's own and those turned off. */\r\n async tools(): Promise<ToolDefinition[]> {\r\n const settings = await this.settings()\r\n return this.home.actions.list()\r\n .filter((action) => action.agent && !action.name.startsWith('agent.') && this.policyOf(settings, action) !== 'off')\r\n .map((action) => ({\r\n name: toToolName(action.name),\r\n description: describeTool(action),\r\n parameters: action.inputSchema,\r\n }))\r\n }\r\n\r\n // ---- settings ----\r\n\r\n async settings(): Promise<AgentSettings> {\r\n if (!this.settingsCache) {\r\n const saved = await this.home.storage.get<Partial<AgentSettings>>(SETTINGS_KEY)\r\n this.settingsCache = { profiles: {}, toolPolicy: {}, disabledSkills: [], ...saved }\r\n }\r\n return this.settingsCache\r\n }\r\n\r\n private async updateSettings(change: (settings: AgentSettings) => void) {\r\n const settings = await this.settings()\r\n change(settings)\r\n await this.home.storage.set(SETTINGS_KEY, settings)\r\n this.home.emit('agent/changed')\r\n return settings\r\n }\r\n\r\n private policyOf(settings: AgentSettings, action: Pick<ActionInfo, 'name' | 'risk'>): ToolPolicy {\r\n return settings.toolPolicy[action.name] ?? defaultPolicy(action.risk)\r\n }\r\n\r\n /** Every action with its policy, for the tool policy table. */\r\n async policies() {\r\n const settings = await this.settings()\r\n return this.home.actions.list()\r\n .filter((action) => action.agent && !action.name.startsWith('agent.'))\r\n .map((action) => ({\r\n name: action.name,\r\n description: action.description,\r\n plugin: action.plugin,\r\n risk: action.risk,\r\n client: action.client,\r\n policy: this.policyOf(settings, action),\r\n custom: action.name in settings.toolPolicy,\r\n }))\r\n }\r\n\r\n /** Sets the policy of some actions; `null` goes back to the default for the action's risk. */\r\n async setPolicy(changes: Record<string, ToolPolicy | null>) {\r\n await this.updateSettings((settings) => {\r\n for (const [name, policy] of Object.entries(changes)) {\r\n if (policy === null) delete settings.toolPolicy[name]\r\n else settings.toolPolicy[name] = policy\r\n }\r\n })\r\n return this.policies()\r\n }\r\n\r\n async profiles() {\r\n return (await this.settings()).profiles\r\n }\r\n\r\n async setProfile(scene: string, profile: SceneProfile | null) {\r\n const settings = await this.updateSettings((settings) => {\r\n if (profile === null) delete settings.profiles[scene]\r\n else settings.profiles[scene] = profile\r\n })\r\n return settings.profiles[scene] ?? {}\r\n }\r\n\r\n /** Tokens used today and the daily budget. */\r\n async usage() {\r\n const saved = await this.home.storage.get<TokenUsage>(USAGE_KEY)\r\n const used = saved?.day === today() ? saved : { day: today(), input: 0, output: 0 }\r\n return { ...used, budget: this.config.dailyTokens }\r\n }\r\n\r\n private async addUsage(usage: { inputTokens: number; outputTokens: number }) {\r\n const current = await this.usage()\r\n await this.home.storage.set(USAGE_KEY, { day: current.day, input: current.input + usage.inputTokens, output: current.output + usage.outputTokens })\r\n }\r\n\r\n private emit(event: AgentEvent) {\r\n this.home.emit('agent/event', event)\r\n }\r\n\r\n private async allSessions() {\r\n const keys = await this.home.storage.list('agent')\r\n const sessions = await Promise.all(keys.map((key) => this.home.storage.get<AgentSession>(key)))\r\n return sessions\r\n .filter((session): session is AgentSession => !!session && Array.isArray(session.messages))\r\n .sort((a, b) => b.updatedAt - a.updatedAt)\r\n }\r\n\r\n private summary({ id, title, createdAt, updatedAt, scene, tags }: AgentSession) {\r\n return { id, title, createdAt, updatedAt, scene, tags: tags ?? [], running: this.running.has(id) }\r\n }\r\n\r\n async sessions() {\r\n return (await this.allSessions()).map((session) => this.summary(session))\r\n }\r\n\r\n /**\r\n * Conversations matching every tag (`scene:flowEditor`, `skill:<id>`, `status:running`, …) and\r\n * containing the query in the title or in what the user or the Agent wrote.\r\n */\r\n async search(options: { query?: string; tags?: string[]; limit?: number } = {}) {\r\n const query = options.query?.trim().toLowerCase()\r\n const results = []\r\n for (const session of await this.allSessions()) {\r\n const summary = this.summary(session)\r\n const tags = [...summary.tags, `status:${summary.running ? 'running' : 'idle'}`]\r\n if (options.tags?.some((tag) => !tags.includes(tag))) continue\r\n let snippet: string | undefined\r\n if (query) {\r\n if (!session.title.toLowerCase().includes(query)) {\r\n const texts = session.messages\r\n .filter((message) => message.role === 'user' || message.role === 'assistant')\r\n .map((message) => (message.role === 'user' ? message.display ?? message.content : message.content))\r\n const hit = texts.find((text): text is string => typeof text === 'string' && text.toLowerCase().includes(query))\r\n if (!hit) continue\r\n const at = hit.toLowerCase().indexOf(query)\r\n snippet = `${at > 30 ? '…' : ''}${hit.slice(Math.max(0, at - 30), at + query.length + 50).replace(/\\s+/g, ' ')}`\r\n }\r\n }\r\n results.push({ ...summary, ...(snippet ? { snippet } : {}) })\r\n if (results.length >= (options.limit ?? 50)) break\r\n }\r\n return results\r\n }\r\n\r\n // ---- skills ----\r\n\r\n /** Adds a skill from a plugin; removed when the plugin unloads. */\r\n defineSkill(definition: SkillDefinition) {\r\n const ctx = this.ctx\r\n const skill: AgentSkill = { ...definition, source: 'plugin', plugin: ctx.fiber.name, enabled: true }\r\n return ctx.effect(() => {\r\n this.pluginSkills.set(skill.id, skill)\r\n return () => {\r\n if (this.pluginSkills.get(skill.id) === skill) this.pluginSkills.delete(skill.id)\r\n }\r\n }, `agent.defineSkill(${definition.id})`)\r\n }\r\n\r\n /** Built-in, plugin and user skills; user skills win on the same id. */\r\n async skills(): Promise<AgentSkill[]> {\r\n const disabled = new Set((await this.settings()).disabledSkills)\r\n const byId = new Map<string, AgentSkill>()\r\n for (const skill of BUILTIN_SKILLS) byId.set(skill.id, { ...skill, source: 'builtin', enabled: true })\r\n for (const skill of this.pluginSkills.values()) byId.set(skill.id, { ...skill })\r\n const keys = await this.home.storage.list('agent/skills')\r\n for (const skill of await Promise.all(keys.map((key) => this.home.storage.get<AgentSkill>(key)))) {\r\n if (skill?.id) byId.set(skill.id, { ...skill, source: 'user', enabled: skill.enabled !== false })\r\n }\r\n return [...byId.values()].map((skill) => (skill.source !== 'user' && disabled.has(skill.id) ? { ...skill, enabled: false } : skill))\r\n }\r\n\r\n async skill(id: string) {\r\n const skill = (await this.skills()).find((item) => item.id === id)\r\n if (!skill) throw new MushinError('not_found', `No skill \"${id}\"`)\r\n return skill\r\n }\r\n\r\n /** Saves a user skill. With the id of a built-in or plugin skill it replaces that one until deleted. */\r\n async saveSkill(input: SkillDefinition & { enabled?: boolean }) {\r\n const skill: AgentSkill = { ...input, source: 'user', enabled: input.enabled !== false }\r\n await this.home.storage.set(`agent/skills/${skill.id}`, skill)\r\n this.home.emit('agent/changed')\r\n return this.skill(skill.id)\r\n }\r\n\r\n async createSkill(input: Omit<SkillDefinition, 'id'> & { id?: string }) {\r\n const taken = new Set((await this.skills()).map((skill) => skill.id))\r\n let id = input.id ?? (input.name.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '').slice(0, 40) || randomId(6).toLowerCase())\r\n if (taken.has(id) && !input.id) id = `${id}-${randomId(4).toLowerCase()}`\r\n else if (taken.has(id)) throw new MushinError('conflict', `A skill with id \"${id}\" already exists`)\r\n return this.saveSkill({ ...input, id })\r\n }\r\n\r\n async updateSkill(id: string, patch: Partial<Omit<SkillDefinition, 'id'>>) {\r\n const current = await this.skill(id)\r\n const { source, plugin, enabled, ...rest } = current\r\n return this.saveSkill({ ...rest, ...patch, id, enabled })\r\n }\r\n\r\n /** Deletes a user skill; a built-in or plugin skill it replaced comes back. */\r\n async deleteSkill(id: string) {\r\n const current = await this.skill(id)\r\n if (current.source !== 'user') throw new MushinError('forbidden', 'Built-in and plugin skills cannot be deleted; turn them off instead')\r\n await this.home.storage.delete(`agent/skills/${id}`)\r\n this.home.emit('agent/changed')\r\n return { deleted: id, restored: (await this.skills()).some((skill) => skill.id === id) }\r\n }\r\n\r\n async setSkillEnabled(id: string, enabled: boolean) {\r\n const current = await this.skill(id)\r\n if (current.source === 'user') {\r\n await this.home.storage.set(`agent/skills/${id}`, { ...current, enabled })\r\n this.home.emit('agent/changed')\r\n return this.skill(id)\r\n }\r\n await this.updateSettings((settings) => {\r\n settings.disabledSkills = enabled ? settings.disabledSkills.filter((item) => item !== id) : [...new Set([...settings.disabledSkills, id])]\r\n })\r\n return this.skill(id)\r\n }\r\n\r\n /** Agent commands and the commands of every bot, for the `/` picker. */\r\n commands() {\r\n const bots = this.home.get('bots')\r\n const names = new Map<string, string>((bots?.list() ?? []).map((bot: { id: string; name: string }) => [bot.id, bot.name]))\r\n const listed = bots?.commandList().commands ?? []\r\n return {\r\n builtin: BUILTIN_COMMANDS,\r\n bots: listed.filter((entry: { hidden?: boolean }) => !entry.hidden).map((entry: any) => ({\r\n name: entry.name,\r\n description: entry.description,\r\n usage: entry.usage,\r\n permission: entry.permission ?? entry.role,\r\n bot: entry.botId,\r\n botName: names.get(entry.botId),\r\n source: entry.source,\r\n })),\r\n }\r\n }\r\n\r\n async session(id: string) {\r\n const session = await this.home.storage.get<AgentSession>(`agent/${id}`)\r\n if (!session) throw new MushinError('not_found', `No Agent session \"${id}\"`)\r\n return session\r\n }\r\n\r\n async createSession(): Promise<AgentSession> {\r\n const now = Date.now()\r\n const session: AgentSession = { id: randomId(), title: '', createdAt: now, updatedAt: now, tools: await this.tools(), messages: [] }\r\n await this.save(session)\r\n return session\r\n }\r\n\r\n async deleteSession(id: string) {\r\n this.cancel(id)\r\n await this.home.storage.delete(`agent/${id}`)\r\n return { deleted: id }\r\n }\r\n\r\n private save(session: AgentSession) {\r\n session.updatedAt = Date.now()\r\n return this.home.storage.set(`agent/${session.id}`, session)\r\n }\r\n\r\n private turnContext(page?: string, scene?: SceneInfo): TurnContext {\r\n const providers = this.home.llm.list()\r\n const bots = this.home.get('bots')?.list() ?? []\r\n return {\r\n page,\r\n scene,\r\n providers: providers.length,\r\n ready: this.home.llm.isReady(),\r\n bots: bots.length,\r\n online: bots.filter((bot: { status: string }) => bot.status === 'online').length,\r\n }\r\n }\r\n\r\n /** A bot's chat around one message, for quoting into an Agent message. */\r\n private async quoteChat(input: NonNullable<SendOptions['quote']>): Promise<QuotedChat> {\r\n const bots = this.home.get('bots')\r\n if (!bots) throw new MushinError('unavailable', 'Quoting a chat needs the bots plugin')\r\n const record = bots.get(input.bot)\r\n const list = await bots.messages(input.bot, { channel: input.channel, limit: 300 })\r\n const index = list.findIndex((item) => item.id === input.id)\r\n if (index < 0) throw new MushinError('not_found', 'That message is no longer in the chat\\'s recent messages')\r\n const picked = list.slice(Math.max(0, index - (input.before ?? 6)), index + 1 + (input.after ?? 2))\r\n return {\r\n bot: input.bot,\r\n botName: record.name,\r\n channel: { type: list[index].channel.type, id: list[index].channel.id, ...(list[index].channel.name ? { name: list[index].channel.name } : {}) },\r\n focus: input.id,\r\n lines: picked.map((item) => ({\r\n id: item.id,\r\n direction: item.direction,\r\n user: item.user.name ?? item.user.id,\r\n userId: item.user.id,\r\n text: segmentsToText(item.segments).trim().slice(0, 500),\r\n at: item.timestamp,\r\n })),\r\n }\r\n }\r\n\r\n /** Starts a turn and returns once it finishes. Progress streams as `agent/event` events. */\r\n async send(sessionId: string | undefined, text: string, options: SendOptions = {}) {\r\n if (!this.home.llm.list().length) {\r\n throw new MushinError('unavailable', 'Add an LLM provider before using the Agent')\r\n }\r\n const usage = await this.usage()\r\n if (usage.budget && usage.input + usage.output >= usage.budget) {\r\n throw new MushinError('unavailable', `The Agent used its daily budget of ${usage.budget} tokens; raise it in the Agent settings or wait until tomorrow`)\r\n }\r\n const session = sessionId ? await this.session(sessionId) : await this.createSession()\r\n if (this.running.has(session.id)) throw new MushinError('conflict', 'The Agent is still working on this conversation')\r\n const running: Running = { abort: new AbortController(), confirms: new Map(), usage: { inputTokens: 0, outputTokens: 0 }, failures: new Map() }\r\n this.running.set(session.id, running)\r\n const skills = options.skills?.length ? await Promise.all(options.skills.map((id) => this.skill(id))) : []\r\n if (!session.title) session.title = (text || skills.map((skill) => skill.name).join(', ')).replace(/\\s+/g, ' ').slice(0, 48)\r\n if (!session.messages.length && options.scene) {\r\n session.scene = { key: options.scene.key, ...(options.scene.label ? { label: options.scene.label } : {}), ...(options.page ? { page: options.page } : {}) }\r\n }\r\n session.tags = [...new Set([...session.tags ?? [], ...turnTags(text, options, skills)])]\r\n const quote = options.quote ? await this.quoteChat(options.quote) : undefined\r\n session.messages.push({\r\n role: 'user',\r\n content: [contextNote(this.turnContext(options.page, options.scene)), ...skills.map(skillBlock), quote ? quoteBlock(quote) : '', text].filter(Boolean).join('\\n\\n'),\r\n display: text,\r\n ...(skills.length ? { skills: skills.map((skill) => skill.name) } : {}),\r\n ...(quote ? { quote } : {}),\r\n at: Date.now(),\r\n })\r\n await this.save(session)\r\n this.emit({ session: session.id, type: 'start' })\r\n try {\r\n const final = await this.loop(session, running, options)\r\n this.emit({ session: session.id, type: 'done', text: final?.text ?? '', usage: running.usage })\r\n } catch (error) {\r\n const message = running.abort.signal.aborted ? 'Stopped' : error instanceof Error ? error.message : String(error)\r\n this.emit({ session: session.id, type: 'error', error: message, ...(error instanceof StepLimit && !running.abort.signal.aborted ? { code: 'max_steps' as const } : {}) })\r\n } finally {\r\n this.running.delete(session.id)\r\n await this.save(session)\r\n }\r\n return { session: session.id }\r\n }\r\n\r\n private async loop(session: AgentSession, running: Running, options: SendOptions) {\r\n let last: LlmResult | undefined\r\n for (let step = 0; step < this.config.maxSteps; step++) {\r\n const history: LlmMessage[] = [{ role: 'system', content: SYSTEM_PROMPT }, ...session.messages.map(stripMeta)]\r\n let result: LlmResult | undefined\r\n for await (const event of this.home.llm.stream({\r\n provider: this.config.provider,\r\n model: this.config.model,\r\n messages: history,\r\n tools: session.tools,\r\n signal: running.abort.signal,\r\n })) {\r\n if (event.type === 'delta') this.emit({ session: session.id, type: 'delta', text: event.text })\r\n else if (event.type === 'result') result = event.result\r\n }\r\n if (!result) throw new Error('The provider returned no result')\r\n last = result\r\n if (result.usage) {\r\n running.usage.inputTokens += result.usage.inputTokens\r\n running.usage.outputTokens += result.usage.outputTokens\r\n await this.addUsage(result.usage)\r\n }\r\n session.messages.push({\r\n role: 'assistant',\r\n content: result.text,\r\n ...(result.toolCalls.length ? { toolCalls: result.toolCalls } : {}),\r\n ...(result.raw ? { raw: result.raw } : {}),\r\n at: Date.now(),\r\n })\r\n if (!result.toolCalls.length) return result\r\n\r\n // A tool call cut off by the output limit, or in a refused turn, may be truncated: never run it.\r\n if (result.finishReason === 'length' || result.finishReason === 'refusal') {\r\n const reason = result.finishReason === 'length'\r\n ? 'The reply hit the output limit, so this tool call may be incomplete and was not run.'\r\n : 'The model declined this turn, so this tool call was not run.'\r\n for (const call of result.toolCalls) {\r\n session.messages.push({ role: 'tool', toolCallId: call.id, content: reason, isError: true, at: Date.now() })\r\n }\r\n throw new Error(reason)\r\n }\r\n\r\n for (const call of result.toolCalls) {\r\n await this.runTool(session, running, call, options)\r\n }\r\n // One round is left: ask for a summary instead of a turn that just stops mid-way.\r\n if (step === this.config.maxSteps - 2) {\r\n const last = session.messages.at(-1)!\r\n last.content += `\\n\\n[This was the last tool round for this message (the limit is ${this.config.maxSteps}). Do not call tools now: tell the user what is done, what is left, and that they can send another message to continue.]`\r\n }\r\n await this.save(session)\r\n }\r\n throw new StepLimit(this.config.maxSteps)\r\n }\r\n\r\n private async runTool(session: AgentSession, running: Running, call: ToolCall, options: SendOptions) {\r\n const name = fromToolName(call.name)\r\n const info = this.home.actions.get(name)\r\n const reply = (content: string, isError = false) => {\r\n session.messages.push({ role: 'tool', toolCallId: call.id, content, ...(isError ? { isError } : {}), at: Date.now() })\r\n }\r\n\r\n let input: unknown\r\n try {\r\n input = JSON.parse(call.arguments || '{}')\r\n } catch {\r\n this.emit({ session: session.id, type: 'tool-result', id: call.id, ok: false, error: 'Arguments are not valid JSON' })\r\n return reply('The arguments were not valid JSON. Send a JSON object that matches the tool schema.', true)\r\n }\r\n if (!info || !info.agent) {\r\n this.emit({ session: session.id, type: 'tool-result', id: call.id, ok: false, error: `Unknown tool ${call.name}` })\r\n return reply(`The tool ${call.name} is not available right now.`, true)\r\n }\r\n\r\n const policy = this.policyOf(await this.settings(), info)\r\n if (policy === 'off') {\r\n this.emit({ session: session.id, type: 'tool-result', id: call.id, ok: false, error: 'Turned off in the Agent settings' })\r\n return reply(`The user turned ${call.name} off for the Agent. Do not use it; tell them if it is needed.`, true)\r\n }\r\n\r\n this.emit({ session: session.id, type: 'tool-call', id: call.id, action: name, input, risk: info.risk })\r\n\r\n if (policy === 'confirm') {\r\n this.emit({ session: session.id, type: 'confirm', id: call.id, action: name, input })\r\n const approved = await this.waitForApproval(running, call.id)\r\n if (!approved) {\r\n this.emit({ session: session.id, type: 'tool-result', id: call.id, ok: false, error: 'Declined by the user' })\r\n return reply('The user declined this action. Do not retry it.', true)\r\n }\r\n }\r\n\r\n try {\r\n const result = await this.home.actions.call(name, input, { kind: 'agent', session: session.id, client: options.client })\r\n this.emit({ session: session.id, type: 'tool-result', id: call.id, ok: true, result })\r\n reply(truncate(JSON.stringify(result ?? { ok: true })))\r\n } catch (error) {\r\n const message = error instanceof Error ? error.message : String(error)\r\n this.emit({ session: session.id, type: 'tool-result', id: call.id, ok: false, error: message })\r\n const failures = (running.failures.get(name) ?? 0) + 1\r\n running.failures.set(name, failures)\r\n const hint = failures >= FAILURE_HINT_AFTER\r\n ? `\\n${call.name} has failed ${failures} times in this reply. Stop retrying it with guessed inputs: take valid values from the error above or from the tool that lists them, or tell the user what is missing.`\r\n : ''\r\n reply(`Error: ${message}${hint}`, true)\r\n }\r\n }\r\n\r\n private waitForApproval(running: Running, callId: string) {\r\n return new Promise<boolean>((resolve) => {\r\n const timer = setTimeout(() => finish(false), this.config.confirmTimeout * 1000)\r\n const finish = (approved: boolean) => {\r\n clearTimeout(timer)\r\n running.confirms.delete(callId)\r\n resolve(approved)\r\n }\r\n running.confirms.set(callId, finish)\r\n running.abort.signal.addEventListener('abort', () => finish(false), { once: true })\r\n })\r\n }\r\n\r\n confirm(sessionId: string, callId: string, approved: boolean) {\r\n const resolve = this.running.get(sessionId)?.confirms.get(callId)\r\n if (!resolve) throw new MushinError('not_found', 'No action is waiting for approval')\r\n resolve(approved)\r\n return { ok: true }\r\n }\r\n\r\n cancel(sessionId: string) {\r\n const running = this.running.get(sessionId)\r\n if (!running) return { ok: false }\r\n running.abort.abort()\r\n return { ok: true }\r\n }\r\n\r\n status() {\r\n return { ready: this.home.llm.isReady(), providers: this.home.llm.list().length, running: [...this.running.keys()] }\r\n }\r\n\r\n private *defineActions() {\r\n const actions = this.home.actions\r\n\r\n yield actions.define({\r\n name: 'agent.status',\r\n description: 'Whether the Agent can run (a provider exists and passed its test).',\r\n risk: 'read',\r\n input: z.object({}),\r\n handler: () => this.status(),\r\n })\r\n\r\n yield actions.define({\r\n name: 'agent.sessions',\r\n description: 'List Agent conversations, newest first.',\r\n risk: 'read',\r\n input: z.object({}),\r\n handler: () => this.sessions(),\r\n })\r\n\r\n yield actions.define({\r\n name: 'agent.session',\r\n description: 'Get one Agent conversation with its messages.',\r\n risk: 'read',\r\n input: z.object({ id: z.string() }),\r\n handler: async ({ id }) => {\r\n const { tools, ...session } = await this.session(id)\r\n const now = new Set((await this.tools()).map((tool) => tool.name))\r\n const toolsStale = tools.length !== now.size || tools.some((tool) => !now.has(tool.name))\r\n return { ...session, messages: session.messages.map(({ raw, ...message }: any) => message), running: this.running.has(id), toolsStale }\r\n },\r\n })\r\n\r\n yield actions.define({\r\n name: 'agent.send',\r\n description: 'Send a message to the Agent. Omit session to start a new conversation. Progress streams over the WebSocket.',\r\n risk: 'write',\r\n input: z.object({\r\n session: z.string().optional(),\r\n text: z.string(),\r\n page: z.string().optional(),\r\n scene: z.object({\r\n key: z.string(),\r\n label: z.string().max(200).optional(),\r\n hint: z.string().max(1000).optional(),\r\n state: z.record(z.string(), z.union([z.string().max(200), z.number(), z.boolean()])).optional(),\r\n resource: z.string().max(200).optional(),\r\n }).optional().describe('The dashboard page as the dashboard describes it'),\r\n skills: z.array(z.string()).max(5).optional().describe('Skill ids to apply to this message'),\r\n quote: z.object({\r\n bot: z.string(),\r\n channel: z.string().describe('The chat\\'s id'),\r\n id: z.string().describe('The quoted message\\'s record id, from bots.messages'),\r\n before: z.number().int().min(0).max(30).optional(),\r\n after: z.number().int().min(0).max(10).optional(),\r\n }).optional().describe('A message of a bot\\'s chat to quote, with a few messages around it'),\r\n }).refine((input) => input.text.trim() || input.skills?.length, 'Send some text or pick a skill'),\r\n handler: ({ session, text, ...options }, caller) => this.send(session, text, { client: caller.client, ...options }),\r\n })\r\n\r\n yield actions.define({\r\n name: 'agent.search',\r\n description: 'Search Agent conversations by text and tags (scene:<page kind>, skill:<id>, command:<name>, resource:<kind>:<id>, status:running).',\r\n risk: 'read',\r\n input: z.object({ query: z.string().optional(), tags: z.array(z.string()).optional(), limit: z.number().int().min(1).max(200).optional() }),\r\n handler: (input) => this.search(input),\r\n })\r\n\r\n yield actions.define({\r\n name: 'agent.commands',\r\n description: 'Commands for the Agent\\'s \"/\" picker: its own (new, history, …) and every bot\\'s commands.',\r\n risk: 'read',\r\n input: z.object({}),\r\n handler: () => this.commands(),\r\n })\r\n\r\n yield actions.define({\r\n name: 'agent.skills.list',\r\n description: 'List the Agent\\'s skills: built in, from plugins, and written by the user.',\r\n risk: 'read',\r\n input: z.object({}),\r\n handler: () => this.skills(),\r\n })\r\n\r\n yield actions.define({\r\n name: 'agent.skills.get',\r\n description: 'Get one Agent skill with its instructions.',\r\n risk: 'read',\r\n input: z.object({ id: z.string() }),\r\n handler: ({ id }) => this.skill(id),\r\n })\r\n\r\n const skillId = z.string().regex(/^[a-z0-9][a-z0-9-]{0,63}$/).describe('Lowercase letters, digits and dashes')\r\n\r\n yield actions.define({\r\n name: 'agent.skills.create',\r\n description: 'Create a user skill. Omit id to make one from the name.',\r\n risk: 'write',\r\n input: skillInput.extend({ id: skillId.optional() }),\r\n handler: (input) => this.createSkill(input),\r\n })\r\n\r\n yield actions.define({\r\n name: 'agent.skills.update',\r\n description: 'Change a skill. Changing a built-in or plugin skill saves your own copy that replaces it until deleted.',\r\n risk: 'write',\r\n input: z.object({\r\n id: z.string(),\r\n name: skillFields.name.optional(),\r\n description: z.string().trim().max(300).optional(),\r\n instructions: skillFields.instructions.optional(),\r\n whenToUse: skillFields.whenToUse,\r\n tools: skillFields.tools,\r\n scenes: skillFields.scenes,\r\n }),\r\n handler: ({ id, ...patch }) => this.updateSkill(id, patch),\r\n })\r\n\r\n yield actions.define({\r\n name: 'agent.skills.delete',\r\n description: 'Delete a user skill. A built-in or plugin skill it replaced comes back.',\r\n risk: 'write',\r\n input: z.object({ id: z.string() }),\r\n handler: ({ id }) => this.deleteSkill(id),\r\n })\r\n\r\n yield actions.define({\r\n name: 'agent.skills.setEnabled',\r\n description: 'Turn a skill on or off; off skills are not offered with $.',\r\n risk: 'write',\r\n input: z.object({ id: z.string(), enabled: z.boolean() }),\r\n handler: ({ id, enabled }) => this.setSkillEnabled(id, enabled),\r\n })\r\n\r\n yield actions.define({\r\n name: 'agent.skills.import',\r\n description: 'Import a skill from a SKILL.md file (YAML frontmatter with name and description, then Markdown instructions), as used by Claude and Codex skills.',\r\n risk: 'write',\r\n input: z.object({ markdown: z.string().min(1).max(40_000), replace: z.boolean().optional().describe('Overwrite a skill with the same id') }),\r\n handler: async ({ markdown, replace }) => {\r\n let parsed: ReturnType<typeof parseSkillMarkdown>\r\n try {\r\n parsed = parseSkillMarkdown(markdown)\r\n } catch (error) {\r\n throw new MushinError('invalid_input', error instanceof Error ? error.message : String(error))\r\n }\r\n const input = skillInput.extend({ id: skillId.optional() }).parse(parsed)\r\n if (replace && input.id) return this.saveSkill({ ...input, id: input.id })\r\n return this.createSkill(input)\r\n },\r\n })\r\n\r\n yield actions.define({\r\n name: 'agent.skills.export',\r\n description: 'A skill as a SKILL.md file.',\r\n risk: 'read',\r\n input: z.object({ id: z.string() }),\r\n handler: async ({ id }) => ({ fileName: 'SKILL.md', markdown: formatSkillMarkdown(await this.skill(id)) }),\r\n })\r\n\r\n yield actions.define({\r\n name: 'agent.profiles.list',\r\n description: 'What the Agent says and offers on each dashboard page, as the user changed it: hint, welcome line, own suggestions, hidden built-in suggestions, recommended skills.',\r\n risk: 'read',\r\n input: z.object({}),\r\n handler: async () => ({ scenes: SCENE_KEYS, profiles: await this.profiles() }),\r\n })\r\n\r\n yield actions.define({\r\n name: 'agent.profiles.update',\r\n description: 'Change what the Agent says and offers on one dashboard page. Send the whole profile; null goes back to the defaults.',\r\n risk: 'write',\r\n input: z.object({ scene: z.enum(SCENE_KEYS), profile: profileInput.nullable() }),\r\n handler: ({ scene, profile }) => this.setProfile(scene, profile),\r\n })\r\n\r\n yield actions.define({\r\n name: 'agent.policy.list',\r\n description: 'Every tool the Agent can use, with its plugin, risk and policy: auto (runs), confirm (asks the user first) or off (not offered).',\r\n risk: 'read',\r\n input: z.object({}),\r\n handler: () => this.policies(),\r\n })\r\n\r\n yield actions.define({\r\n name: 'agent.policy.set',\r\n description: 'Set the policy of tools by action name: auto, confirm, or off; null goes back to the default (dangerous actions ask, others run). Off tools leave new conversations only.',\r\n risk: 'dangerous',\r\n input: z.object({ policies: z.record(z.string(), policyInput.nullable()) }),\r\n handler: ({ policies }) => this.setPolicy(policies),\r\n })\r\n\r\n yield actions.define({\r\n name: 'agent.usage',\r\n description: 'Tokens the Agent used today and its daily budget (0 means no limit).',\r\n risk: 'read',\r\n input: z.object({}),\r\n handler: () => this.usage(),\r\n })\r\n\r\n yield actions.define({\r\n name: 'agent.confirm',\r\n description: 'Approve or decline an action the Agent is waiting on.',\r\n risk: 'write',\r\n input: z.object({ session: z.string(), id: z.string(), approved: z.boolean() }),\r\n handler: ({ session, id, approved }) => this.confirm(session, id, approved),\r\n })\r\n\r\n yield actions.define({\r\n name: 'agent.cancel',\r\n description: 'Stop the Agent\\'s current reply in a conversation.',\r\n risk: 'write',\r\n input: z.object({ session: z.string() }),\r\n handler: ({ session }) => this.cancel(session),\r\n })\r\n\r\n yield actions.define({\r\n name: 'agent.deleteSession',\r\n description: 'Delete an Agent conversation.',\r\n risk: 'write',\r\n input: z.object({ id: z.string() }),\r\n handler: ({ id }) => this.deleteSession(id),\r\n })\r\n }\r\n}\r\n\r\nfunction describeTool(action: ActionInfo) {\r\n const notes: string[] = []\r\n if (action.risk === 'dangerous') notes.push('Dangerous: the user must approve it.')\r\n if (action.client) notes.push('Runs in the user\\'s dashboard; fails if none is connected.')\r\n return [action.description, ...notes].join(' ')\r\n}\r\n\r\n/** Search tags for one message: its scene, skills, a leading command, and the page's resource. */\r\n/** A quoted chat as the model reads it; the picked message is marked, with its record id for samples. */\r\nfunction quoteBlock(quote: QuotedChat) {\r\n const where = quote.channel.type === 'group' ? `group ${quote.channel.name ? `${quote.channel.name} ` : ''}(${quote.channel.id})` : `private chat with ${quote.channel.id}`\r\n const lines = quote.lines.map((line) => {\r\n const time = new Date(line.at).toISOString().slice(11, 16)\r\n const who = line.direction === 'out' ? `${quote.botName} (bot)` : `${line.user} (${line.userId})`\r\n return `${line.id === quote.focus ? '→ ' : ' '}[${time}] ${who}: ${line.text}`\r\n })\r\n return [\r\n `<quote bot=\"${quote.bot}\" chat=\"${quote.channel.id}\" message=\"${quote.focus}\">`,\r\n `Messages from ${quote.botName} in the ${where}; the user picked the one marked →. To build or check a flow for it, pass sample { bot: \"${quote.bot}\", id: \"${quote.focus}\", channel: \"${quote.channel.id}\" } to flows.test or flows.preview.`,\r\n ...lines,\r\n '</quote>',\r\n ].join('\\n')\r\n}\r\n\r\nfunction turnTags(text: string, options: SendOptions, skills: AgentSkill[]) {\r\n const tags: string[] = []\r\n if (options.scene) tags.push(`scene:${options.scene.key}`)\r\n if (options.scene?.resource) tags.push(`resource:${options.scene.resource}`)\r\n for (const skill of skills) tags.push(`skill:${skill.id}`)\r\n const command = /^\\s*\\/([\\p{L}\\p{N}_-]+)/u.exec(text)\r\n if (command) tags.push(`command:${command[1]}`)\r\n return tags\r\n}\r\n\r\nfunction stripMeta(message: AgentMessage): LlmMessage {\r\n const { display, skills, quote, at, ...rest } = message\r\n return rest as LlmMessage\r\n}\r\n\r\nfunction truncate(text: string) {\r\n if (text.length <= MAX_RESULT_CHARS) return text\r\n return `${text.slice(0, MAX_RESULT_CHARS)}… [truncated ${text.length - MAX_RESULT_CHARS} characters; ask for less, e.g. with a filter or limit]`\r\n}\r\n\r\nexport default Agent\r\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import {\n type ActionInfo, Context, field, fromToolName, MushinError, randomId, segmentsToText, Service, toToolName, z,\n} from '@mushinjs/core'\nimport type { LlmMessage, LlmResult, ToolCall, ToolDefinition } from '@mushinjs/plugin-providers'\nimport type {} from '@mushinjs/plugin-storage'\nimport { contextNote, type SceneInfo, skillBlock, SYSTEM_PROMPT, type TurnContext } from './prompt'\nimport {\n type AgentSettings, defaultPolicy, formatSkillMarkdown, parseSkillMarkdown, policyInput, profileInput, SCENE_KEYS, type SceneProfile, today,\n type TokenUsage, type ToolPolicy,\n} from './settings'\nimport { type AgentSkill, BUILTIN_SKILLS, type SkillDefinition, skillFields, skillInput } from './skills'\n\nexport * from './prompt'\nexport * from './settings'\nexport * from './skills'\n\ndeclare module '@mushinjs/core' {\n interface Context {\n agent: Agent\n }\n\n interface Events {\n 'agent/event'(event: AgentEvent): void\n /** Skills, page profiles or tool policies changed. */\n 'agent/changed'(): void\n }\n}\n\nexport type AgentEvent = { session: string } & (\n | { type: 'start' }\n | { type: 'delta'; text: string }\n | { type: 'tool-call'; id: string; action: string; input: unknown; risk: string }\n | { type: 'confirm'; id: string; action: string; input: unknown }\n | { type: 'tool-result'; id: string; ok: boolean; result?: unknown; error?: string }\n | { type: 'done'; text: string; usage?: { inputTokens: number; outputTokens: number } }\n /** `code` is `max_steps` when the turn ran out of tool rounds, so the dashboard can offer to go on. */\n | { type: 'error'; error: string; code?: 'max_steps' }\n)\n\n/**\n * A stored message; `display` holds the user's own words when the content carries a context note,\n * and `skills` the names of the skills picked for it.\n */\nexport type AgentMessage = LlmMessage & {\n display?: string\n skills?: string[]\n /** A chat quoted into the message, as the dashboard shows it: who said what, and where. */\n quote?: QuotedChat\n at: number\n}\n\n/** Messages of a bot's chat quoted into an Agent message, around one picked message. */\nexport interface QuotedChat {\n bot: string\n botName: string\n channel: { type: 'group' | 'private'; id: string; name?: string }\n /** The picked message's record id; a sample for flows.test and flows.preview. */\n focus: string\n lines: { id: string; direction: 'in' | 'out'; user: string; userId: string; text: string; at: number }[]\n}\n\n/** Where a conversation was started, for the history list. */\nexport interface SessionScene {\n key: string\n label?: string\n page?: string\n}\n\nexport interface AgentSession {\n id: string\n title: string\n createdAt: number\n updatedAt: number\n /** Tool list frozen at creation, so every request in the session sends identical tools. */\n tools: ToolDefinition[]\n messages: AgentMessage[]\n /** The page the conversation was started on. */\n scene?: SessionScene\n /** What it touched, for search: `scene:<key>`, `skill:<id>`, `command:<name>`, `resource:<kind>:<id>`. */\n tags?: string[]\n}\n\nexport interface SendOptions {\n /** Dashboard connection id; client actions such as ui.navigate are routed back to it. */\n client?: string\n page?: string\n /** The page as the dashboard describes it; its hint and state go into the context note. */\n scene?: SceneInfo\n /** Ids of skills whose instructions go into this message. */\n skills?: string[]\n /** A message of a bot's chat to quote, with a few messages around it. */\n quote?: { bot: string; channel: string; id: string; before?: number; after?: number }\n}\n\n/** Commands the dashboard runs itself, without asking the model. */\nexport const BUILTIN_COMMANDS = [\n { name: 'new', description: 'Start a new conversation', 'zh-CN': '开始新对话' },\n { name: 'history', description: 'Open the full conversation history', 'zh-CN': '打开完整历史' },\n { name: 'model', description: 'Switch the Agent\\'s model', 'zh-CN': '切换模型' },\n { name: 'status', description: 'Show how much context this conversation uses', 'zh-CN': '查看上下文用量' },\n { name: 'clear', description: 'Clear the input and close the conversation', 'zh-CN': '清空当前对话视图' },\n { name: 'help', description: 'Show what you can type', 'zh-CN': '查看可用的指令和技能' },\n]\n\nconst SETTINGS_KEY = 'agent/settings/main'\nconst USAGE_KEY = 'agent/settings/usage'\n\nconst MAX_RESULT_CHARS = 16_000\n\nexport const Config = z.object({\n provider: z.string().optional().meta(field('Provider', 'Provider or model profile for the Agent; empty uses the default provider', {\n 'zh-CN': { title: '提供商', description: '智能体使用的提供商或配置方案;留空使用默认提供商' },\n }, { choices: 'providers.choices' })),\n model: z.string().optional().meta(field('Model', 'Model for the Agent; empty uses the provider\\'s default', {\n 'zh-CN': { title: '模型', description: '智能体使用的模型;留空使用提供商默认模型' },\n })),\n maxSteps: z.number().int().min(1).max(50).default(20).meta(field('Max steps', 'Most tool-calling rounds in one reply', {\n 'zh-CN': { title: '最大步数', description: '一次回复中最多调用工具的轮数' },\n })),\n confirmTimeout: z.number().int().min(10).default(600).meta(field('Approval timeout', 'Seconds to wait for approval of a dangerous action', {\n 'zh-CN': { title: '确认超时', description: '等待用户批准危险操作的秒数' },\n })),\n dailyTokens: z.number().int().min(0).default(0).meta(field('Daily token budget', 'Input and output tokens the Agent may use per day; 0 means no limit', {\n 'zh-CN': { title: '每日 Token 预算', description: '智能体每天最多使用的输入和输出 Token;0 表示不限制' },\n })),\n})\n\nexport type Config = z.infer<typeof Config>\n\ninterface Running {\n abort: AbortController\n confirms: Map<string, (approved: boolean) => void>\n /** Tokens of every request in this turn. */\n usage: { inputTokens: number; outputTokens: number }\n /** Failed calls per tool in this turn, to tell the model to stop guessing. */\n failures: Map<string, number>\n}\n\n/** The turn used every tool round it may; the dashboard offers to continue. */\nclass StepLimit extends Error {\n constructor(steps: number) {\n super(`Stopped after ${steps} tool rounds; send another message to continue`)\n }\n}\n\n/** After this many failures of one tool in a turn, its errors ask the model to change course. */\nconst FAILURE_HINT_AFTER = 3\n\n/** Runs conversations in which the LLM operates Mushin.js through the action registry. */\nexport class Agent extends Service {\n static inject = ['actions', 'llm', 'storage']\n static Config = Config\n\n private home: Context\n private running = new Map<string, Running>()\n private pluginSkills = new Map<string, AgentSkill>()\n private settingsCache?: AgentSettings\n\n constructor(ctx: Context, public config: Config) {\n super(ctx, 'agent')\n this.home = ctx\n }\n\n *[Service.init]() {\n yield* this.defineActions()\n yield () => {\n for (const id of this.running.keys()) this.cancel(id)\n }\n }\n\n /** Tools offered to the model: every action except the Agent's own and those turned off. */\n async tools(): Promise<ToolDefinition[]> {\n const settings = await this.settings()\n return this.home.actions.list()\n .filter((action) => action.agent && !action.name.startsWith('agent.') && this.policyOf(settings, action) !== 'off')\n .map((action) => ({\n name: toToolName(action.name),\n description: describeTool(action),\n parameters: action.inputSchema,\n }))\n }\n\n // ---- settings ----\n\n async settings(): Promise<AgentSettings> {\n if (!this.settingsCache) {\n const saved = await this.home.storage.get<Partial<AgentSettings>>(SETTINGS_KEY)\n this.settingsCache = { profiles: {}, toolPolicy: {}, disabledSkills: [], ...saved }\n }\n return this.settingsCache\n }\n\n private async updateSettings(change: (settings: AgentSettings) => void) {\n const settings = await this.settings()\n change(settings)\n await this.home.storage.set(SETTINGS_KEY, settings)\n this.home.emit('agent/changed')\n return settings\n }\n\n private policyOf(settings: AgentSettings, action: Pick<ActionInfo, 'name' | 'risk'>): ToolPolicy {\n return settings.toolPolicy[action.name] ?? defaultPolicy(action.risk)\n }\n\n /** Every action with its policy, for the tool policy table. */\n async policies() {\n const settings = await this.settings()\n return this.home.actions.list()\n .filter((action) => action.agent && !action.name.startsWith('agent.'))\n .map((action) => ({\n name: action.name,\n description: action.description,\n plugin: action.plugin,\n risk: action.risk,\n client: action.client,\n policy: this.policyOf(settings, action),\n custom: action.name in settings.toolPolicy,\n }))\n }\n\n /** Sets the policy of some actions; `null` goes back to the default for the action's risk. */\n async setPolicy(changes: Record<string, ToolPolicy | null>) {\n await this.updateSettings((settings) => {\n for (const [name, policy] of Object.entries(changes)) {\n if (policy === null) delete settings.toolPolicy[name]\n else settings.toolPolicy[name] = policy\n }\n })\n return this.policies()\n }\n\n async profiles() {\n return (await this.settings()).profiles\n }\n\n async setProfile(scene: string, profile: SceneProfile | null) {\n const settings = await this.updateSettings((settings) => {\n if (profile === null) delete settings.profiles[scene]\n else settings.profiles[scene] = profile\n })\n return settings.profiles[scene] ?? {}\n }\n\n /** Tokens used today and the daily budget. */\n async usage() {\n const saved = await this.home.storage.get<TokenUsage>(USAGE_KEY)\n const used = saved?.day === today() ? saved : { day: today(), input: 0, output: 0 }\n return { ...used, budget: this.config.dailyTokens }\n }\n\n private async addUsage(usage: { inputTokens: number; outputTokens: number }) {\n const current = await this.usage()\n await this.home.storage.set(USAGE_KEY, { day: current.day, input: current.input + usage.inputTokens, output: current.output + usage.outputTokens })\n }\n\n private emit(event: AgentEvent) {\n this.home.emit('agent/event', event)\n }\n\n private async allSessions() {\n const keys = await this.home.storage.list('agent')\n const sessions = await Promise.all(keys.map((key) => this.home.storage.get<AgentSession>(key)))\n return sessions\n .filter((session): session is AgentSession => !!session && Array.isArray(session.messages))\n .sort((a, b) => b.updatedAt - a.updatedAt)\n }\n\n private summary({ id, title, createdAt, updatedAt, scene, tags }: AgentSession) {\n return { id, title, createdAt, updatedAt, scene, tags: tags ?? [], running: this.running.has(id) }\n }\n\n async sessions() {\n return (await this.allSessions()).map((session) => this.summary(session))\n }\n\n /**\n * Conversations matching every tag (`scene:flowEditor`, `skill:<id>`, `status:running`, …) and\n * containing the query in the title or in what the user or the Agent wrote.\n */\n async search(options: { query?: string; tags?: string[]; limit?: number } = {}) {\n const query = options.query?.trim().toLowerCase()\n const results = []\n for (const session of await this.allSessions()) {\n const summary = this.summary(session)\n const tags = [...summary.tags, `status:${summary.running ? 'running' : 'idle'}`]\n if (options.tags?.some((tag) => !tags.includes(tag))) continue\n let snippet: string | undefined\n if (query) {\n if (!session.title.toLowerCase().includes(query)) {\n const texts = session.messages\n .filter((message) => message.role === 'user' || message.role === 'assistant')\n .map((message) => (message.role === 'user' ? message.display ?? message.content : message.content))\n const hit = texts.find((text): text is string => typeof text === 'string' && text.toLowerCase().includes(query))\n if (!hit) continue\n const at = hit.toLowerCase().indexOf(query)\n snippet = `${at > 30 ? '…' : ''}${hit.slice(Math.max(0, at - 30), at + query.length + 50).replace(/\\s+/g, ' ')}`\n }\n }\n results.push({ ...summary, ...(snippet ? { snippet } : {}) })\n if (results.length >= (options.limit ?? 50)) break\n }\n return results\n }\n\n // ---- skills ----\n\n /** Adds a skill from a plugin; removed when the plugin unloads. */\n defineSkill(definition: SkillDefinition) {\n const ctx = this.ctx\n const skill: AgentSkill = { ...definition, source: 'plugin', plugin: ctx.fiber.name, enabled: true }\n return ctx.effect(() => {\n this.pluginSkills.set(skill.id, skill)\n return () => {\n if (this.pluginSkills.get(skill.id) === skill) this.pluginSkills.delete(skill.id)\n }\n }, `agent.defineSkill(${definition.id})`)\n }\n\n /** Built-in, plugin and user skills; user skills win on the same id. */\n async skills(): Promise<AgentSkill[]> {\n const disabled = new Set((await this.settings()).disabledSkills)\n const byId = new Map<string, AgentSkill>()\n for (const skill of BUILTIN_SKILLS) byId.set(skill.id, { ...skill, source: 'builtin', enabled: true })\n for (const skill of this.pluginSkills.values()) byId.set(skill.id, { ...skill })\n const keys = await this.home.storage.list('agent/skills')\n for (const skill of await Promise.all(keys.map((key) => this.home.storage.get<AgentSkill>(key)))) {\n if (skill?.id) byId.set(skill.id, { ...skill, source: 'user', enabled: skill.enabled !== false })\n }\n return [...byId.values()].map((skill) => (skill.source !== 'user' && disabled.has(skill.id) ? { ...skill, enabled: false } : skill))\n }\n\n async skill(id: string) {\n const skill = (await this.skills()).find((item) => item.id === id)\n if (!skill) throw new MushinError('not_found', `No skill \"${id}\"`)\n return skill\n }\n\n /** Saves a user skill. With the id of a built-in or plugin skill it replaces that one until deleted. */\n async saveSkill(input: SkillDefinition & { enabled?: boolean }) {\n const skill: AgentSkill = { ...input, source: 'user', enabled: input.enabled !== false }\n await this.home.storage.set(`agent/skills/${skill.id}`, skill)\n this.home.emit('agent/changed')\n return this.skill(skill.id)\n }\n\n async createSkill(input: Omit<SkillDefinition, 'id'> & { id?: string }) {\n const taken = new Set((await this.skills()).map((skill) => skill.id))\n let id = input.id ?? (input.name.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '').slice(0, 40) || randomId(6).toLowerCase())\n if (taken.has(id) && !input.id) id = `${id}-${randomId(4).toLowerCase()}`\n else if (taken.has(id)) throw new MushinError('conflict', `A skill with id \"${id}\" already exists`)\n return this.saveSkill({ ...input, id })\n }\n\n async updateSkill(id: string, patch: Partial<Omit<SkillDefinition, 'id'>>) {\n const current = await this.skill(id)\n const { source, plugin, enabled, ...rest } = current\n return this.saveSkill({ ...rest, ...patch, id, enabled })\n }\n\n /** Deletes a user skill; a built-in or plugin skill it replaced comes back. */\n async deleteSkill(id: string) {\n const current = await this.skill(id)\n if (current.source !== 'user') throw new MushinError('forbidden', 'Built-in and plugin skills cannot be deleted; turn them off instead')\n await this.home.storage.delete(`agent/skills/${id}`)\n this.home.emit('agent/changed')\n return { deleted: id, restored: (await this.skills()).some((skill) => skill.id === id) }\n }\n\n async setSkillEnabled(id: string, enabled: boolean) {\n const current = await this.skill(id)\n if (current.source === 'user') {\n await this.home.storage.set(`agent/skills/${id}`, { ...current, enabled })\n this.home.emit('agent/changed')\n return this.skill(id)\n }\n await this.updateSettings((settings) => {\n settings.disabledSkills = enabled ? settings.disabledSkills.filter((item) => item !== id) : [...new Set([...settings.disabledSkills, id])]\n })\n return this.skill(id)\n }\n\n /** Agent commands and the commands of every bot, for the `/` picker. */\n commands() {\n const bots = this.home.get('bots')\n const names = new Map<string, string>((bots?.list() ?? []).map((bot: { id: string; name: string }) => [bot.id, bot.name]))\n const listed = bots?.commandList().commands ?? []\n return {\n builtin: BUILTIN_COMMANDS,\n bots: listed.filter((entry: { hidden?: boolean }) => !entry.hidden).map((entry: any) => ({\n name: entry.name,\n description: entry.description,\n usage: entry.usage,\n permission: entry.permission ?? entry.role,\n bot: entry.botId,\n botName: names.get(entry.botId),\n source: entry.source,\n })),\n }\n }\n\n async session(id: string) {\n const session = await this.home.storage.get<AgentSession>(`agent/${id}`)\n if (!session) throw new MushinError('not_found', `No Agent session \"${id}\"`)\n return session\n }\n\n async createSession(): Promise<AgentSession> {\n const now = Date.now()\n const session: AgentSession = { id: randomId(), title: '', createdAt: now, updatedAt: now, tools: await this.tools(), messages: [] }\n await this.save(session)\n return session\n }\n\n async deleteSession(id: string) {\n this.cancel(id)\n await this.home.storage.delete(`agent/${id}`)\n return { deleted: id }\n }\n\n private save(session: AgentSession) {\n session.updatedAt = Date.now()\n return this.home.storage.set(`agent/${session.id}`, session)\n }\n\n private turnContext(page?: string, scene?: SceneInfo): TurnContext {\n const providers = this.home.llm.list()\n const bots = this.home.get('bots')?.list() ?? []\n return {\n page,\n scene,\n providers: providers.length,\n ready: this.home.llm.isReady(),\n bots: bots.length,\n online: bots.filter((bot: { status: string }) => bot.status === 'online').length,\n }\n }\n\n /** A bot's chat around one message, for quoting into an Agent message. */\n private async quoteChat(input: NonNullable<SendOptions['quote']>): Promise<QuotedChat> {\n const bots = this.home.get('bots')\n if (!bots) throw new MushinError('unavailable', 'Quoting a chat needs the bots plugin')\n const record = bots.get(input.bot)\n const list = await bots.messages(input.bot, { channel: input.channel, limit: 300 })\n const index = list.findIndex((item) => item.id === input.id)\n if (index < 0) throw new MushinError('not_found', 'That message is no longer in the chat\\'s recent messages')\n const picked = list.slice(Math.max(0, index - (input.before ?? 6)), index + 1 + (input.after ?? 2))\n return {\n bot: input.bot,\n botName: record.name,\n channel: { type: list[index].channel.type, id: list[index].channel.id, ...(list[index].channel.name ? { name: list[index].channel.name } : {}) },\n focus: input.id,\n lines: picked.map((item) => ({\n id: item.id,\n direction: item.direction,\n user: item.user.name ?? item.user.id,\n userId: item.user.id,\n text: segmentsToText(item.segments).trim().slice(0, 500),\n at: item.timestamp,\n })),\n }\n }\n\n /** Starts a turn and returns once it finishes. Progress streams as `agent/event` events. */\n async send(sessionId: string | undefined, text: string, options: SendOptions = {}) {\n if (!this.home.llm.list().length) {\n throw new MushinError('unavailable', 'Add an LLM provider before using the Agent')\n }\n const usage = await this.usage()\n if (usage.budget && usage.input + usage.output >= usage.budget) {\n throw new MushinError('unavailable', `The Agent used its daily budget of ${usage.budget} tokens; raise it in the Agent settings or wait until tomorrow`)\n }\n const session = sessionId ? await this.session(sessionId) : await this.createSession()\n if (this.running.has(session.id)) throw new MushinError('conflict', 'The Agent is still working on this conversation')\n const running: Running = { abort: new AbortController(), confirms: new Map(), usage: { inputTokens: 0, outputTokens: 0 }, failures: new Map() }\n this.running.set(session.id, running)\n const skills = options.skills?.length ? await Promise.all(options.skills.map((id) => this.skill(id))) : []\n if (!session.title) session.title = (text || skills.map((skill) => skill.name).join(', ')).replace(/\\s+/g, ' ').slice(0, 48)\n if (!session.messages.length && options.scene) {\n session.scene = { key: options.scene.key, ...(options.scene.label ? { label: options.scene.label } : {}), ...(options.page ? { page: options.page } : {}) }\n }\n session.tags = [...new Set([...session.tags ?? [], ...turnTags(text, options, skills)])]\n const quote = options.quote ? await this.quoteChat(options.quote) : undefined\n session.messages.push({\n role: 'user',\n content: [contextNote(this.turnContext(options.page, options.scene)), ...skills.map(skillBlock), quote ? quoteBlock(quote) : '', text].filter(Boolean).join('\\n\\n'),\n display: text,\n ...(skills.length ? { skills: skills.map((skill) => skill.name) } : {}),\n ...(quote ? { quote } : {}),\n at: Date.now(),\n })\n await this.save(session)\n this.emit({ session: session.id, type: 'start' })\n try {\n const final = await this.loop(session, running, options)\n this.emit({ session: session.id, type: 'done', text: final?.text ?? '', usage: running.usage })\n } catch (error) {\n const message = running.abort.signal.aborted ? 'Stopped' : error instanceof Error ? error.message : String(error)\n this.emit({ session: session.id, type: 'error', error: message, ...(error instanceof StepLimit && !running.abort.signal.aborted ? { code: 'max_steps' as const } : {}) })\n } finally {\n this.running.delete(session.id)\n await this.save(session)\n }\n return { session: session.id }\n }\n\n private async loop(session: AgentSession, running: Running, options: SendOptions) {\n let last: LlmResult | undefined\n for (let step = 0; step < this.config.maxSteps; step++) {\n const history: LlmMessage[] = [{ role: 'system', content: SYSTEM_PROMPT }, ...session.messages.map(stripMeta)]\n let result: LlmResult | undefined\n for await (const event of this.home.llm.stream({\n provider: this.config.provider,\n model: this.config.model,\n messages: history,\n tools: session.tools,\n signal: running.abort.signal,\n })) {\n if (event.type === 'delta') this.emit({ session: session.id, type: 'delta', text: event.text })\n else if (event.type === 'result') result = event.result\n }\n if (!result) throw new Error('The provider returned no result')\n last = result\n if (result.usage) {\n running.usage.inputTokens += result.usage.inputTokens\n running.usage.outputTokens += result.usage.outputTokens\n await this.addUsage(result.usage)\n }\n session.messages.push({\n role: 'assistant',\n content: result.text,\n ...(result.toolCalls.length ? { toolCalls: result.toolCalls } : {}),\n ...(result.raw ? { raw: result.raw } : {}),\n at: Date.now(),\n })\n if (!result.toolCalls.length) return result\n\n // A tool call cut off by the output limit, or in a refused turn, may be truncated: never run it.\n if (result.finishReason === 'length' || result.finishReason === 'refusal') {\n const reason = result.finishReason === 'length'\n ? 'The reply hit the output limit, so this tool call may be incomplete and was not run.'\n : 'The model declined this turn, so this tool call was not run.'\n for (const call of result.toolCalls) {\n session.messages.push({ role: 'tool', toolCallId: call.id, content: reason, isError: true, at: Date.now() })\n }\n throw new Error(reason)\n }\n\n for (const call of result.toolCalls) {\n await this.runTool(session, running, call, options)\n }\n // One round is left: ask for a summary instead of a turn that just stops mid-way.\n if (step === this.config.maxSteps - 2) {\n const last = session.messages.at(-1)!\n last.content += `\\n\\n[This was the last tool round for this message (the limit is ${this.config.maxSteps}). Do not call tools now: tell the user what is done, what is left, and that they can send another message to continue.]`\n }\n await this.save(session)\n }\n throw new StepLimit(this.config.maxSteps)\n }\n\n private async runTool(session: AgentSession, running: Running, call: ToolCall, options: SendOptions) {\n const name = fromToolName(call.name)\n const info = this.home.actions.get(name)\n const reply = (content: string, isError = false) => {\n session.messages.push({ role: 'tool', toolCallId: call.id, content, ...(isError ? { isError } : {}), at: Date.now() })\n }\n\n let input: unknown\n try {\n input = JSON.parse(call.arguments || '{}')\n } catch {\n this.emit({ session: session.id, type: 'tool-result', id: call.id, ok: false, error: 'Arguments are not valid JSON' })\n return reply('The arguments were not valid JSON. Send a JSON object that matches the tool schema.', true)\n }\n if (!info || !info.agent) {\n this.emit({ session: session.id, type: 'tool-result', id: call.id, ok: false, error: `Unknown tool ${call.name}` })\n return reply(`The tool ${call.name} is not available right now.`, true)\n }\n\n const policy = this.policyOf(await this.settings(), info)\n if (policy === 'off') {\n this.emit({ session: session.id, type: 'tool-result', id: call.id, ok: false, error: 'Turned off in the Agent settings' })\n return reply(`The user turned ${call.name} off for the Agent. Do not use it; tell them if it is needed.`, true)\n }\n\n this.emit({ session: session.id, type: 'tool-call', id: call.id, action: name, input, risk: info.risk })\n\n if (policy === 'confirm') {\n this.emit({ session: session.id, type: 'confirm', id: call.id, action: name, input })\n const approved = await this.waitForApproval(running, call.id)\n if (!approved) {\n this.emit({ session: session.id, type: 'tool-result', id: call.id, ok: false, error: 'Declined by the user' })\n return reply('The user declined this action. Do not retry it.', true)\n }\n }\n\n try {\n const result = await this.home.actions.call(name, input, { kind: 'agent', session: session.id, client: options.client })\n this.emit({ session: session.id, type: 'tool-result', id: call.id, ok: true, result })\n reply(truncate(JSON.stringify(result ?? { ok: true })))\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n this.emit({ session: session.id, type: 'tool-result', id: call.id, ok: false, error: message })\n const failures = (running.failures.get(name) ?? 0) + 1\n running.failures.set(name, failures)\n const hint = failures >= FAILURE_HINT_AFTER\n ? `\\n${call.name} has failed ${failures} times in this reply. Stop retrying it with guessed inputs: take valid values from the error above or from the tool that lists them, or tell the user what is missing.`\n : ''\n reply(`Error: ${message}${hint}`, true)\n }\n }\n\n private waitForApproval(running: Running, callId: string) {\n return new Promise<boolean>((resolve) => {\n const timer = setTimeout(() => finish(false), this.config.confirmTimeout * 1000)\n const finish = (approved: boolean) => {\n clearTimeout(timer)\n running.confirms.delete(callId)\n resolve(approved)\n }\n running.confirms.set(callId, finish)\n running.abort.signal.addEventListener('abort', () => finish(false), { once: true })\n })\n }\n\n confirm(sessionId: string, callId: string, approved: boolean) {\n const resolve = this.running.get(sessionId)?.confirms.get(callId)\n if (!resolve) throw new MushinError('not_found', 'No action is waiting for approval')\n resolve(approved)\n return { ok: true }\n }\n\n cancel(sessionId: string) {\n const running = this.running.get(sessionId)\n if (!running) return { ok: false }\n running.abort.abort()\n return { ok: true }\n }\n\n status() {\n return { ready: this.home.llm.isReady(), providers: this.home.llm.list().length, running: [...this.running.keys()] }\n }\n\n private *defineActions() {\n const actions = this.home.actions\n\n yield actions.define({\n name: 'agent.status',\n description: 'Whether the Agent can run (a provider exists and passed its test).',\n risk: 'read',\n input: z.object({}),\n handler: () => this.status(),\n })\n\n yield actions.define({\n name: 'agent.sessions',\n description: 'List Agent conversations, newest first.',\n risk: 'read',\n input: z.object({}),\n handler: () => this.sessions(),\n })\n\n yield actions.define({\n name: 'agent.session',\n description: 'Get one Agent conversation with its messages.',\n risk: 'read',\n input: z.object({ id: z.string() }),\n handler: async ({ id }) => {\n const { tools, ...session } = await this.session(id)\n const now = new Set((await this.tools()).map((tool) => tool.name))\n const toolsStale = tools.length !== now.size || tools.some((tool) => !now.has(tool.name))\n return { ...session, messages: session.messages.map(({ raw, ...message }: any) => message), running: this.running.has(id), toolsStale }\n },\n })\n\n yield actions.define({\n name: 'agent.send',\n description: 'Send a message to the Agent. Omit session to start a new conversation. Progress streams over the WebSocket.',\n risk: 'write',\n input: z.object({\n session: z.string().optional(),\n text: z.string(),\n page: z.string().optional(),\n scene: z.object({\n key: z.string(),\n label: z.string().max(200).optional(),\n hint: z.string().max(1000).optional(),\n state: z.record(z.string(), z.union([z.string().max(200), z.number(), z.boolean()])).optional(),\n resource: z.string().max(200).optional(),\n }).optional().describe('The dashboard page as the dashboard describes it'),\n skills: z.array(z.string()).max(5).optional().describe('Skill ids to apply to this message'),\n quote: z.object({\n bot: z.string(),\n channel: z.string().describe('The chat\\'s id'),\n id: z.string().describe('The quoted message\\'s record id, from bots.messages'),\n before: z.number().int().min(0).max(30).optional(),\n after: z.number().int().min(0).max(10).optional(),\n }).optional().describe('A message of a bot\\'s chat to quote, with a few messages around it'),\n }).refine((input) => input.text.trim() || input.skills?.length, 'Send some text or pick a skill'),\n handler: ({ session, text, ...options }, caller) => this.send(session, text, { client: caller.client, ...options }),\n })\n\n yield actions.define({\n name: 'agent.search',\n description: 'Search Agent conversations by text and tags (scene:<page kind>, skill:<id>, command:<name>, resource:<kind>:<id>, status:running).',\n risk: 'read',\n input: z.object({ query: z.string().optional(), tags: z.array(z.string()).optional(), limit: z.number().int().min(1).max(200).optional() }),\n handler: (input) => this.search(input),\n })\n\n yield actions.define({\n name: 'agent.commands',\n description: 'Commands for the Agent\\'s \"/\" picker: its own (new, history, …) and every bot\\'s commands.',\n risk: 'read',\n input: z.object({}),\n handler: () => this.commands(),\n })\n\n yield actions.define({\n name: 'agent.skills.list',\n description: 'List the Agent\\'s skills: built in, from plugins, and written by the user.',\n risk: 'read',\n input: z.object({}),\n handler: () => this.skills(),\n })\n\n yield actions.define({\n name: 'agent.skills.get',\n description: 'Get one Agent skill with its instructions.',\n risk: 'read',\n input: z.object({ id: z.string() }),\n handler: ({ id }) => this.skill(id),\n })\n\n const skillId = z.string().regex(/^[a-z0-9][a-z0-9-]{0,63}$/).describe('Lowercase letters, digits and dashes')\n\n yield actions.define({\n name: 'agent.skills.create',\n description: 'Create a user skill. Omit id to make one from the name.',\n risk: 'write',\n input: skillInput.extend({ id: skillId.optional() }),\n handler: (input) => this.createSkill(input),\n })\n\n yield actions.define({\n name: 'agent.skills.update',\n description: 'Change a skill. Changing a built-in or plugin skill saves your own copy that replaces it until deleted.',\n risk: 'write',\n input: z.object({\n id: z.string(),\n name: skillFields.name.optional(),\n description: z.string().trim().max(300).optional(),\n instructions: skillFields.instructions.optional(),\n whenToUse: skillFields.whenToUse,\n tools: skillFields.tools,\n scenes: skillFields.scenes,\n }),\n handler: ({ id, ...patch }) => this.updateSkill(id, patch),\n })\n\n yield actions.define({\n name: 'agent.skills.delete',\n description: 'Delete a user skill. A built-in or plugin skill it replaced comes back.',\n risk: 'write',\n input: z.object({ id: z.string() }),\n handler: ({ id }) => this.deleteSkill(id),\n })\n\n yield actions.define({\n name: 'agent.skills.setEnabled',\n description: 'Turn a skill on or off; off skills are not offered with $.',\n risk: 'write',\n input: z.object({ id: z.string(), enabled: z.boolean() }),\n handler: ({ id, enabled }) => this.setSkillEnabled(id, enabled),\n })\n\n yield actions.define({\n name: 'agent.skills.import',\n description: 'Import a skill from a SKILL.md file (YAML frontmatter with name and description, then Markdown instructions), as used by Claude and Codex skills.',\n risk: 'write',\n input: z.object({ markdown: z.string().min(1).max(40_000), replace: z.boolean().optional().describe('Overwrite a skill with the same id') }),\n handler: async ({ markdown, replace }) => {\n let parsed: ReturnType<typeof parseSkillMarkdown>\n try {\n parsed = parseSkillMarkdown(markdown)\n } catch (error) {\n throw new MushinError('invalid_input', error instanceof Error ? error.message : String(error))\n }\n const input = skillInput.extend({ id: skillId.optional() }).parse(parsed)\n if (replace && input.id) return this.saveSkill({ ...input, id: input.id })\n return this.createSkill(input)\n },\n })\n\n yield actions.define({\n name: 'agent.skills.export',\n description: 'A skill as a SKILL.md file.',\n risk: 'read',\n input: z.object({ id: z.string() }),\n handler: async ({ id }) => ({ fileName: 'SKILL.md', markdown: formatSkillMarkdown(await this.skill(id)) }),\n })\n\n yield actions.define({\n name: 'agent.profiles.list',\n description: 'What the Agent says and offers on each dashboard page, as the user changed it: hint, welcome line, own suggestions, hidden built-in suggestions, recommended skills.',\n risk: 'read',\n input: z.object({}),\n handler: async () => ({ scenes: SCENE_KEYS, profiles: await this.profiles() }),\n })\n\n yield actions.define({\n name: 'agent.profiles.update',\n description: 'Change what the Agent says and offers on one dashboard page. Send the whole profile; null goes back to the defaults.',\n risk: 'write',\n input: z.object({ scene: z.enum(SCENE_KEYS), profile: profileInput.nullable() }),\n handler: ({ scene, profile }) => this.setProfile(scene, profile),\n })\n\n yield actions.define({\n name: 'agent.policy.list',\n description: 'Every tool the Agent can use, with its plugin, risk and policy: auto (runs), confirm (asks the user first) or off (not offered).',\n risk: 'read',\n input: z.object({}),\n handler: () => this.policies(),\n })\n\n yield actions.define({\n name: 'agent.policy.set',\n description: 'Set the policy of tools by action name: auto, confirm, or off; null goes back to the default (dangerous actions ask, others run). Off tools leave new conversations only.',\n risk: 'dangerous',\n input: z.object({ policies: z.record(z.string(), policyInput.nullable()) }),\n handler: ({ policies }) => this.setPolicy(policies),\n })\n\n yield actions.define({\n name: 'agent.usage',\n description: 'Tokens the Agent used today and its daily budget (0 means no limit).',\n risk: 'read',\n input: z.object({}),\n handler: () => this.usage(),\n })\n\n yield actions.define({\n name: 'agent.confirm',\n description: 'Approve or decline an action the Agent is waiting on.',\n risk: 'write',\n input: z.object({ session: z.string(), id: z.string(), approved: z.boolean() }),\n handler: ({ session, id, approved }) => this.confirm(session, id, approved),\n })\n\n yield actions.define({\n name: 'agent.cancel',\n description: 'Stop the Agent\\'s current reply in a conversation.',\n risk: 'write',\n input: z.object({ session: z.string() }),\n handler: ({ session }) => this.cancel(session),\n })\n\n yield actions.define({\n name: 'agent.deleteSession',\n description: 'Delete an Agent conversation.',\n risk: 'write',\n input: z.object({ id: z.string() }),\n handler: ({ id }) => this.deleteSession(id),\n })\n }\n}\n\nfunction describeTool(action: ActionInfo) {\n const notes: string[] = []\n if (action.risk === 'dangerous') notes.push('Dangerous: the user must approve it.')\n if (action.client) notes.push('Runs in the user\\'s dashboard; fails if none is connected.')\n return [action.description, ...notes].join(' ')\n}\n\n/** Search tags for one message: its scene, skills, a leading command, and the page's resource. */\n/** A quoted chat as the model reads it; the picked message is marked, with its record id for samples. */\nfunction quoteBlock(quote: QuotedChat) {\n const where = quote.channel.type === 'group' ? `group ${quote.channel.name ? `${quote.channel.name} ` : ''}(${quote.channel.id})` : `private chat with ${quote.channel.id}`\n const lines = quote.lines.map((line) => {\n const time = new Date(line.at).toISOString().slice(11, 16)\n const who = line.direction === 'out' ? `${quote.botName} (bot)` : `${line.user} (${line.userId})`\n return `${line.id === quote.focus ? '→ ' : ' '}[${time}] ${who}: ${line.text}`\n })\n return [\n `<quote bot=\"${quote.bot}\" chat=\"${quote.channel.id}\" message=\"${quote.focus}\">`,\n `Messages from ${quote.botName} in the ${where}; the user picked the one marked →. To build or check a flow for it, pass sample { bot: \"${quote.bot}\", id: \"${quote.focus}\", channel: \"${quote.channel.id}\" } to flows.test or flows.preview.`,\n ...lines,\n '</quote>',\n ].join('\\n')\n}\n\nfunction turnTags(text: string, options: SendOptions, skills: AgentSkill[]) {\n const tags: string[] = []\n if (options.scene) tags.push(`scene:${options.scene.key}`)\n if (options.scene?.resource) tags.push(`resource:${options.scene.resource}`)\n for (const skill of skills) tags.push(`skill:${skill.id}`)\n const command = /^\\s*\\/([\\p{L}\\p{N}_-]+)/u.exec(text)\n if (command) tags.push(`command:${command[1]}`)\n return tags\n}\n\nfunction stripMeta(message: AgentMessage): LlmMessage {\n const { display, skills, quote, at, ...rest } = message\n return rest as LlmMessage\n}\n\nfunction truncate(text: string) {\n if (text.length <= MAX_RESULT_CHARS) return text\n return `${text.slice(0, MAX_RESULT_CHARS)}… [truncated ${text.length - MAX_RESULT_CHARS} characters; ask for less, e.g. with a filter or limit]`\n}\n\nexport default Agent\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"settings.js","names":[],"sources":["../src/settings.ts"],"sourcesContent":["import { type Risk, z } from '@mushinjs/core'\r\nimport type { AgentSkill } from './skills'\r\n\r\n/** Whether the Agent runs a tool on its own, asks first, or never sees it. */\r\nexport type ToolPolicy = 'auto' | 'confirm' | 'off'\r\n\r\n/** The default for a risk level: dangerous actions ask first, the rest run. */\r\nexport function defaultPolicy(risk: Risk): ToolPolicy {\r\n return risk === 'dangerous' ? 'confirm' : 'auto'\r\n}\r\n\r\n/** A suggestion the user adds to a page. */\r\nexport interface CustomRecommendation {\r\n text: string\r\n /** What is sent when it is clicked; the text when empty. */\r\n prompt?: string\r\n skill?: string\r\n}\r\n\r\n/** What the Agent says and offers on one dashboard page; empty fields keep the dashboard's defaults. */\r\nexport interface SceneProfile {\r\n /** Replaces the page's hint, which goes into the <context> block. */\r\n hint?: string\r\n /** Replaces the welcome line of an empty conversation. */\r\n welcome?: string\r\n /** Shown before the built-in suggestions. */\r\n recommendations?: CustomRecommendation[]\r\n /** Ids of built-in suggestions to hide. */\r\n hidden?: string[]\r\n /** Skill ids recommended on this page, besides the skills' own scenes. */\r\n skills?: string[]\r\n /** Show urgent suggestions above the input while a conversation is open. On unless false. */\r\n autoShow?: boolean\r\n}\r\n\r\nexport interface AgentSettings {\r\n profiles: Record<string, SceneProfile>\r\n /** Overrides of the default policy, by action name. */\r\n toolPolicy: Record<string, ToolPolicy>\r\n /** Built-in and plugin skills the user turned off. */\r\n disabledSkills: string[]\r\n}\r\n\r\nexport const SCENE_KEYS = ['overview', 'setup', 'providers', 'bots', 'botDetail', 'flows', 'flowEditor', 'personas', 'knowledge', 'database', 'plugins', 'logs', 'settings', 'agent'] as const\r\n\r\nexport const profileInput = z.object({\r\n hint: z.string().max(1000).optional(),\r\n welcome: z.string().max(500).optional(),\r\n recommendations: z.array(z.object({\r\n text: z.string().trim().min(1).max(200),\r\n prompt: z.string().max(2000).optional(),\r\n skill: z.string().optional(),\r\n })).max(10).optional(),\r\n hidden: z.array(z.string()).max(30).optional(),\r\n skills: z.array(z.string()).max(20).optional(),\r\n autoShow: z.boolean().optional(),\r\n})\r\n\r\nexport const policyInput = z.enum(['auto', 'confirm', 'off'])\r\n\r\n/** Token use of one day, for the daily budget. */\r\nexport interface TokenUsage {\r\n day: string\r\n input: number\r\n output: number\r\n}\r\n\r\nexport function today() {\r\n const now = new Date()\r\n return `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}`\r\n}\r\n\r\n// ---- SKILL.md ----\r\n\r\nfunction unquote(value: string) {\r\n const text = value.trim()\r\n if ((text.startsWith('\"') && text.endsWith('\"')) || (text.startsWith('\\'') && text.endsWith('\\''))) return text.slice(1, -1)\r\n return text\r\n}\r\n\r\nfunction listValue(value: string) {\r\n const text = value.trim()\r\n if (text.startsWith('[') && text.endsWith(']')) return text.slice(1, -1).split(',').map(unquote).filter(Boolean)\r\n return text.split(/[,\\s]+/).map(unquote).filter(Boolean)\r\n}\r\n\r\n/**\r\n * Reads a skill in the `SKILL.md` format of Claude and Codex skills: YAML frontmatter with `name`\r\n * and `description`, then the instructions in Markdown. Only flat keys and simple lists are read.\r\n */\r\nexport function parseSkillMarkdown(source: string) {\r\n const text = source.replace(/^/, '').replace(/\\r\\n/g, '\\n')\r\n const match = /^---\\n([\\s\\S]*?)\\n---\\n?([\\s\\S]*)$/.exec(text)\r\n const meta: Record<string, string | string[]> = {}\r\n let body = text\r\n if (match) {\r\n body = match[2]\r\n let listKey: string | undefined\r\n let folded: string | undefined\r\n for (const line of match[1].split('\\n')) {\r\n const item = /^\\s+-\\s+(.*)$/.exec(line)\r\n if (item && listKey) {\r\n ;(meta[listKey] as string[]).push(unquote(item[1]))\r\n continue\r\n }\r\n if (folded && /^\\s+\\S/.test(line)) {\r\n meta[folded] = `${meta[folded] ? `${meta[folded]} ` : ''}${line.trim()}`\r\n continue\r\n }\r\n listKey = folded = undefined\r\n const pair = /^([A-Za-z][\\w-]*):\\s*(.*)$/.exec(line)\r\n if (!pair) continue\r\n const [, key, value] = pair\r\n if (!value.trim()) {\r\n meta[key] = []\r\n listKey = key\r\n } else if (/^[>|][-+]?$/.test(value.trim())) {\r\n meta[key] = ''\r\n folded = key\r\n } else {\r\n meta[key] = value\r\n }\r\n }\r\n }\r\n const str = (key: string) => {\r\n const value = meta[key]\r\n return typeof value === 'string' ? unquote(value) : undefined\r\n }\r\n const list = (key: string) => {\r\n const value = meta[key]\r\n if (value === undefined) return undefined\r\n return Array.isArray(value) ? value : listValue(value)\r\n }\r\n const heading = /^#\\s+(.+)$/m.exec(body)?.[1]?.trim()\r\n const name = str('name') ?? heading\r\n if (!name) throw new Error('The skill has no name: add \"name:\" to the frontmatter or start with a \"# Title\"')\r\n return {\r\n ...(str('id') ? { id: str('id') } : {}),\r\n name,\r\n description: str('description') ?? '',\r\n instructions: body.trim(),\r\n ...(str('when_to_use') ?? str('whenToUse') ? { whenToUse: str('when_to_use') ?? str('whenToUse') } : {}),\r\n ...(list('tools') ?? list('allowed-tools') ? { tools: list('tools') ?? list('allowed-tools') } : {}),\r\n ...(list('scenes') ? { scenes: list('scenes') } : {}),\r\n }\r\n}\r\n\r\nconst yamlString = (value: string) => (/^[\\w\\s一-鿿,.()()、,。-]*$/.test(value) && value.trim() === value ? value : JSON.stringify(value))\r\n\r\n/** Writes a skill as a `SKILL.md` file. */\r\nexport function formatSkillMarkdown(skill: Pick<AgentSkill, 'id' | 'name' | 'description' | 'instructions' | 'whenToUse' | 'tools' | 'scenes'>) {\r\n const lines = ['---', `name: ${yamlString(skill.name)}`, `description: ${yamlString(skill.description)}`]\r\n if (skill.whenToUse) lines.push(`when_to_use: ${yamlString(skill.whenToUse)}`)\r\n if (skill.tools?.length) lines.push(`tools: [${skill.tools.join(', ')}]`)\r\n if (skill.scenes?.length) lines.push(`scenes: [${skill.scenes.join(', ')}]`)\r\n lines.push(`id: ${skill.id}`, '---', '', skill.instructions.trim(), '')\r\n return lines.join('\\n')\r\n}\r\n"],"mappings":"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"}
1
+ {"version":3,"file":"settings.js","names":[],"sources":["../src/settings.ts"],"sourcesContent":["import { type Risk, z } from '@mushinjs/core'\nimport type { AgentSkill } from './skills'\n\n/** Whether the Agent runs a tool on its own, asks first, or never sees it. */\nexport type ToolPolicy = 'auto' | 'confirm' | 'off'\n\n/** The default for a risk level: dangerous actions ask first, the rest run. */\nexport function defaultPolicy(risk: Risk): ToolPolicy {\n return risk === 'dangerous' ? 'confirm' : 'auto'\n}\n\n/** A suggestion the user adds to a page. */\nexport interface CustomRecommendation {\n text: string\n /** What is sent when it is clicked; the text when empty. */\n prompt?: string\n skill?: string\n}\n\n/** What the Agent says and offers on one dashboard page; empty fields keep the dashboard's defaults. */\nexport interface SceneProfile {\n /** Replaces the page's hint, which goes into the <context> block. */\n hint?: string\n /** Replaces the welcome line of an empty conversation. */\n welcome?: string\n /** Shown before the built-in suggestions. */\n recommendations?: CustomRecommendation[]\n /** Ids of built-in suggestions to hide. */\n hidden?: string[]\n /** Skill ids recommended on this page, besides the skills' own scenes. */\n skills?: string[]\n /** Show urgent suggestions above the input while a conversation is open. On unless false. */\n autoShow?: boolean\n}\n\nexport interface AgentSettings {\n profiles: Record<string, SceneProfile>\n /** Overrides of the default policy, by action name. */\n toolPolicy: Record<string, ToolPolicy>\n /** Built-in and plugin skills the user turned off. */\n disabledSkills: string[]\n}\n\nexport const SCENE_KEYS = ['overview', 'setup', 'providers', 'bots', 'botDetail', 'flows', 'flowEditor', 'personas', 'knowledge', 'database', 'plugins', 'logs', 'settings', 'agent'] as const\n\nexport const profileInput = z.object({\n hint: z.string().max(1000).optional(),\n welcome: z.string().max(500).optional(),\n recommendations: z.array(z.object({\n text: z.string().trim().min(1).max(200),\n prompt: z.string().max(2000).optional(),\n skill: z.string().optional(),\n })).max(10).optional(),\n hidden: z.array(z.string()).max(30).optional(),\n skills: z.array(z.string()).max(20).optional(),\n autoShow: z.boolean().optional(),\n})\n\nexport const policyInput = z.enum(['auto', 'confirm', 'off'])\n\n/** Token use of one day, for the daily budget. */\nexport interface TokenUsage {\n day: string\n input: number\n output: number\n}\n\nexport function today() {\n const now = new Date()\n return `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}`\n}\n\n// ---- SKILL.md ----\n\nfunction unquote(value: string) {\n const text = value.trim()\n if ((text.startsWith('\"') && text.endsWith('\"')) || (text.startsWith('\\'') && text.endsWith('\\''))) return text.slice(1, -1)\n return text\n}\n\nfunction listValue(value: string) {\n const text = value.trim()\n if (text.startsWith('[') && text.endsWith(']')) return text.slice(1, -1).split(',').map(unquote).filter(Boolean)\n return text.split(/[,\\s]+/).map(unquote).filter(Boolean)\n}\n\n/**\n * Reads a skill in the `SKILL.md` format of Claude and Codex skills: YAML frontmatter with `name`\n * and `description`, then the instructions in Markdown. Only flat keys and simple lists are read.\n */\nexport function parseSkillMarkdown(source: string) {\n const text = source.replace(/^/, '').replace(/\\r\\n/g, '\\n')\n const match = /^---\\n([\\s\\S]*?)\\n---\\n?([\\s\\S]*)$/.exec(text)\n const meta: Record<string, string | string[]> = {}\n let body = text\n if (match) {\n body = match[2]\n let listKey: string | undefined\n let folded: string | undefined\n for (const line of match[1].split('\\n')) {\n const item = /^\\s+-\\s+(.*)$/.exec(line)\n if (item && listKey) {\n ;(meta[listKey] as string[]).push(unquote(item[1]))\n continue\n }\n if (folded && /^\\s+\\S/.test(line)) {\n meta[folded] = `${meta[folded] ? `${meta[folded]} ` : ''}${line.trim()}`\n continue\n }\n listKey = folded = undefined\n const pair = /^([A-Za-z][\\w-]*):\\s*(.*)$/.exec(line)\n if (!pair) continue\n const [, key, value] = pair\n if (!value.trim()) {\n meta[key] = []\n listKey = key\n } else if (/^[>|][-+]?$/.test(value.trim())) {\n meta[key] = ''\n folded = key\n } else {\n meta[key] = value\n }\n }\n }\n const str = (key: string) => {\n const value = meta[key]\n return typeof value === 'string' ? unquote(value) : undefined\n }\n const list = (key: string) => {\n const value = meta[key]\n if (value === undefined) return undefined\n return Array.isArray(value) ? value : listValue(value)\n }\n const heading = /^#\\s+(.+)$/m.exec(body)?.[1]?.trim()\n const name = str('name') ?? heading\n if (!name) throw new Error('The skill has no name: add \"name:\" to the frontmatter or start with a \"# Title\"')\n return {\n ...(str('id') ? { id: str('id') } : {}),\n name,\n description: str('description') ?? '',\n instructions: body.trim(),\n ...(str('when_to_use') ?? str('whenToUse') ? { whenToUse: str('when_to_use') ?? str('whenToUse') } : {}),\n ...(list('tools') ?? list('allowed-tools') ? { tools: list('tools') ?? list('allowed-tools') } : {}),\n ...(list('scenes') ? { scenes: list('scenes') } : {}),\n }\n}\n\nconst yamlString = (value: string) => (/^[\\w\\s一-鿿,.()()、,。-]*$/.test(value) && value.trim() === value ? value : JSON.stringify(value))\n\n/** Writes a skill as a `SKILL.md` file. */\nexport function formatSkillMarkdown(skill: Pick<AgentSkill, 'id' | 'name' | 'description' | 'instructions' | 'whenToUse' | 'tools' | 'scenes'>) {\n const lines = ['---', `name: ${yamlString(skill.name)}`, `description: ${yamlString(skill.description)}`]\n if (skill.whenToUse) lines.push(`when_to_use: ${yamlString(skill.whenToUse)}`)\n if (skill.tools?.length) lines.push(`tools: [${skill.tools.join(', ')}]`)\n if (skill.scenes?.length) lines.push(`scenes: [${skill.scenes.join(', ')}]`)\n lines.push(`id: ${skill.id}`, '---', '', skill.instructions.trim(), '')\n return lines.join('\\n')\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"skills.js","names":[],"sources":["../src/skills.ts"],"sourcesContent":["import { z } from '@mushinjs/core'\r\n\r\n/** Where a skill comes from: shipped with the Agent, added by a plugin, or written by the user. */\r\nexport type SkillSource = 'builtin' | 'plugin' | 'user'\r\n\r\n/** A reusable way of doing something; picked with `$`, its instructions go into that one message. */\r\nexport interface AgentSkill {\r\n id: string\r\n name: string\r\n /** One line: what it is for. */\r\n description: string\r\n /** The steps, in Markdown. */\r\n instructions: string\r\n /** When to use it, for people picking one. */\r\n whenToUse?: string\r\n /** Actions it tends to use, e.g. `bots.logs`. */\r\n tools?: string[]\r\n /** Scene keys where it is recommended, e.g. `botDetail`. */\r\n scenes?: string[]\r\n source: SkillSource\r\n /** The plugin that added it. */\r\n plugin?: string\r\n /** Off: not offered with `$`. */\r\n enabled: boolean\r\n}\r\n\r\n/** What a plugin passes to `ctx.agent.defineSkill()`. */\r\nexport type SkillDefinition = Omit<AgentSkill, 'source' | 'plugin' | 'enabled'>\r\n\r\nexport const skillFields = {\r\n name: z.string().trim().min(1).max(80),\r\n description: z.string().trim().max(300).default(''),\r\n instructions: z.string().min(1).max(20_000).describe('The steps, in Markdown'),\r\n whenToUse: z.string().max(500).optional(),\r\n tools: z.array(z.string()).max(30).optional().describe('Action names it tends to use, e.g. bots.logs'),\r\n scenes: z.array(z.string()).max(20).optional().describe('Scene keys where it is recommended: overview, bots, botDetail, providers, flows, flowEditor, plugins, logs, personas, knowledge, settings, agent'),\r\n}\r\n\r\nexport const skillInput = z.object(skillFields)\r\n\r\n/** Skills that ship with the Agent. */\r\nexport const BUILTIN_SKILLS: SkillDefinition[] = [\r\n {\r\n id: 'diagnose-bot',\r\n name: '排查机器人连接',\r\n description: '机器人离线、连不上 NapCat 或不回复时,按步骤找出原因',\r\n whenToUse: '机器人状态不是在线,或者在线但不回复消息',\r\n instructions: [\r\n '1. 用 bots.list 找到这个机器人,记下状态和错误信息。',\r\n '2. 用 bots.logs 读它最近的日志:连接地址、NapCat 的 self id、令牌是否被拒绝、登录记录。',\r\n '3. 根据日志判断:地址或端口不对、NapCat 没开 WebSocket、令牌不一致、消息格式不是 array、反向连接地址不对。',\r\n '4. 在线但不回复时,用 bots.plugins.list 看插件是否启用,用 flows.route 看一条消息会被谁处理。',\r\n '5. 给出最可能的原因和具体修改步骤;能直接改的配置(地址、令牌)先说明再改,改完用 bots.get 确认状态。',\r\n ].join('\\n'),\r\n tools: ['bots.list', 'bots.logs', 'bots.get', 'bots.plugins.list', 'flows.route'],\r\n scenes: ['bots', 'botDetail'],\r\n },\r\n {\r\n id: 'build-flow',\r\n name: '搭建流程',\r\n description: '把一段描述变成可运行的对话流程,并测试通过',\r\n whenToUse: '想让机器人在某种消息下做某件事',\r\n instructions: [\r\n '1. 先问清楚(或从描述中确定):什么消息触发、要回复什么、用在哪个机器人上。',\r\n '2. 用 flows.nodeTypes 看全部节点类型的一行简介,选出触发器和动作节点(需要计数、冷却、限额时用对应的逻辑节点),再把选中的类型传给 flows.nodeTypes 的 types 读配置和端口。只用列表里有的类型名,不要猜。',\r\n '3. 用 flows.create 创建流程并绑定机器人,节点之间用 exec 连线,值用 {{节点.输出}} 引用。',\r\n '4. 用 flows.test 发几条样例消息(包括不该触发的),检查路径和回复;有问题就用 flows.update 修正后再测。',\r\n '5. 用 ui.navigate 打开 /flows/<id>,简要说明流程怎么工作。',\r\n ].join('\\n'),\r\n tools: ['flows.nodeTypes', 'flows.create', 'flows.test', 'flows.update', 'ui.navigate'],\r\n scenes: ['flows', 'flowEditor'],\r\n },\r\n {\r\n id: 'flow-from-chat',\r\n name: '根据会话创建流程',\r\n description: '从引用的会话消息出发,搭建并用真实消息验证一个流程',\r\n whenToUse: '在会话里引用了一条消息,想让机器人对这类消息做出回应',\r\n instructions: [\r\n '1. 读消息里的 <quote>:被 → 标出的是用户选中的消息,记下机器人、会话和消息 id。',\r\n '2. 用 flows.history(带 message)看这条消息已经触发了哪些流程;用 flows.route 看现在发同样内容会被谁处理。',\r\n '3. 和用户确认想要的效果(触发方式、回复内容、谁能用);能从引用的会话推断的不必再问。',\r\n '4. 用 flows.nodeTypes 选节点(不带参数看列表,再用 types 读选中节点的配置),用 flows.create 创建流程并绑定到这个机器人。',\r\n '5. 用 flows.test 带上 sample(引用里给出的 bot、id、channel)验证真实消息能走通;有 AI 节点时用 flows.preview 检查发给模型的内容。再用一两条不该触发的消息测试。',\r\n '6. 用 ui.navigate 打开 /flows/<id>?sample=<bot>:<channel>:<id>,让用户直接看到样本下的效果。',\r\n ].join('\\n'),\r\n tools: ['flows.history', 'flows.route', 'flows.nodeTypes', 'flows.create', 'flows.update', 'flows.test', 'flows.preview', 'ui.navigate'],\r\n scenes: ['botDetail', 'flows', 'flowEditor'],\r\n },\r\n {\r\n id: 'fix-flow',\r\n name: '修复流程问题',\r\n description: '读出流程的校验问题,逐个修好并重新测试',\r\n whenToUse: '流程编辑器里有错误或警告',\r\n instructions: [\r\n '1. 用 flows.get 读当前流程(上下文里有它的 id)和它的 issues。',\r\n '2. 逐条说明每个问题的原因:缺少节点类型时说明要启用哪个插件;引用不存在的输出时找到正确的节点 id;被其他触发器挡住时用 flows.triggers 看顺序。',\r\n '3. 能修的用 flows.update 修,修改前简要说明要改什么。',\r\n '4. 用 flows.test 验证,然后总结改了什么。',\r\n ].join('\\n'),\r\n tools: ['flows.get', 'flows.update', 'flows.test', 'flows.triggers'],\r\n scenes: ['flowEditor'],\r\n },\r\n {\r\n id: 'connect-provider',\r\n name: '连接模型提供商',\r\n description: '添加一个大模型提供商并测试通过',\r\n whenToUse: '还没有提供商,或者想换一个模型服务',\r\n instructions: [\r\n '1. 问用户要用哪家服务(DeepSeek、通义千问、Moonshot、OpenAI、Anthropic、本地 Ollama)和 API 密钥;本地 Ollama 不需要密钥。',\r\n '2. 用 providers.types 读配置格式,用 providers.create 创建,填好接口地址和模型。',\r\n '3. 用 providers.test 测试;失败时根据错误说明原因(密钥、地址、模型名、网络)。',\r\n '4. 成功后告诉用户延迟,并询问是否设为默认。',\r\n ].join('\\n'),\r\n tools: ['providers.types', 'providers.create', 'providers.test', 'providers.setDefault'],\r\n scenes: ['providers', 'setup'],\r\n },\r\n]\r\n"],"mappings":";;AA6BA,MAAa,cAAc;CACzB,MAAM,EAAE,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE;CACrC,aAAa,EAAE,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,QAAQ,EAAE;CAClD,cAAc,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,GAAM,CAAC,CAAC,SAAS,wBAAwB;CAC7E,WAAW,EAAE,OAAO,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,SAAS;CACxC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS,8CAA8C;CACrG,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS,kJAAkJ;AAC5M;AAEA,MAAa,aAAa,EAAE,OAAO,WAAW;;AAG9C,MAAa,iBAAoC;CAC/C;EACE,IAAI;EACJ,MAAM;EACN,aAAa;EACb,WAAW;EACX,cAAc;GACZ;GACA;GACA;GACA;GACA;EACF,CAAC,CAAC,KAAK,IAAI;EACX,OAAO;GAAC;GAAa;GAAa;GAAY;GAAqB;EAAa;EAChF,QAAQ,CAAC,QAAQ,WAAW;CAC9B;CACA;EACE,IAAI;EACJ,MAAM;EACN,aAAa;EACb,WAAW;EACX,cAAc;GACZ;GACA;GACA;GACA;GACA;EACF,CAAC,CAAC,KAAK,IAAI;EACX,OAAO;GAAC;GAAmB;GAAgB;GAAc;GAAgB;EAAa;EACtF,QAAQ,CAAC,SAAS,YAAY;CAChC;CACA;EACE,IAAI;EACJ,MAAM;EACN,aAAa;EACb,WAAW;EACX,cAAc;GACZ;GACA;GACA;GACA;GACA;GACA;EACF,CAAC,CAAC,KAAK,IAAI;EACX,OAAO;GAAC;GAAiB;GAAe;GAAmB;GAAgB;GAAgB;GAAc;GAAiB;EAAa;EACvI,QAAQ;GAAC;GAAa;GAAS;EAAY;CAC7C;CACA;EACE,IAAI;EACJ,MAAM;EACN,aAAa;EACb,WAAW;EACX,cAAc;GACZ;GACA;GACA;GACA;EACF,CAAC,CAAC,KAAK,IAAI;EACX,OAAO;GAAC;GAAa;GAAgB;GAAc;EAAgB;EACnE,QAAQ,CAAC,YAAY;CACvB;CACA;EACE,IAAI;EACJ,MAAM;EACN,aAAa;EACb,WAAW;EACX,cAAc;GACZ;GACA;GACA;GACA;EACF,CAAC,CAAC,KAAK,IAAI;EACX,OAAO;GAAC;GAAmB;GAAoB;GAAkB;EAAsB;EACvF,QAAQ,CAAC,aAAa,OAAO;CAC/B;AACF"}
1
+ {"version":3,"file":"skills.js","names":[],"sources":["../src/skills.ts"],"sourcesContent":["import { z } from '@mushinjs/core'\n\n/** Where a skill comes from: shipped with the Agent, added by a plugin, or written by the user. */\nexport type SkillSource = 'builtin' | 'plugin' | 'user'\n\n/** A reusable way of doing something; picked with `$`, its instructions go into that one message. */\nexport interface AgentSkill {\n id: string\n name: string\n /** One line: what it is for. */\n description: string\n /** The steps, in Markdown. */\n instructions: string\n /** When to use it, for people picking one. */\n whenToUse?: string\n /** Actions it tends to use, e.g. `bots.logs`. */\n tools?: string[]\n /** Scene keys where it is recommended, e.g. `botDetail`. */\n scenes?: string[]\n source: SkillSource\n /** The plugin that added it. */\n plugin?: string\n /** Off: not offered with `$`. */\n enabled: boolean\n}\n\n/** What a plugin passes to `ctx.agent.defineSkill()`. */\nexport type SkillDefinition = Omit<AgentSkill, 'source' | 'plugin' | 'enabled'>\n\nexport const skillFields = {\n name: z.string().trim().min(1).max(80),\n description: z.string().trim().max(300).default(''),\n instructions: z.string().min(1).max(20_000).describe('The steps, in Markdown'),\n whenToUse: z.string().max(500).optional(),\n tools: z.array(z.string()).max(30).optional().describe('Action names it tends to use, e.g. bots.logs'),\n scenes: z.array(z.string()).max(20).optional().describe('Scene keys where it is recommended: overview, bots, botDetail, providers, flows, flowEditor, plugins, logs, personas, knowledge, settings, agent'),\n}\n\nexport const skillInput = z.object(skillFields)\n\n/** Skills that ship with the Agent. */\nexport const BUILTIN_SKILLS: SkillDefinition[] = [\n {\n id: 'diagnose-bot',\n name: '排查机器人连接',\n description: '机器人离线、连不上 NapCat 或不回复时,按步骤找出原因',\n whenToUse: '机器人状态不是在线,或者在线但不回复消息',\n instructions: [\n '1. 用 bots.list 找到这个机器人,记下状态和错误信息。',\n '2. 用 bots.logs 读它最近的日志:连接地址、NapCat 的 self id、令牌是否被拒绝、登录记录。',\n '3. 根据日志判断:地址或端口不对、NapCat 没开 WebSocket、令牌不一致、消息格式不是 array、反向连接地址不对。',\n '4. 在线但不回复时,用 bots.plugins.list 看插件是否启用,用 flows.route 看一条消息会被谁处理。',\n '5. 给出最可能的原因和具体修改步骤;能直接改的配置(地址、令牌)先说明再改,改完用 bots.get 确认状态。',\n ].join('\\n'),\n tools: ['bots.list', 'bots.logs', 'bots.get', 'bots.plugins.list', 'flows.route'],\n scenes: ['bots', 'botDetail'],\n },\n {\n id: 'build-flow',\n name: '搭建流程',\n description: '把一段描述变成可运行的对话流程,并测试通过',\n whenToUse: '想让机器人在某种消息下做某件事',\n instructions: [\n '1. 先问清楚(或从描述中确定):什么消息触发、要回复什么、用在哪个机器人上。',\n '2. 用 flows.nodeTypes 看全部节点类型的一行简介,选出触发器和动作节点(需要计数、冷却、限额时用对应的逻辑节点),再把选中的类型传给 flows.nodeTypes 的 types 读配置和端口。只用列表里有的类型名,不要猜。',\n '3. 用 flows.create 创建流程并绑定机器人,节点之间用 exec 连线,值用 {{节点.输出}} 引用。',\n '4. 用 flows.test 发几条样例消息(包括不该触发的),检查路径和回复;有问题就用 flows.update 修正后再测。',\n '5. 用 ui.navigate 打开 /flows/<id>,简要说明流程怎么工作。',\n ].join('\\n'),\n tools: ['flows.nodeTypes', 'flows.create', 'flows.test', 'flows.update', 'ui.navigate'],\n scenes: ['flows', 'flowEditor'],\n },\n {\n id: 'flow-from-chat',\n name: '根据会话创建流程',\n description: '从引用的会话消息出发,搭建并用真实消息验证一个流程',\n whenToUse: '在会话里引用了一条消息,想让机器人对这类消息做出回应',\n instructions: [\n '1. 读消息里的 <quote>:被 → 标出的是用户选中的消息,记下机器人、会话和消息 id。',\n '2. 用 flows.history(带 message)看这条消息已经触发了哪些流程;用 flows.route 看现在发同样内容会被谁处理。',\n '3. 和用户确认想要的效果(触发方式、回复内容、谁能用);能从引用的会话推断的不必再问。',\n '4. 用 flows.nodeTypes 选节点(不带参数看列表,再用 types 读选中节点的配置),用 flows.create 创建流程并绑定到这个机器人。',\n '5. 用 flows.test 带上 sample(引用里给出的 bot、id、channel)验证真实消息能走通;有 AI 节点时用 flows.preview 检查发给模型的内容。再用一两条不该触发的消息测试。',\n '6. 用 ui.navigate 打开 /flows/<id>?sample=<bot>:<channel>:<id>,让用户直接看到样本下的效果。',\n ].join('\\n'),\n tools: ['flows.history', 'flows.route', 'flows.nodeTypes', 'flows.create', 'flows.update', 'flows.test', 'flows.preview', 'ui.navigate'],\n scenes: ['botDetail', 'flows', 'flowEditor'],\n },\n {\n id: 'fix-flow',\n name: '修复流程问题',\n description: '读出流程的校验问题,逐个修好并重新测试',\n whenToUse: '流程编辑器里有错误或警告',\n instructions: [\n '1. 用 flows.get 读当前流程(上下文里有它的 id)和它的 issues。',\n '2. 逐条说明每个问题的原因:缺少节点类型时说明要启用哪个插件;引用不存在的输出时找到正确的节点 id;被其他触发器挡住时用 flows.triggers 看顺序。',\n '3. 能修的用 flows.update 修,修改前简要说明要改什么。',\n '4. 用 flows.test 验证,然后总结改了什么。',\n ].join('\\n'),\n tools: ['flows.get', 'flows.update', 'flows.test', 'flows.triggers'],\n scenes: ['flowEditor'],\n },\n {\n id: 'connect-provider',\n name: '连接模型提供商',\n description: '添加一个大模型提供商并测试通过',\n whenToUse: '还没有提供商,或者想换一个模型服务',\n instructions: [\n '1. 问用户要用哪家服务(DeepSeek、通义千问、Moonshot、OpenAI、Anthropic、本地 Ollama)和 API 密钥;本地 Ollama 不需要密钥。',\n '2. 用 providers.types 读配置格式,用 providers.create 创建,填好接口地址和模型。',\n '3. 用 providers.test 测试;失败时根据错误说明原因(密钥、地址、模型名、网络)。',\n '4. 成功后告诉用户延迟,并询问是否设为默认。',\n ].join('\\n'),\n tools: ['providers.types', 'providers.create', 'providers.test', 'providers.setDefault'],\n scenes: ['providers', 'setup'],\n },\n]\n"],"mappings":";;AA6BA,MAAa,cAAc;CACzB,MAAM,EAAE,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE;CACrC,aAAa,EAAE,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,QAAQ,EAAE;CAClD,cAAc,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,GAAM,CAAC,CAAC,SAAS,wBAAwB;CAC7E,WAAW,EAAE,OAAO,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,SAAS;CACxC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS,8CAA8C;CACrG,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS,kJAAkJ;AAC5M;AAEA,MAAa,aAAa,EAAE,OAAO,WAAW;;AAG9C,MAAa,iBAAoC;CAC/C;EACE,IAAI;EACJ,MAAM;EACN,aAAa;EACb,WAAW;EACX,cAAc;GACZ;GACA;GACA;GACA;GACA;EACF,CAAC,CAAC,KAAK,IAAI;EACX,OAAO;GAAC;GAAa;GAAa;GAAY;GAAqB;EAAa;EAChF,QAAQ,CAAC,QAAQ,WAAW;CAC9B;CACA;EACE,IAAI;EACJ,MAAM;EACN,aAAa;EACb,WAAW;EACX,cAAc;GACZ;GACA;GACA;GACA;GACA;EACF,CAAC,CAAC,KAAK,IAAI;EACX,OAAO;GAAC;GAAmB;GAAgB;GAAc;GAAgB;EAAa;EACtF,QAAQ,CAAC,SAAS,YAAY;CAChC;CACA;EACE,IAAI;EACJ,MAAM;EACN,aAAa;EACb,WAAW;EACX,cAAc;GACZ;GACA;GACA;GACA;GACA;GACA;EACF,CAAC,CAAC,KAAK,IAAI;EACX,OAAO;GAAC;GAAiB;GAAe;GAAmB;GAAgB;GAAgB;GAAc;GAAiB;EAAa;EACvI,QAAQ;GAAC;GAAa;GAAS;EAAY;CAC7C;CACA;EACE,IAAI;EACJ,MAAM;EACN,aAAa;EACb,WAAW;EACX,cAAc;GACZ;GACA;GACA;GACA;EACF,CAAC,CAAC,KAAK,IAAI;EACX,OAAO;GAAC;GAAa;GAAgB;GAAc;EAAgB;EACnE,QAAQ,CAAC,YAAY;CACvB;CACA;EACE,IAAI;EACJ,MAAM;EACN,aAAa;EACb,WAAW;EACX,cAAc;GACZ;GACA;GACA;GACA;EACF,CAAC,CAAC,KAAK,IAAI;EACX,OAAO;GAAC;GAAmB;GAAoB;GAAkB;EAAsB;EACvF,QAAQ,CAAC,aAAa,OAAO;CAC/B;AACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mushinjs/plugin-agent",
3
- "version": "0.2.0-next.20261112165327",
3
+ "version": "0.2.0-next.20261113103537",
4
4
  "description": "The Mushin.js Agent",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -51,8 +51,8 @@
51
51
  }
52
52
  },
53
53
  "dependencies": {
54
- "@mushinjs/core": "0.2.0-next.20261112165327",
55
- "@mushinjs/plugin-storage": "0.2.0-next.20261112165327",
56
- "@mushinjs/plugin-providers": "0.2.0-next.20261112165327"
54
+ "@mushinjs/core": "0.2.0-next.20261113103537",
55
+ "@mushinjs/plugin-storage": "0.2.0-next.20261113103537",
56
+ "@mushinjs/plugin-providers": "0.2.0-next.20261113103537"
57
57
  }
58
58
  }