Add strip_fences option and fix exec() scoping for nested functions
- Add strip_fences field to PromptStep for removing markdown code fences - Fix exec() to use same dict for globals and locals, allowing nested functions to access module-level imports - Add GUI checkbox for strip_fences option - Update CLAUDE.md with improved documentation Co-Authored-By: Claude Opus 4.5 <[email protected]>
This commit is contained in:
@@ -5,7 +5,8 @@ import ast
|
||||
from PySide6.QtWidgets import (
|
||||
QDialog, QVBoxLayout, QFormLayout, QLineEdit,
|
||||
QComboBox, QPushButton, QHBoxLayout, QLabel,
|
||||
QPlainTextEdit, QSplitter, QGroupBox, QTextEdit, QMessageBox
|
||||
QPlainTextEdit, QSplitter, QGroupBox, QTextEdit, QMessageBox,
|
||||
QCheckBox
|
||||
)
|
||||
from PySide6.QtCore import Qt, QThread, Signal
|
||||
|
||||
@@ -68,6 +69,10 @@ class PromptStepDialog(QDialog):
|
||||
self.output_input.setText("response")
|
||||
form.addRow("Output variable:", self.output_input)
|
||||
|
||||
# Strip fences checkbox
|
||||
self.strip_fences_check = QCheckBox("Strip markdown code fences from output")
|
||||
form.addRow("", self.strip_fences_check)
|
||||
|
||||
layout.addLayout(form)
|
||||
|
||||
# Prompt text
|
||||
@@ -118,6 +123,7 @@ class PromptStepDialog(QDialog):
|
||||
|
||||
self.output_input.setText(step.output_var)
|
||||
self.prompt_input.setPlainText(step.prompt)
|
||||
self.strip_fences_check.setChecked(step.strip_fences)
|
||||
|
||||
def _validate_and_accept(self):
|
||||
"""Validate and accept."""
|
||||
@@ -146,7 +152,8 @@ class PromptStepDialog(QDialog):
|
||||
provider=self.provider_combo.currentText(),
|
||||
output_var=self.output_input.text().strip(),
|
||||
profile=profile,
|
||||
name=name
|
||||
name=name,
|
||||
strip_fences=self.strip_fences_check.isChecked()
|
||||
)
|
||||
|
||||
|
||||
|
||||
+13
-3
@@ -221,7 +221,13 @@ def execute_prompt_step(
|
||||
print(f"Error in prompt step: {result.error}", file=sys.stderr)
|
||||
return "", False
|
||||
|
||||
return result.text, True
|
||||
text = result.text
|
||||
if step.strip_fences:
|
||||
import re
|
||||
text = re.sub(r'^```\w*\n', '', text.strip())
|
||||
text = re.sub(r'\n```\s*$', '', text)
|
||||
|
||||
return text, True
|
||||
|
||||
|
||||
def execute_code_step(
|
||||
@@ -245,11 +251,15 @@ def execute_code_step(
|
||||
code = substitute_variables(step.code, variables, warn_non_scalar=verbose)
|
||||
|
||||
# Create execution environment with variables
|
||||
local_vars = dict(variables)
|
||||
# IMPORTANT: Use the same dict for both globals and locals.
|
||||
# When exec() gets separate dicts, nested functions can't access
|
||||
# module-level imports (they look in globals, not the exec's locals).
|
||||
local_vars = {"__builtins__": __builtins__}
|
||||
local_vars.update(variables)
|
||||
|
||||
try:
|
||||
# Execute the code with substituted variables
|
||||
exec(code, {"__builtins__": __builtins__}, local_vars)
|
||||
exec(code, local_vars, local_vars)
|
||||
|
||||
# Support comma-separated output vars (e.g., "a, b, c")
|
||||
output_vars = [v.strip() for v in step.output_var.split(',')]
|
||||
|
||||
@@ -100,6 +100,7 @@ class PromptStep:
|
||||
prompt_file: Optional[str] = None # Optional filename for external prompt
|
||||
profile: Optional[str] = None # Optional AI persona profile name
|
||||
name: Optional[str] = None # Optional display name for the step
|
||||
strip_fences: bool = False # Strip markdown code fences from output
|
||||
|
||||
def to_dict(self) -> dict:
|
||||
d = {
|
||||
@@ -114,6 +115,8 @@ class PromptStep:
|
||||
d["profile"] = self.profile
|
||||
if self.name:
|
||||
d["name"] = self.name
|
||||
if self.strip_fences:
|
||||
d["strip_fences"] = self.strip_fences
|
||||
return d
|
||||
|
||||
@classmethod
|
||||
@@ -124,7 +127,8 @@ class PromptStep:
|
||||
output_var=data["output_var"],
|
||||
prompt_file=data.get("prompt_file"),
|
||||
profile=data.get("profile"),
|
||||
name=data.get("name")
|
||||
name=data.get("name"),
|
||||
strip_fences=data.get("strip_fences", False)
|
||||
)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user