| |
| |
|
|
| import type { Action, Skill } from "./skill.ts"; |
| import { findPlaceholders, substitute, substituteWithReport } from "./substitute.ts"; |
|
|
| export interface StepPlan { |
| id: string; |
| action: Action; |
| instruction: string; |
| target: { |
| description: string; |
| bbox?: [number, number, number, number]; |
| ax_role?: string; |
| ax_name?: string; |
| }; |
| successCheck: string; |
| fallback?: string; |
| } |
|
|
| export interface ExecutionPlan { |
| skill_name: string; |
| intent: string; |
| domain: string; |
| inputs: Record<string, string>; |
| steps: StepPlan[]; |
| unbound_placeholders: string[]; |
| } |
|
|
| export function planSkill( |
| skill: Skill, |
| inputs: Record<string, string> = {}, |
| ): ExecutionPlan { |
| const unbound = new Set<string>(); |
| const collect = (s: string) => { |
| for (const ph of findPlaceholders(s)) { |
| const key = ph.slice(2, -2); |
| if (inputs[key] === undefined && inputs[key.toLowerCase()] === undefined) { |
| unbound.add(ph); |
| } |
| } |
| }; |
|
|
| for (const ph of skill.meta.placeholders) { |
| const key = ph.slice(2, -2); |
| if (inputs[key] === undefined && inputs[key.toLowerCase()] === undefined) { |
| unbound.add(ph); |
| } |
| } |
|
|
| const steps: StepPlan[] = skill.steps.map((s) => { |
| collect(s.instruction); |
| collect(s.target.description); |
| collect(s.successCheck); |
| if (s.fallback) collect(s.fallback); |
|
|
| const target: StepPlan["target"] = { |
| description: substitute(s.target.description, inputs), |
| }; |
| if (s.target.bbox) target.bbox = s.target.bbox; |
| if (s.target.ax_role) target.ax_role = s.target.ax_role; |
| if (s.target.ax_name) target.ax_name = s.target.ax_name; |
|
|
| const step: StepPlan = { |
| id: s.id, |
| action: s.action, |
| instruction: substitute(s.instruction, inputs), |
| target, |
| successCheck: substitute(s.successCheck, inputs), |
| }; |
| if (s.fallback) step.fallback = substitute(s.fallback, inputs); |
| return step; |
| }); |
|
|
| return { |
| skill_name: skill.name, |
| intent: substitute(skill.intent, inputs), |
| domain: skill.meta.domain, |
| inputs, |
| steps, |
| unbound_placeholders: [...unbound].sort(), |
| }; |
| } |
|
|
| export { substitute, substituteWithReport, findPlaceholders }; |
|
|