-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathyamlLoader.ts
More file actions
75 lines (65 loc) · 2.53 KB
/
Copy pathyamlLoader.ts
File metadata and controls
75 lines (65 loc) · 2.53 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
import YAML from 'yaml'
import { logForDebugging } from '../../utils/debug.js'
interface YamlWorkflowStep {
agent: string
label?: string
phase?: string
schema?: Record<string, unknown>
model?: string
effort?: string
}
interface YamlWorkflow {
name: string
description: string
phases?: Array<{ title: string; detail?: string }>
steps: YamlWorkflowStep[]
args?: unknown
}
// JSON.stringify produces a complete, properly-escaped JS string literal.
// Using it for all interpolated values prevents code injection via crafted YAML.
function jsStr(val: string): string {
return JSON.stringify(val)
}
export function parseYamlWorkflow(content: string, source: string): string | null {
try {
const parsed = YAML.parse(content) as YamlWorkflow | null
if (!parsed || !parsed.name || !parsed.steps) {
logForDebugging(`[yamlLoader] invalid workflow: missing name or steps`)
return null
}
const phases = parsed.phases || []
const meta = {
name: parsed.name,
description: parsed.description || '',
...(phases.length > 0 ? { phases } : {}),
}
const lines: string[] = []
lines.push(`export const meta = ${JSON.stringify(meta, null, 2)}`)
lines.push('')
let currentPhase = ''
for (const step of parsed.steps) {
if (step.phase && step.phase !== currentPhase) {
lines.push(`phase(${jsStr(step.phase)})`)
currentPhase = step.phase
}
const opts: string[] = []
if (step.label) opts.push(`label: ${jsStr(step.label)}`)
if (step.phase) opts.push(`phase: ${jsStr(step.phase)}`)
if (step.model) opts.push(`model: ${jsStr(step.model)}`)
if (step.effort) opts.push(`effort: ${jsStr(step.effort)}`)
if (step.schema) opts.push(`schema: ${JSON.stringify(step.schema)}`)
const optsStr = opts.length > 0 ? `, { ${opts.join(', ')} }` : ''
if (!step.agent) {
logForDebugging(`[yamlLoader] skipping step with missing agent field`)
continue
}
lines.push(`await agent(${jsStr(step.agent)}${optsStr})`)
}
const script = lines.join('\n')
logForDebugging(`[yamlLoader] converted YAML workflow "${parsed.name}" (${parsed.steps.length} steps)`)
return script
} catch (err) {
logForDebugging(`[yamlLoader] parse error: ${(err as Error).message}`)
return null
}
}