feat: Script Generator Phase 1 — backend models, engine, API, and AD templates #105

Merged
chihlasm merged 78 commits from feat/script-generator into main 2026-03-15 00:19:00 +00:00
2 changed files with 27 additions and 7 deletions
Showing only changes of commit 5efe42583a - Show all commits

View File

@@ -67,6 +67,16 @@ export function ScriptTemplateEditor({ templateId, onBack, onSaved }: Props) {
const { canShareScriptTemplate } = usePermissions() const { canShareScriptTemplate } = usePermissions()
// Dismiss stepper if user edits the script body during detection
const scriptBodyRef = form.script_body
useEffect(() => {
if (showStepper) {
setShowStepper(false)
setDetectedCandidates([])
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [scriptBodyRef])
// Load categories + template detail (if editing) // Load categories + template detail (if editing)
useEffect(() => { useEffect(() => {
const load = async () => { const load = async () => {

View File

@@ -127,19 +127,33 @@ function parseDefault(value: string | null, type: ScriptParameter['type']): stri
*/ */
function findScriptLevelParamBlock(script: string): { start: number; end: number } | null { function findScriptLevelParamBlock(script: string): { start: number; end: number } | null {
const lines = script.split('\n') const lines = script.split('\n')
let inFunction = false let functionBraceDepth = 0
let paramStart = -1 let paramStart = -1
let parenDepth = 0 let parenDepth = 0
for (let i = 0; i < lines.length; i++) { for (let i = 0; i < lines.length; i++) {
const trimmed = lines[i].trim() const trimmed = lines[i].trim()
// Track function blocks with brace depth to handle nested braces
if (/^function\s+/i.test(trimmed)) { if (/^function\s+/i.test(trimmed)) {
inFunction = true // Count braces on this line and subsequent lines
for (const ch of lines[i]) {
if (ch === '{') functionBraceDepth++
if (ch === '}') functionBraceDepth--
}
continue continue
} }
if (!inFunction && /^param\s*\(/i.test(trimmed) && paramStart === -1) { // Track braces while inside a function
if (functionBraceDepth > 0) {
for (const ch of lines[i]) {
if (ch === '{') functionBraceDepth++
if (ch === '}') functionBraceDepth--
}
continue
}
if (functionBraceDepth === 0 && /^param\s*\(/i.test(trimmed) && paramStart === -1) {
paramStart = i paramStart = i
for (let j = i; j < lines.length; j++) { for (let j = i; j < lines.length; j++) {
for (const ch of lines[j]) { for (const ch of lines[j]) {
@@ -151,10 +165,6 @@ function findScriptLevelParamBlock(script: string): { start: number; end: number
} }
} }
} }
if (inFunction && trimmed === '}') {
inFunction = false
}
} }
return null return null