ManimCat / src /studio-agent /skills /runtime /skill-runtime.ts
Bin29's picture
Sync from main: e764154 feat(plot-skill): add math-exam-diagram SKILL.md for exam-style math figures
abcf568
Raw
History Blame Contribute Delete
3.28 kB
import type { StudioSession } from '../../domain/types'
import { logPlotStudioSkillTrace } from '../../observability/plot-studio-skill-trace'
import { createStudioSkillRegistry, type StudioSkillRegistry } from '../registry/skill-registry'
import { createStudioSkillLoader } from '../resolver/skill-loader'
import type {
StudioResolvedSkill,
StudioSkillDiscoveryEntry,
StudioSkillUsageSummary
} from '../schema/skill-types'
import {
createInMemoryStudioSkillStateStore,
type StudioSkillStateStore
} from '../state/skill-state-store'
export interface StudioSkillRuntime {
listDiscovery(session: StudioSession): Promise<StudioSkillDiscoveryEntry[]>
resolve(name: string, session: StudioSession): Promise<StudioResolvedSkill>
listSummaries(session: StudioSession): Promise<StudioSkillUsageSummary[]>
recordUsage(input: {
session: StudioSession
skillName: string
reason?: string
takeaway?: string
stillRelevant?: boolean
}): Promise<void>
}
export function createStudioSkillRuntime(input?: {
registry?: StudioSkillRegistry
stateStore?: StudioSkillStateStore
maxFiles?: number
}): StudioSkillRuntime {
const registry = input?.registry ?? createStudioSkillRegistry()
const loader = createStudioSkillLoader({
registry,
maxFiles: input?.maxFiles
})
const stateStore = input?.stateStore ?? createInMemoryStudioSkillStateStore()
return {
async listDiscovery(session) {
logPlotStudioSkillTrace(session.studioKind, 'skill.discovery.requested', {
sessionId: session.id,
sessionDirectory: session.directory,
})
const entries = await registry.list(session)
logPlotStudioSkillTrace(session.studioKind, 'skill.discovery.completed', {
sessionId: session.id,
discoveredSkillCount: entries.length,
discoveredSkillNames: entries.map((entry) => entry.name),
})
return entries
},
async resolve(name, session) {
logPlotStudioSkillTrace(session.studioKind, 'skill.resolve.requested', {
sessionId: session.id,
skillName: name,
})
const skill = await loader.resolve(name, session)
logPlotStudioSkillTrace(session.studioKind, 'skill.resolve.completed', {
sessionId: session.id,
skillName: skill.name,
source: skill.source,
scope: skill.scope,
entryFile: skill.entryFile,
fileCount: skill.files.length,
})
return skill
},
async listSummaries(session) {
logPlotStudioSkillTrace(session.studioKind, 'skill.summary.requested', {
sessionId: session.id,
})
const summaries = await stateStore.list(session)
logPlotStudioSkillTrace(session.studioKind, 'skill.summary.completed', {
sessionId: session.id,
summaryCount: summaries.length,
summarySkillNames: summaries.map((summary) => summary.skillName),
})
return summaries
},
async recordUsage(value) {
await stateStore.record(value)
logPlotStudioSkillTrace(value.session.studioKind, 'skill.usage.recorded', {
sessionId: value.session.id,
skillName: value.skillName,
reason: value.reason,
takeaway: value.takeaway,
stillRelevant: value.stillRelevant,
})
}
}
}