Files
openagent/.opencode/tool/library-skills.ts
Thomas Marchand 3d0b4d19b7 Th0rgal/update branding (#32)
* feat: chroots

* wip

* Update workspace templates and Playwright tests

* Fix thinking panel close button not working during active thinking

The auto-show useEffect was including showThinkingPanel in its dependency
array, causing the panel to immediately reopen when closed since the state
change would trigger the effect while hasActiveThinking was still true.

Changed to use a ref to track previous state and only auto-show on
transition from inactive to active thinking.

* wip

* wip

* wip

* Cleanup web search tool and remove hardcoded OAuth credentials

* Ralph iteration 1: work in progress

* Ralph iteration 2: work in progress

* Ralph iteration 3: work in progress

* Ralph iteration 4: work in progress

* Ralph iteration 5: work in progress

* Ralph iteration 6: work in progress

* Ralph iteration 1: work in progress

* Ralph iteration 2: work in progress

* Ralph iteration 3: work in progress

* Ralph iteration 4: work in progress

* Ralph iteration 5: work in progress

* Ralph iteration 6: work in progress

* Ralph iteration 7: work in progress

* Ralph iteration 1: work in progress

* Ralph iteration 2: work in progress

* improve readme

* fix: remove unused file

* feat: hero screenshot

* Update README with cleaner vision and hero screenshot

Simplified the vision section with "what if" framing, removed
architecture diagram, added hero screenshot showing mission view.
2026-01-12 14:45:05 -08:00

103 lines
3.6 KiB
TypeScript

import { tool } from "@opencode-ai/plugin"
// The Open Agent API URL - the backend handles library configuration internally
const API_BASE = "http://127.0.0.1:3000"
async function apiRequest(endpoint: string, options: RequestInit = {}) {
const url = `${API_BASE}/api/library${endpoint}`
const response = await fetch(url, {
...options,
headers: {
"Content-Type": "application/json",
...options.headers,
},
})
if (!response.ok) {
const text = await response.text()
throw new Error(`API error ${response.status}: ${text}`)
}
const contentType = response.headers.get("content-type")
if (contentType?.includes("application/json")) {
return response.json()
}
return response.text()
}
// ─────────────────────────────────────────────────────────────────────────────
// Skills
// ─────────────────────────────────────────────────────────────────────────────
export const list_skills = tool({
description: "List all skills in the library with their names and descriptions",
args: {},
async execute() {
const skills = await apiRequest("/skill")
if (!skills || skills.length === 0) {
return "No skills found in the library."
}
return skills.map((s: { name: string; description?: string }) =>
`- ${s.name}: ${s.description || "(no description)"}`
).join("\n")
},
})
export const get_skill = tool({
description: "Get the full content of a skill by name, including SKILL.md and any additional files",
args: {
name: tool.schema.string().describe("The skill name (e.g., 'git-release')"),
},
async execute(args) {
const skill = await apiRequest(`/skill/${encodeURIComponent(args.name)}`)
let result = `# Skill: ${skill.name}\n\n`
result += `**Path:** ${skill.path}\n`
if (skill.description) {
result += `**Description:** ${skill.description}\n`
}
result += `\n## SKILL.md Content\n\n${skill.content}`
if (skill.files && skill.files.length > 0) {
result += "\n\n## Additional Files\n"
for (const file of skill.files) {
result += `\n### ${file.path}\n\n${file.content}`
}
}
if (skill.references && skill.references.length > 0) {
result += "\n\n## Reference Files\n"
result += skill.references.map((r: string) => `- ${r}`).join("\n")
}
return result
},
})
export const save_skill = tool({
description: "Create or update a skill in the library. Provide the full SKILL.md content including YAML frontmatter.",
args: {
name: tool.schema.string().describe("The skill name (lowercase, hyphens allowed, 1-64 chars)"),
content: tool.schema.string().describe("Full SKILL.md content including YAML frontmatter with name and description"),
},
async execute(args) {
await apiRequest(`/skill/${encodeURIComponent(args.name)}`, {
method: "PUT",
body: JSON.stringify({ content: args.content }),
})
return `Skill '${args.name}' saved successfully. Remember to commit and push your changes.`
},
})
export const delete_skill = tool({
description: "Delete a skill from the library",
args: {
name: tool.schema.string().describe("The skill name to delete"),
},
async execute(args) {
await apiRequest(`/skill/${encodeURIComponent(args.name)}`, {
method: "DELETE",
})
return `Skill '${args.name}' deleted. Remember to commit and push your changes.`
},
})