import path from "path"import fs from "fs/promises"import z from "zod"import { Tool } from "./tool"import { Global } from "@/global"import { OpenScience } from "@/openscience"import { RSILifecycle } from "@/session/rsi/lifecycle"import { Log } from "@/util/log" const log = Log.create({ service: "tool.learn" }) export const LearnTool = Tool.define("learn", { description: "Save a learned skill distilled from conversation analysis. Writes SKILL.md to disk, uploads to cloud, and registers for lifecycle tracking. Called as the final step of /learn analysis.", parameters: z.object({ name: z.string().describe("Skill identifier (kebab-case, e.g. 'debug-oom-pytorch')"), description: z.string().describe("One-line description of what this skill teaches"), content: z.string().describe("Full SKILL.md content including frontmatter"), }), async execute(params, ctx) { const dir = path.join(Global.Path.data, "learned-skills", params.name) const filepath = path.join(dir, "SKILL.md") await fs.mkdir(dir, { recursive: true }) await Bun.write(filepath, params.content) log.info("learned skill written", { name: params.name, path: filepath }) const uploaded = await OpenScience.uploadLearnedSkill(params.name, params.description, params.content, { agent: ctx.agent, score: 0, }).catch(() => false) await RSILifecycle.registerSkill(params.name).catch(() => {}) return { title: `Learned skill: ${params.name}`, output: [ `Learned skill "${params.name}" saved successfully.`, ` Path: ${filepath}`, ` Cloud: ${uploaded ? "uploaded" : "local only (upload failed or no session)"}`, ` Description: ${params.description}`, "", "The skill will be available in future sessions via the skill tool.", ].join("\n"), metadata: { name: params.name, uploaded }, } },})
import path from "path"
import fs from "fs/promises"
import z from "zod"
import { Tool } from "./tool"
import { Global } from "@/global"
import { OpenScience } from "@/openscience"
import { RSILifecycle } from "@/session/rsi/lifecycle"
import { Log } from "@/util/log"
const log = Log.create({ service: "tool.learn" })
export const LearnTool = Tool.define("learn", {
description:
"Save a learned skill distilled from conversation analysis. Writes SKILL.md to disk, uploads to cloud, and registers for lifecycle tracking. Called as the final step of /learn analysis.",
parameters: z.object({
name: z.string().describe("Skill identifier (kebab-case, e.g. 'debug-oom-pytorch')"),
description: z.string().describe("One-line description of what this skill teaches"),
content: z.string().describe("Full SKILL.md content including frontmatter"),
}),
async execute(params, ctx) {
const dir = path.join(Global.Path.data, "learned-skills", params.name)
const filepath = path.join(dir, "SKILL.md")
await fs.mkdir(dir, { recursive: true })
await Bun.write(filepath, params.content)
log.info("learned skill written", { name: params.name, path: filepath })
const uploaded = await OpenScience.uploadLearnedSkill(params.name, params.description, params.content, {
agent: ctx.agent,
score: 0,
}).catch(() => false)
await RSILifecycle.registerSkill(params.name).catch(() => {})
return {
title: `Learned skill: ${params.name}`,
output: [
`Learned skill "${params.name}" saved successfully.`,
` Path: ${filepath}`,
` Cloud: ${uploaded ? "uploaded" : "local only (upload failed or no session)"}`,
` Description: ${params.description}`,
"",
"The skill will be available in future sessions via the skill tool.",
].join("\n"),
metadata: { name: params.name, uploaded },
}
},
})