Add missing participant SmartTools
Added 7 additional AI participants: - discussion-backend: Backend/API perspective - discussion-designer: Visual/UX design perspective - discussion-devops: Infrastructure/deployment perspective - discussion-frontend: Frontend/UI perspective - discussion-performance: Performance/optimization perspective - discussion-qa: Testing/quality perspective - discussion-ux: User experience perspective These are now bundled with the project and will be installed automatically when building the Docker container. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
896f855738
commit
a39103c2ca
|
|
@ -0,0 +1,141 @@
|
||||||
|
name: discussion-backend
|
||||||
|
description: Backend development specialist participant for discussions
|
||||||
|
category: Discussion
|
||||||
|
meta:
|
||||||
|
display_name: AI-Backend
|
||||||
|
alias: backend
|
||||||
|
type: voting
|
||||||
|
expertise:
|
||||||
|
- API design
|
||||||
|
- Database design
|
||||||
|
- Server architecture
|
||||||
|
- Authentication/Authorization
|
||||||
|
- Data modeling
|
||||||
|
- Microservices
|
||||||
|
- Message queues
|
||||||
|
concerns:
|
||||||
|
- Is the API design RESTful/consistent?
|
||||||
|
- What's the data model?
|
||||||
|
- How do we handle transactions?
|
||||||
|
- Is authentication properly implemented?
|
||||||
|
voice: en-AU-Neural2-B
|
||||||
|
provider: codex
|
||||||
|
color:
|
||||||
|
- 100
|
||||||
|
- 200
|
||||||
|
- 100
|
||||||
|
arguments:
|
||||||
|
- flag: --callout
|
||||||
|
variable: callout
|
||||||
|
default: ''
|
||||||
|
description: Specific question or @mention context
|
||||||
|
- flag: --templates-dir
|
||||||
|
variable: templates_dir
|
||||||
|
default: templates
|
||||||
|
description: Path to templates directory
|
||||||
|
- flag: --diagrams-dir
|
||||||
|
variable: diagrams_dir
|
||||||
|
default: diagrams
|
||||||
|
description: Path to save diagrams
|
||||||
|
- flag: --log-file
|
||||||
|
variable: log_file
|
||||||
|
default: ''
|
||||||
|
description: Path to log file for progress updates
|
||||||
|
steps:
|
||||||
|
- type: code
|
||||||
|
code: "import re\nimport os\n\nphase_match = re.search(r'<!--\\s*Phase:\\s*(\\w+)\\\
|
||||||
|
s*-->', input, re.IGNORECASE)\ntemplate_match = re.search(r'<!--\\s*Template:\\\
|
||||||
|
s*(\\w+)\\s*-->', input, re.IGNORECASE)\n\ncurrent_phase = phase_match.group(1)\
|
||||||
|
\ if phase_match else \"initial_feedback\"\ntemplate_name = template_match.group(1)\
|
||||||
|
\ if template_match else \"feature\"\n\ntemplate_path = os.path.join(templates_dir,\
|
||||||
|
\ template_name + \".yaml\")\nphase_goal = \"Provide backend feedback\"\nphase_instructions\
|
||||||
|
\ = \"Review the proposal for backend implementation concerns.\"\n\nif os.path.exists(template_path):\n\
|
||||||
|
\ import yaml\n with open(template_path, 'r') as f:\n template =\
|
||||||
|
\ yaml.safe_load(f)\n phases = template.get(\"phases\", {})\n phase_info\
|
||||||
|
\ = phases.get(current_phase, {})\n phase_goal = phase_info.get(\"goal\", phase_goal)\n\
|
||||||
|
\ phase_instructions = phase_info.get(\"instructions\", phase_instructions)\n\
|
||||||
|
\nphase_context = \"Current Phase: \" + current_phase + \"\\n\"\nphase_context\
|
||||||
|
\ += \"Phase Goal: \" + phase_goal + \"\\n\"\nphase_context += \"Phase Instructions:\\\
|
||||||
|
n\" + phase_instructions\n"
|
||||||
|
output_var: phase_context, current_phase
|
||||||
|
- type: code
|
||||||
|
code: "import re\nimport os\n\ntitle_match = re.search(r'<!--\\s*Title:\\s*(.+?)\\\
|
||||||
|
s*-->', input)\ndiscussion_name = \"discussion\"\nif title_match:\n discussion_name\
|
||||||
|
\ = title_match.group(1).strip().lower()\n discussion_name = re.sub(r'[^a-z0-9]+',\
|
||||||
|
\ '-', discussion_name)\n\nos.makedirs(diagrams_dir, exist_ok=True)\n\nexisting\
|
||||||
|
\ = []\nif os.path.exists(diagrams_dir):\n for f in os.listdir(diagrams_dir):\n\
|
||||||
|
\ if f.startswith(discussion_name):\n existing.append(f)\n\n\
|
||||||
|
next_num = len(existing) + 1\ndiagram_path = diagrams_dir + \"/\" + discussion_name\
|
||||||
|
\ + \"_backend_\" + str(next_num) + \".puml\"\n"
|
||||||
|
output_var: diagram_path
|
||||||
|
- type: code
|
||||||
|
code: "import sys\nimport datetime as dt\ntimestamp = dt.datetime.now().strftime(\"\
|
||||||
|
%H:%M:%S\")\nfor msg in [f\"Phase: {current_phase}\", \"Calling AI provider...\"\
|
||||||
|
]:\n line = f\"[{timestamp}] [backend] {msg}\"\n print(line, file=sys.stderr)\n\
|
||||||
|
\ sys.stderr.flush()\n if log_file:\n with open(log_file, 'a') as\
|
||||||
|
\ f:\n f.write(line + \"\\n\")\n f.flush()\n"
|
||||||
|
output_var: _progress1
|
||||||
|
- type: prompt
|
||||||
|
prompt: "You are AI-Backend (also known as Blake), a backend development specialist\
|
||||||
|
\ who\ndesigns robust APIs, efficient databases, and scalable server architectures.\n\
|
||||||
|
\n## Your Role\n- Design clean, consistent API interfaces\n- Model data relationships\
|
||||||
|
\ and storage strategies\n- Ensure proper authentication and authorization\n-\
|
||||||
|
\ Consider transaction handling and data integrity\n- Apply backend best practices\
|
||||||
|
\ and patterns\n\n## Your Perspective\n- APIs are contracts - design them carefully\n\
|
||||||
|
- Database design determines application limits\n- N+1 queries are the silent\
|
||||||
|
\ performance killer\n- Idempotency matters for reliability\n- Think about the\
|
||||||
|
\ data lifecycle\n\n## Backend Checklist\n- API design (REST/GraphQL conventions)\n\
|
||||||
|
- Database schema and indexes\n- Authentication/Authorization flow\n- Transaction\
|
||||||
|
\ boundaries\n- Caching strategy\n- Error handling and logging\n- Rate limiting\
|
||||||
|
\ and quotas\n- Migration strategy\n\n## Phase Context\n{phase_context}\n\n##\
|
||||||
|
\ Diagrams\nWhen creating API or database diagrams, include a reference marker.\n\
|
||||||
|
Diagram path to use: {diagram_path}\n\nIMPORTANT: When you create a diagram, your\
|
||||||
|
\ comment MUST include:\nDIAGRAM: {diagram_path}\n\n## Current Discussion\n{input}\n\
|
||||||
|
\n## Your Task\n{callout}\n\nFollow the phase instructions. Analyze from a backend\
|
||||||
|
\ development perspective.\n\n## Response Format\nRespond with valid JSON only.\
|
||||||
|
\ Use \\n for newlines in strings:\n{{\n \"comment\": \"Your backend analysis...\\\
|
||||||
|
n\\nDIAGRAM: path/file.puml (if created)\",\n \"vote\": \"READY\" or \"CHANGES\"\
|
||||||
|
\ or \"REJECT\" or null,\n \"diagram\": \"@startuml\\n...\\n@enduml\"\n}}\n\n\
|
||||||
|
Vote meanings:\n- READY: Backend implementation is solid\n- CHANGES: Backend improvements\
|
||||||
|
\ needed\n- REJECT: Significant backend issues\n- null: Comment only, no vote\
|
||||||
|
\ change\n\nIf you have nothing meaningful to add, respond: {{\"sentinel\": \"\
|
||||||
|
NO_RESPONSE\"}}\n"
|
||||||
|
provider: codex
|
||||||
|
output_var: response
|
||||||
|
- type: code
|
||||||
|
code: "import sys\nimport datetime as dt\ntimestamp = dt.datetime.now().strftime(\"\
|
||||||
|
%H:%M:%S\")\nline = f\"[{timestamp}] [backend] AI response received\"\nprint(line,\
|
||||||
|
\ file=sys.stderr)\nsys.stderr.flush()\nif log_file:\n with open(log_file,\
|
||||||
|
\ 'a') as f:\n f.write(line + \"\\n\")\n f.flush()\n"
|
||||||
|
output_var: _progress2
|
||||||
|
- type: code
|
||||||
|
code: "import re\njson_text = response.strip()\nif json_text.startswith('```'):\n\
|
||||||
|
\ code_block = re.search(r'```(?:json)?\\s*(\\{.*\\})\\s*```', json_text, re.DOTALL)\n\
|
||||||
|
\ if code_block:\n json_text = code_block.group(1).strip()\n"
|
||||||
|
output_var: json_text
|
||||||
|
- type: code
|
||||||
|
code: "import json\ntry:\n parsed = json.loads(json_text)\nexcept json.JSONDecodeError\
|
||||||
|
\ as e:\n fixed = json_text.replace('\\n', '\\\\n')\n try:\n parsed\
|
||||||
|
\ = json.loads(fixed)\n except json.JSONDecodeError:\n import re\n \
|
||||||
|
\ comment_match = re.search(r'\"comment\"\\s*:\\s*\"(.*?)\"(?=\\s*[,}])',\
|
||||||
|
\ json_text, re.DOTALL)\n vote_match = re.search(r'\"vote\"\\s*:\\s*(\"\
|
||||||
|
?\\w+\"?|null)', json_text)\n diagram_match = re.search(r'\"diagram\"\\\
|
||||||
|
s*:\\s*\"(.*?)\"(?=\\s*[,}])', json_text, re.DOTALL)\n parsed = {\n \
|
||||||
|
\ \"comment\": comment_match.group(1).replace('\\n', ' ') if comment_match\
|
||||||
|
\ else \"Parse error\",\n \"vote\": vote_match.group(1).strip('\"')\
|
||||||
|
\ if vote_match else None,\n \"diagram\": diagram_match.group(1) if\
|
||||||
|
\ diagram_match else None\n }\n if parsed[\"vote\"] == \"null\"\
|
||||||
|
:\n parsed[\"vote\"] = None\ncomment = parsed.get(\"comment\", \"\"\
|
||||||
|
)\nvote = parsed.get(\"vote\")\ndiagram_content = parsed.get(\"diagram\")\nhas_diagram\
|
||||||
|
\ = \"true\" if diagram_content else \"false\"\n"
|
||||||
|
output_var: comment, vote, diagram_content, has_diagram
|
||||||
|
- type: code
|
||||||
|
code: "if has_diagram == \"true\" and diagram_content:\n with open(diagram_path,\
|
||||||
|
\ 'w') as f:\n f.write(diagram_content)\n saved_diagram = diagram_path\n\
|
||||||
|
else:\n saved_diagram = \"\"\n"
|
||||||
|
output_var: saved_diagram
|
||||||
|
- type: code
|
||||||
|
code: "import json\nresult = {\"comment\": comment, \"vote\": vote}\nif saved_diagram:\n\
|
||||||
|
\ result[\"diagram_file\"] = saved_diagram\nfinal_response = json.dumps(result)\n"
|
||||||
|
output_var: final_response
|
||||||
|
output: '{final_response}'
|
||||||
|
|
@ -0,0 +1,141 @@
|
||||||
|
name: discussion-designer
|
||||||
|
description: UI/Visual design specialist participant for discussions
|
||||||
|
category: Discussion
|
||||||
|
meta:
|
||||||
|
display_name: AI-Designer
|
||||||
|
alias: designer
|
||||||
|
type: voting
|
||||||
|
expertise:
|
||||||
|
- Visual design
|
||||||
|
- UI patterns
|
||||||
|
- Color theory
|
||||||
|
- Typography
|
||||||
|
- Layout systems
|
||||||
|
- Design systems
|
||||||
|
- Accessibility (visual)
|
||||||
|
concerns:
|
||||||
|
- Is the visual hierarchy clear?
|
||||||
|
- Does this follow design system guidelines?
|
||||||
|
- Is the interface aesthetically pleasing and consistent?
|
||||||
|
- Are visual elements accessible (contrast, sizing)?
|
||||||
|
voice: en-GB-Neural2-A
|
||||||
|
provider: claude-haiku
|
||||||
|
color:
|
||||||
|
- 200
|
||||||
|
- 100
|
||||||
|
- 255
|
||||||
|
arguments:
|
||||||
|
- flag: --callout
|
||||||
|
variable: callout
|
||||||
|
default: ''
|
||||||
|
description: Specific question or @mention context
|
||||||
|
- flag: --templates-dir
|
||||||
|
variable: templates_dir
|
||||||
|
default: templates
|
||||||
|
description: Path to templates directory
|
||||||
|
- flag: --diagrams-dir
|
||||||
|
variable: diagrams_dir
|
||||||
|
default: diagrams
|
||||||
|
description: Path to save diagrams
|
||||||
|
- flag: --log-file
|
||||||
|
variable: log_file
|
||||||
|
default: ''
|
||||||
|
description: Path to log file for progress updates
|
||||||
|
steps:
|
||||||
|
- type: code
|
||||||
|
code: "import re\nimport os\n\nphase_match = re.search(r'<!--\\s*Phase:\\s*(\\w+)\\\
|
||||||
|
s*-->', input, re.IGNORECASE)\ntemplate_match = re.search(r'<!--\\s*Template:\\\
|
||||||
|
s*(\\w+)\\s*-->', input, re.IGNORECASE)\n\ncurrent_phase = phase_match.group(1)\
|
||||||
|
\ if phase_match else \"initial_feedback\"\ntemplate_name = template_match.group(1)\
|
||||||
|
\ if template_match else \"feature\"\n\ntemplate_path = os.path.join(templates_dir,\
|
||||||
|
\ template_name + \".yaml\")\nphase_goal = \"Provide design feedback\"\nphase_instructions\
|
||||||
|
\ = \"Review the proposal for visual design concerns.\"\n\nif os.path.exists(template_path):\n\
|
||||||
|
\ import yaml\n with open(template_path, 'r') as f:\n template =\
|
||||||
|
\ yaml.safe_load(f)\n phases = template.get(\"phases\", {})\n phase_info\
|
||||||
|
\ = phases.get(current_phase, {})\n phase_goal = phase_info.get(\"goal\", phase_goal)\n\
|
||||||
|
\ phase_instructions = phase_info.get(\"instructions\", phase_instructions)\n\
|
||||||
|
\nphase_context = \"Current Phase: \" + current_phase + \"\\n\"\nphase_context\
|
||||||
|
\ += \"Phase Goal: \" + phase_goal + \"\\n\"\nphase_context += \"Phase Instructions:\\\
|
||||||
|
n\" + phase_instructions\n"
|
||||||
|
output_var: phase_context, current_phase
|
||||||
|
- type: code
|
||||||
|
code: "import re\nimport os\n\ntitle_match = re.search(r'<!--\\s*Title:\\s*(.+?)\\\
|
||||||
|
s*-->', input)\ndiscussion_name = \"discussion\"\nif title_match:\n discussion_name\
|
||||||
|
\ = title_match.group(1).strip().lower()\n discussion_name = re.sub(r'[^a-z0-9]+',\
|
||||||
|
\ '-', discussion_name)\n\nos.makedirs(diagrams_dir, exist_ok=True)\n\nexisting\
|
||||||
|
\ = []\nif os.path.exists(diagrams_dir):\n for f in os.listdir(diagrams_dir):\n\
|
||||||
|
\ if f.startswith(discussion_name):\n existing.append(f)\n\n\
|
||||||
|
next_num = len(existing) + 1\ndiagram_path = diagrams_dir + \"/\" + discussion_name\
|
||||||
|
\ + \"_designer_\" + str(next_num) + \".puml\"\n"
|
||||||
|
output_var: diagram_path
|
||||||
|
- type: code
|
||||||
|
code: "import sys\nimport datetime as dt\ntimestamp = dt.datetime.now().strftime(\"\
|
||||||
|
%H:%M:%S\")\nfor msg in [f\"Phase: {current_phase}\", \"Calling AI provider...\"\
|
||||||
|
]:\n line = f\"[{timestamp}] [designer] {msg}\"\n print(line, file=sys.stderr)\n\
|
||||||
|
\ sys.stderr.flush()\n if log_file:\n with open(log_file, 'a') as\
|
||||||
|
\ f:\n f.write(line + \"\\n\")\n f.flush()\n"
|
||||||
|
output_var: _progress1
|
||||||
|
- type: prompt
|
||||||
|
prompt: "You are AI-Designer (also known as Dana), a visual design specialist who\
|
||||||
|
\ focuses on\ncreating beautiful, intuitive, and consistent user interfaces.\n\
|
||||||
|
\n## Your Role\n- Evaluate visual design decisions and aesthetics\n- Ensure consistency\
|
||||||
|
\ with design systems and patterns\n- Consider visual hierarchy and information\
|
||||||
|
\ architecture\n- Suggest improvements for clarity and usability\n- Balance aesthetics\
|
||||||
|
\ with functionality\n\n## Your Perspective\n- Design is how it works, not just\
|
||||||
|
\ how it looks\n- Consistency builds trust and reduces cognitive load\n- White\
|
||||||
|
\ space is a design element, not empty space\n- Every visual element should serve\
|
||||||
|
\ a purpose\n- Accessible design is good design\n\n## Design Checklist\n- Visual\
|
||||||
|
\ hierarchy (what draws attention first?)\n- Color usage and contrast ratios\n\
|
||||||
|
- Typography (readability, scale, weight)\n- Spacing and alignment\n- Component\
|
||||||
|
\ consistency\n- Responsive considerations\n- Brand alignment\n\n## Phase Context\n\
|
||||||
|
{phase_context}\n\n## Diagrams\nWhen creating wireframes or layout diagrams, include\
|
||||||
|
\ a reference marker.\nDiagram path to use: {diagram_path}\n\nIMPORTANT: When\
|
||||||
|
\ you create a diagram, your comment MUST include:\nDIAGRAM: {diagram_path}\n\n\
|
||||||
|
## Current Discussion\n{input}\n\n## Your Task\n{callout}\n\nFollow the phase\
|
||||||
|
\ instructions. Analyze from a visual design perspective.\n\n## Response Format\n\
|
||||||
|
Respond with valid JSON only. Use \\n for newlines in strings:\n{{\n \"comment\"\
|
||||||
|
: \"Your design analysis...\\n\\nDIAGRAM: path/file.puml (if created)\",\n \"\
|
||||||
|
vote\": \"READY\" or \"CHANGES\" or \"REJECT\" or null,\n \"diagram\": \"@startuml\\\
|
||||||
|
n...\\n@enduml\"\n}}\n\nVote meanings:\n- READY: Design is solid and consistent\n\
|
||||||
|
- CHANGES: Design improvements needed\n- REJECT: Fundamental design issues\n-\
|
||||||
|
\ null: Comment only, no vote change\n\nIf you have nothing meaningful to add,\
|
||||||
|
\ respond: {{\"sentinel\": \"NO_RESPONSE\"}}\n"
|
||||||
|
provider: claude-haiku
|
||||||
|
output_var: response
|
||||||
|
- type: code
|
||||||
|
code: "import sys\nimport datetime as dt\ntimestamp = dt.datetime.now().strftime(\"\
|
||||||
|
%H:%M:%S\")\nline = f\"[{timestamp}] [designer] AI response received\"\nprint(line,\
|
||||||
|
\ file=sys.stderr)\nsys.stderr.flush()\nif log_file:\n with open(log_file,\
|
||||||
|
\ 'a') as f:\n f.write(line + \"\\n\")\n f.flush()\n"
|
||||||
|
output_var: _progress2
|
||||||
|
- type: code
|
||||||
|
code: "import re\njson_text = response.strip()\nif json_text.startswith('```'):\n\
|
||||||
|
\ code_block = re.search(r'```(?:json)?\\s*(\\{.*\\})\\s*```', json_text, re.DOTALL)\n\
|
||||||
|
\ if code_block:\n json_text = code_block.group(1).strip()\n"
|
||||||
|
output_var: json_text
|
||||||
|
- type: code
|
||||||
|
code: "import json\ntry:\n parsed = json.loads(json_text)\nexcept json.JSONDecodeError\
|
||||||
|
\ as e:\n fixed = json_text.replace('\\n', '\\\\n')\n try:\n parsed\
|
||||||
|
\ = json.loads(fixed)\n except json.JSONDecodeError:\n import re\n \
|
||||||
|
\ comment_match = re.search(r'\"comment\"\\s*:\\s*\"(.*?)\"(?=\\s*[,}])',\
|
||||||
|
\ json_text, re.DOTALL)\n vote_match = re.search(r'\"vote\"\\s*:\\s*(\"\
|
||||||
|
?\\w+\"?|null)', json_text)\n diagram_match = re.search(r'\"diagram\"\\\
|
||||||
|
s*:\\s*\"(.*?)\"(?=\\s*[,}])', json_text, re.DOTALL)\n parsed = {\n \
|
||||||
|
\ \"comment\": comment_match.group(1).replace('\\n', ' ') if comment_match\
|
||||||
|
\ else \"Parse error\",\n \"vote\": vote_match.group(1).strip('\"')\
|
||||||
|
\ if vote_match else None,\n \"diagram\": diagram_match.group(1) if\
|
||||||
|
\ diagram_match else None\n }\n if parsed[\"vote\"] == \"null\"\
|
||||||
|
:\n parsed[\"vote\"] = None\ncomment = parsed.get(\"comment\", \"\"\
|
||||||
|
)\nvote = parsed.get(\"vote\")\ndiagram_content = parsed.get(\"diagram\")\nhas_diagram\
|
||||||
|
\ = \"true\" if diagram_content else \"false\"\n"
|
||||||
|
output_var: comment, vote, diagram_content, has_diagram
|
||||||
|
- type: code
|
||||||
|
code: "if has_diagram == \"true\" and diagram_content:\n with open(diagram_path,\
|
||||||
|
\ 'w') as f:\n f.write(diagram_content)\n saved_diagram = diagram_path\n\
|
||||||
|
else:\n saved_diagram = \"\"\n"
|
||||||
|
output_var: saved_diagram
|
||||||
|
- type: code
|
||||||
|
code: "import json\nresult = {\"comment\": comment, \"vote\": vote}\nif saved_diagram:\n\
|
||||||
|
\ result[\"diagram_file\"] = saved_diagram\nfinal_response = json.dumps(result)\n"
|
||||||
|
output_var: final_response
|
||||||
|
output: '{final_response}'
|
||||||
|
|
@ -0,0 +1,143 @@
|
||||||
|
name: discussion-devops
|
||||||
|
description: DevOps specialist participant for discussions
|
||||||
|
category: Discussion
|
||||||
|
meta:
|
||||||
|
display_name: AI-DevOps
|
||||||
|
alias: devops
|
||||||
|
type: voting
|
||||||
|
expertise:
|
||||||
|
- CI/CD pipelines
|
||||||
|
- Infrastructure as Code
|
||||||
|
- Container orchestration
|
||||||
|
- Monitoring and observability
|
||||||
|
- Cloud platforms (AWS
|
||||||
|
- GCP
|
||||||
|
- Azure)
|
||||||
|
- Configuration management
|
||||||
|
- Deployment strategies
|
||||||
|
concerns:
|
||||||
|
- How do we deploy this?
|
||||||
|
- What's the monitoring strategy?
|
||||||
|
- Is this infrastructure scalable?
|
||||||
|
- How do we handle rollbacks?
|
||||||
|
voice: en-US-Neural2-F
|
||||||
|
provider: claude
|
||||||
|
color:
|
||||||
|
- 100
|
||||||
|
- 200
|
||||||
|
- 255
|
||||||
|
arguments:
|
||||||
|
- flag: --callout
|
||||||
|
variable: callout
|
||||||
|
default: ''
|
||||||
|
description: Specific question or @mention context
|
||||||
|
- flag: --templates-dir
|
||||||
|
variable: templates_dir
|
||||||
|
default: templates
|
||||||
|
description: Path to templates directory
|
||||||
|
- flag: --diagrams-dir
|
||||||
|
variable: diagrams_dir
|
||||||
|
default: diagrams
|
||||||
|
description: Path to save diagrams
|
||||||
|
- flag: --log-file
|
||||||
|
variable: log_file
|
||||||
|
default: ''
|
||||||
|
description: Path to log file for progress updates
|
||||||
|
steps:
|
||||||
|
- type: code
|
||||||
|
code: "import re\nimport os\n\nphase_match = re.search(r'<!--\\s*Phase:\\s*(\\w+)\\\
|
||||||
|
s*-->', input, re.IGNORECASE)\ntemplate_match = re.search(r'<!--\\s*Template:\\\
|
||||||
|
s*(\\w+)\\s*-->', input, re.IGNORECASE)\n\ncurrent_phase = phase_match.group(1)\
|
||||||
|
\ if phase_match else \"initial_feedback\"\ntemplate_name = template_match.group(1)\
|
||||||
|
\ if template_match else \"feature\"\n\ntemplate_path = os.path.join(templates_dir,\
|
||||||
|
\ template_name + \".yaml\")\nphase_goal = \"Provide DevOps feedback\"\nphase_instructions\
|
||||||
|
\ = \"Review the proposal for deployment and infrastructure concerns.\"\n\nif\
|
||||||
|
\ os.path.exists(template_path):\n import yaml\n with open(template_path,\
|
||||||
|
\ 'r') as f:\n template = yaml.safe_load(f)\n phases = template.get(\"\
|
||||||
|
phases\", {})\n phase_info = phases.get(current_phase, {})\n phase_goal\
|
||||||
|
\ = phase_info.get(\"goal\", phase_goal)\n phase_instructions = phase_info.get(\"\
|
||||||
|
instructions\", phase_instructions)\n\nphase_context = \"Current Phase: \" + current_phase\
|
||||||
|
\ + \"\\n\"\nphase_context += \"Phase Goal: \" + phase_goal + \"\\n\"\nphase_context\
|
||||||
|
\ += \"Phase Instructions:\\n\" + phase_instructions\n"
|
||||||
|
output_var: phase_context, current_phase
|
||||||
|
- type: code
|
||||||
|
code: "import re\nimport os\n\ntitle_match = re.search(r'<!--\\s*Title:\\s*(.+?)\\\
|
||||||
|
s*-->', input)\ndiscussion_name = \"discussion\"\nif title_match:\n discussion_name\
|
||||||
|
\ = title_match.group(1).strip().lower()\n discussion_name = re.sub(r'[^a-z0-9]+',\
|
||||||
|
\ '-', discussion_name)\n\nos.makedirs(diagrams_dir, exist_ok=True)\n\nexisting\
|
||||||
|
\ = []\nif os.path.exists(diagrams_dir):\n for f in os.listdir(diagrams_dir):\n\
|
||||||
|
\ if f.startswith(discussion_name):\n existing.append(f)\n\n\
|
||||||
|
next_num = len(existing) + 1\ndiagram_path = diagrams_dir + \"/\" + discussion_name\
|
||||||
|
\ + \"_devops_\" + str(next_num) + \".puml\"\n"
|
||||||
|
output_var: diagram_path
|
||||||
|
- type: code
|
||||||
|
code: "import sys\nimport datetime as dt\ntimestamp = dt.datetime.now().strftime(\"\
|
||||||
|
%H:%M:%S\")\nfor msg in [f\"Phase: {current_phase}\", \"Calling AI provider...\"\
|
||||||
|
]:\n line = f\"[{timestamp}] [devops] {msg}\"\n print(line, file=sys.stderr)\n\
|
||||||
|
\ sys.stderr.flush()\n if log_file:\n with open(log_file, 'a') as\
|
||||||
|
\ f:\n f.write(line + \"\\n\")\n f.flush()\n"
|
||||||
|
output_var: _progress1
|
||||||
|
- type: prompt
|
||||||
|
prompt: "You are AI-DevOps (also known as Devon), a DevOps specialist who ensures\n\
|
||||||
|
reliable deployments, robust infrastructure, and comprehensive observability.\n\
|
||||||
|
\n## Your Role\n- Design deployment pipelines and strategies\n- Plan infrastructure\
|
||||||
|
\ and scaling approaches\n- Ensure monitoring and alerting coverage\n- Consider\
|
||||||
|
\ disaster recovery and rollback procedures\n- Apply DevOps and SRE best practices\n\
|
||||||
|
\n## Your Perspective\n- If it's not automated, it's a future incident\n- Monitoring\
|
||||||
|
\ is not optional - you can't fix what you can't see\n- Every deployment should\
|
||||||
|
\ be reversible\n- Infrastructure as code prevents configuration drift\n- Chaos\
|
||||||
|
\ is inevitable - plan for it\n\n## DevOps Checklist\n- CI/CD pipeline requirements\n\
|
||||||
|
- Container/orchestration needs\n- Environment configuration\n- Secrets management\n\
|
||||||
|
- Monitoring and alerting\n- Logging and tracing\n- Backup and recovery\n- Scaling\
|
||||||
|
\ strategy (horizontal/vertical)\n- Deployment strategy (blue-green, canary, rolling)\n\
|
||||||
|
\n## Phase Context\n{phase_context}\n\n## Diagrams\nWhen creating infrastructure\
|
||||||
|
\ or deployment diagrams, include a reference marker.\nDiagram path to use: {diagram_path}\n\
|
||||||
|
\nIMPORTANT: When you create a diagram, your comment MUST include:\nDIAGRAM: {diagram_path}\n\
|
||||||
|
\n## Current Discussion\n{input}\n\n## Your Task\n{callout}\n\nFollow the phase\
|
||||||
|
\ instructions. Analyze from a DevOps/infrastructure perspective.\n\n## Response\
|
||||||
|
\ Format\nRespond with valid JSON only. Use \\n for newlines in strings:\n{{\n\
|
||||||
|
\ \"comment\": \"Your DevOps analysis...\\n\\nDIAGRAM: path/file.puml (if created)\"\
|
||||||
|
,\n \"vote\": \"READY\" or \"CHANGES\" or \"REJECT\" or null,\n \"diagram\"\
|
||||||
|
: \"@startuml\\n...\\n@enduml\"\n}}\n\nVote meanings:\n- READY: Deployment/infrastructure\
|
||||||
|
\ is solid\n- CHANGES: DevOps improvements needed\n- REJECT: Significant infrastructure\
|
||||||
|
\ issues\n- null: Comment only, no vote change\n\nIf you have nothing meaningful\
|
||||||
|
\ to add, respond: {{\"sentinel\": \"NO_RESPONSE\"}}\n"
|
||||||
|
provider: claude
|
||||||
|
output_var: response
|
||||||
|
- type: code
|
||||||
|
code: "import sys\nimport datetime as dt\ntimestamp = dt.datetime.now().strftime(\"\
|
||||||
|
%H:%M:%S\")\nline = f\"[{timestamp}] [devops] AI response received\"\nprint(line,\
|
||||||
|
\ file=sys.stderr)\nsys.stderr.flush()\nif log_file:\n with open(log_file,\
|
||||||
|
\ 'a') as f:\n f.write(line + \"\\n\")\n f.flush()\n"
|
||||||
|
output_var: _progress2
|
||||||
|
- type: code
|
||||||
|
code: "import re\njson_text = response.strip()\nif json_text.startswith('```'):\n\
|
||||||
|
\ code_block = re.search(r'```(?:json)?\\s*(\\{.*\\})\\s*```', json_text, re.DOTALL)\n\
|
||||||
|
\ if code_block:\n json_text = code_block.group(1).strip()\n"
|
||||||
|
output_var: json_text
|
||||||
|
- type: code
|
||||||
|
code: "import json\ntry:\n parsed = json.loads(json_text)\nexcept json.JSONDecodeError\
|
||||||
|
\ as e:\n fixed = json_text.replace('\\n', '\\\\n')\n try:\n parsed\
|
||||||
|
\ = json.loads(fixed)\n except json.JSONDecodeError:\n import re\n \
|
||||||
|
\ comment_match = re.search(r'\"comment\"\\s*:\\s*\"(.*?)\"(?=\\s*[,}])',\
|
||||||
|
\ json_text, re.DOTALL)\n vote_match = re.search(r'\"vote\"\\s*:\\s*(\"\
|
||||||
|
?\\w+\"?|null)', json_text)\n diagram_match = re.search(r'\"diagram\"\\\
|
||||||
|
s*:\\s*\"(.*?)\"(?=\\s*[,}])', json_text, re.DOTALL)\n parsed = {\n \
|
||||||
|
\ \"comment\": comment_match.group(1).replace('\\n', ' ') if comment_match\
|
||||||
|
\ else \"Parse error\",\n \"vote\": vote_match.group(1).strip('\"')\
|
||||||
|
\ if vote_match else None,\n \"diagram\": diagram_match.group(1) if\
|
||||||
|
\ diagram_match else None\n }\n if parsed[\"vote\"] == \"null\"\
|
||||||
|
:\n parsed[\"vote\"] = None\ncomment = parsed.get(\"comment\", \"\"\
|
||||||
|
)\nvote = parsed.get(\"vote\")\ndiagram_content = parsed.get(\"diagram\")\nhas_diagram\
|
||||||
|
\ = \"true\" if diagram_content else \"false\"\n"
|
||||||
|
output_var: comment, vote, diagram_content, has_diagram
|
||||||
|
- type: code
|
||||||
|
code: "if has_diagram == \"true\" and diagram_content:\n with open(diagram_path,\
|
||||||
|
\ 'w') as f:\n f.write(diagram_content)\n saved_diagram = diagram_path\n\
|
||||||
|
else:\n saved_diagram = \"\"\n"
|
||||||
|
output_var: saved_diagram
|
||||||
|
- type: code
|
||||||
|
code: "import json\nresult = {\"comment\": comment, \"vote\": vote}\nif saved_diagram:\n\
|
||||||
|
\ result[\"diagram_file\"] = saved_diagram\nfinal_response = json.dumps(result)\n"
|
||||||
|
output_var: final_response
|
||||||
|
output: '{final_response}'
|
||||||
|
|
@ -0,0 +1,141 @@
|
||||||
|
name: discussion-frontend
|
||||||
|
description: Frontend development specialist participant for discussions
|
||||||
|
category: Discussion
|
||||||
|
meta:
|
||||||
|
display_name: AI-Frontend
|
||||||
|
alias: frontend
|
||||||
|
type: voting
|
||||||
|
expertise:
|
||||||
|
- React/Vue/Angular
|
||||||
|
- CSS/Styling
|
||||||
|
- Component architecture
|
||||||
|
- State management
|
||||||
|
- Browser APIs
|
||||||
|
- Performance optimization
|
||||||
|
- Responsive design
|
||||||
|
concerns:
|
||||||
|
- Is this component reusable?
|
||||||
|
- What's the state management strategy?
|
||||||
|
- How does this affect bundle size?
|
||||||
|
- Is this accessible and responsive?
|
||||||
|
voice: en-US-Neural2-C
|
||||||
|
provider: opencode-pickle
|
||||||
|
color:
|
||||||
|
- 255
|
||||||
|
- 150
|
||||||
|
- 200
|
||||||
|
arguments:
|
||||||
|
- flag: --callout
|
||||||
|
variable: callout
|
||||||
|
default: ''
|
||||||
|
description: Specific question or @mention context
|
||||||
|
- flag: --templates-dir
|
||||||
|
variable: templates_dir
|
||||||
|
default: templates
|
||||||
|
description: Path to templates directory
|
||||||
|
- flag: --diagrams-dir
|
||||||
|
variable: diagrams_dir
|
||||||
|
default: diagrams
|
||||||
|
description: Path to save diagrams
|
||||||
|
- flag: --log-file
|
||||||
|
variable: log_file
|
||||||
|
default: ''
|
||||||
|
description: Path to log file for progress updates
|
||||||
|
steps:
|
||||||
|
- type: code
|
||||||
|
code: "import re\nimport os\n\nphase_match = re.search(r'<!--\\s*Phase:\\s*(\\w+)\\\
|
||||||
|
s*-->', input, re.IGNORECASE)\ntemplate_match = re.search(r'<!--\\s*Template:\\\
|
||||||
|
s*(\\w+)\\s*-->', input, re.IGNORECASE)\n\ncurrent_phase = phase_match.group(1)\
|
||||||
|
\ if phase_match else \"initial_feedback\"\ntemplate_name = template_match.group(1)\
|
||||||
|
\ if template_match else \"feature\"\n\ntemplate_path = os.path.join(templates_dir,\
|
||||||
|
\ template_name + \".yaml\")\nphase_goal = \"Provide frontend feedback\"\nphase_instructions\
|
||||||
|
\ = \"Review the proposal for frontend implementation concerns.\"\n\nif os.path.exists(template_path):\n\
|
||||||
|
\ import yaml\n with open(template_path, 'r') as f:\n template =\
|
||||||
|
\ yaml.safe_load(f)\n phases = template.get(\"phases\", {})\n phase_info\
|
||||||
|
\ = phases.get(current_phase, {})\n phase_goal = phase_info.get(\"goal\", phase_goal)\n\
|
||||||
|
\ phase_instructions = phase_info.get(\"instructions\", phase_instructions)\n\
|
||||||
|
\nphase_context = \"Current Phase: \" + current_phase + \"\\n\"\nphase_context\
|
||||||
|
\ += \"Phase Goal: \" + phase_goal + \"\\n\"\nphase_context += \"Phase Instructions:\\\
|
||||||
|
n\" + phase_instructions\n"
|
||||||
|
output_var: phase_context, current_phase
|
||||||
|
- type: code
|
||||||
|
code: "import re\nimport os\n\ntitle_match = re.search(r'<!--\\s*Title:\\s*(.+?)\\\
|
||||||
|
s*-->', input)\ndiscussion_name = \"discussion\"\nif title_match:\n discussion_name\
|
||||||
|
\ = title_match.group(1).strip().lower()\n discussion_name = re.sub(r'[^a-z0-9]+',\
|
||||||
|
\ '-', discussion_name)\n\nos.makedirs(diagrams_dir, exist_ok=True)\n\nexisting\
|
||||||
|
\ = []\nif os.path.exists(diagrams_dir):\n for f in os.listdir(diagrams_dir):\n\
|
||||||
|
\ if f.startswith(discussion_name):\n existing.append(f)\n\n\
|
||||||
|
next_num = len(existing) + 1\ndiagram_path = diagrams_dir + \"/\" + discussion_name\
|
||||||
|
\ + \"_frontend_\" + str(next_num) + \".puml\"\n"
|
||||||
|
output_var: diagram_path
|
||||||
|
- type: code
|
||||||
|
code: "import sys\nimport datetime as dt\ntimestamp = dt.datetime.now().strftime(\"\
|
||||||
|
%H:%M:%S\")\nfor msg in [f\"Phase: {current_phase}\", \"Calling AI provider...\"\
|
||||||
|
]:\n line = f\"[{timestamp}] [frontend] {msg}\"\n print(line, file=sys.stderr)\n\
|
||||||
|
\ sys.stderr.flush()\n if log_file:\n with open(log_file, 'a') as\
|
||||||
|
\ f:\n f.write(line + \"\\n\")\n f.flush()\n"
|
||||||
|
output_var: _progress1
|
||||||
|
- type: prompt
|
||||||
|
prompt: "You are AI-Frontend (also known as Fiona), a frontend development specialist\
|
||||||
|
\ who\nbuilds performant, accessible, and maintainable user interfaces.\n\n##\
|
||||||
|
\ Your Role\n- Evaluate frontend architecture and component design\n- Consider\
|
||||||
|
\ state management and data flow\n- Ensure responsive and accessible implementations\n\
|
||||||
|
- Optimize for performance and bundle size\n- Apply modern frontend best practices\n\
|
||||||
|
\n## Your Perspective\n- Components should be composable and reusable\n- Performance\
|
||||||
|
\ matters - every millisecond counts\n- CSS is code - it needs architecture too\n\
|
||||||
|
- Progressive enhancement over graceful degradation\n- Don't fight the browser\
|
||||||
|
\ - work with it\n\n## Frontend Checklist\n- Component hierarchy and data flow\n\
|
||||||
|
- State management approach\n- CSS strategy (modules, styled-components, etc.)\n\
|
||||||
|
- Bundle size impact\n- Browser compatibility\n- Mobile/responsive behavior\n\
|
||||||
|
- Loading and error states\n- Accessibility (keyboard, screen readers)\n\n## Phase\
|
||||||
|
\ Context\n{phase_context}\n\n## Diagrams\nWhen creating component diagrams, include\
|
||||||
|
\ a reference marker.\nDiagram path to use: {diagram_path}\n\nIMPORTANT: When\
|
||||||
|
\ you create a diagram, your comment MUST include:\nDIAGRAM: {diagram_path}\n\n\
|
||||||
|
## Current Discussion\n{input}\n\n## Your Task\n{callout}\n\nFollow the phase\
|
||||||
|
\ instructions. Analyze from a frontend development perspective.\n\n## Response\
|
||||||
|
\ Format\nRespond with valid JSON only. Use \\n for newlines in strings:\n{{\n\
|
||||||
|
\ \"comment\": \"Your frontend analysis...\\n\\nDIAGRAM: path/file.puml (if created)\"\
|
||||||
|
,\n \"vote\": \"READY\" or \"CHANGES\" or \"REJECT\" or null,\n \"diagram\"\
|
||||||
|
: \"@startuml\\n...\\n@enduml\"\n}}\n\nVote meanings:\n- READY: Frontend implementation\
|
||||||
|
\ is solid\n- CHANGES: Frontend improvements needed\n- REJECT: Significant frontend\
|
||||||
|
\ issues\n- null: Comment only, no vote change\n\nIf you have nothing meaningful\
|
||||||
|
\ to add, respond: {{\"sentinel\": \"NO_RESPONSE\"}}\n"
|
||||||
|
provider: opencode-pickle
|
||||||
|
output_var: response
|
||||||
|
- type: code
|
||||||
|
code: "import sys\nimport datetime as dt\ntimestamp = dt.datetime.now().strftime(\"\
|
||||||
|
%H:%M:%S\")\nline = f\"[{timestamp}] [frontend] AI response received\"\nprint(line,\
|
||||||
|
\ file=sys.stderr)\nsys.stderr.flush()\nif log_file:\n with open(log_file,\
|
||||||
|
\ 'a') as f:\n f.write(line + \"\\n\")\n f.flush()\n"
|
||||||
|
output_var: _progress2
|
||||||
|
- type: code
|
||||||
|
code: "import re\njson_text = response.strip()\nif json_text.startswith('```'):\n\
|
||||||
|
\ code_block = re.search(r'```(?:json)?\\s*(\\{.*\\})\\s*```', json_text, re.DOTALL)\n\
|
||||||
|
\ if code_block:\n json_text = code_block.group(1).strip()\n"
|
||||||
|
output_var: json_text
|
||||||
|
- type: code
|
||||||
|
code: "import json\ntry:\n parsed = json.loads(json_text)\nexcept json.JSONDecodeError\
|
||||||
|
\ as e:\n fixed = json_text.replace('\\n', '\\\\n')\n try:\n parsed\
|
||||||
|
\ = json.loads(fixed)\n except json.JSONDecodeError:\n import re\n \
|
||||||
|
\ comment_match = re.search(r'\"comment\"\\s*:\\s*\"(.*?)\"(?=\\s*[,}])',\
|
||||||
|
\ json_text, re.DOTALL)\n vote_match = re.search(r'\"vote\"\\s*:\\s*(\"\
|
||||||
|
?\\w+\"?|null)', json_text)\n diagram_match = re.search(r'\"diagram\"\\\
|
||||||
|
s*:\\s*\"(.*?)\"(?=\\s*[,}])', json_text, re.DOTALL)\n parsed = {\n \
|
||||||
|
\ \"comment\": comment_match.group(1).replace('\\n', ' ') if comment_match\
|
||||||
|
\ else \"Parse error\",\n \"vote\": vote_match.group(1).strip('\"')\
|
||||||
|
\ if vote_match else None,\n \"diagram\": diagram_match.group(1) if\
|
||||||
|
\ diagram_match else None\n }\n if parsed[\"vote\"] == \"null\"\
|
||||||
|
:\n parsed[\"vote\"] = None\ncomment = parsed.get(\"comment\", \"\"\
|
||||||
|
)\nvote = parsed.get(\"vote\")\ndiagram_content = parsed.get(\"diagram\")\nhas_diagram\
|
||||||
|
\ = \"true\" if diagram_content else \"false\"\n"
|
||||||
|
output_var: comment, vote, diagram_content, has_diagram
|
||||||
|
- type: code
|
||||||
|
code: "if has_diagram == \"true\" and diagram_content:\n with open(diagram_path,\
|
||||||
|
\ 'w') as f:\n f.write(diagram_content)\n saved_diagram = diagram_path\n\
|
||||||
|
else:\n saved_diagram = \"\"\n"
|
||||||
|
output_var: saved_diagram
|
||||||
|
- type: code
|
||||||
|
code: "import json\nresult = {\"comment\": comment, \"vote\": vote}\nif saved_diagram:\n\
|
||||||
|
\ result[\"diagram_file\"] = saved_diagram\nfinal_response = json.dumps(result)\n"
|
||||||
|
output_var: final_response
|
||||||
|
output: '{final_response}'
|
||||||
|
|
@ -0,0 +1,126 @@
|
||||||
|
name: discussion-performance
|
||||||
|
description: Performance optimization specialist participant for discussions
|
||||||
|
category: Discussion
|
||||||
|
meta:
|
||||||
|
display_name: AI-Performance
|
||||||
|
alias: performance
|
||||||
|
type: voting
|
||||||
|
expertise:
|
||||||
|
- Performance profiling
|
||||||
|
- Algorithm optimization
|
||||||
|
- Caching strategies
|
||||||
|
- Database optimization
|
||||||
|
- Memory management
|
||||||
|
- Load testing
|
||||||
|
- Scalability patterns
|
||||||
|
concerns:
|
||||||
|
- What's the time complexity?
|
||||||
|
- Where are the bottlenecks?
|
||||||
|
- How does this scale under load?
|
||||||
|
- Are we using resources efficiently?
|
||||||
|
voice: en-US-Neural2-J
|
||||||
|
provider: opencode-reasoner
|
||||||
|
color:
|
||||||
|
- 255
|
||||||
|
- 220
|
||||||
|
- 100
|
||||||
|
arguments:
|
||||||
|
- flag: --callout
|
||||||
|
variable: callout
|
||||||
|
default: ''
|
||||||
|
description: Specific question or @mention context
|
||||||
|
- flag: --templates-dir
|
||||||
|
variable: templates_dir
|
||||||
|
default: templates
|
||||||
|
description: Path to templates directory
|
||||||
|
- flag: --diagrams-dir
|
||||||
|
variable: diagrams_dir
|
||||||
|
default: diagrams
|
||||||
|
description: Path to save diagrams
|
||||||
|
- flag: --log-file
|
||||||
|
variable: log_file
|
||||||
|
default: ''
|
||||||
|
description: Path to log file for progress updates
|
||||||
|
steps:
|
||||||
|
- type: code
|
||||||
|
code: "import re\nimport os\n\nphase_match = re.search(r'<!--\\s*Phase:\\s*(\\w+)\\\
|
||||||
|
s*-->', input, re.IGNORECASE)\ntemplate_match = re.search(r'<!--\\s*Template:\\\
|
||||||
|
s*(\\w+)\\s*-->', input, re.IGNORECASE)\n\ncurrent_phase = phase_match.group(1)\
|
||||||
|
\ if phase_match else \"initial_feedback\"\ntemplate_name = template_match.group(1)\
|
||||||
|
\ if template_match else \"feature\"\n\ntemplate_path = os.path.join(templates_dir,\
|
||||||
|
\ template_name + \".yaml\")\nphase_goal = \"Provide performance feedback\"\n\
|
||||||
|
phase_instructions = \"Review the proposal for performance and scalability concerns.\"\
|
||||||
|
\n\nif os.path.exists(template_path):\n import yaml\n with open(template_path,\
|
||||||
|
\ 'r') as f:\n template = yaml.safe_load(f)\n phases = template.get(\"\
|
||||||
|
phases\", {})\n phase_info = phases.get(current_phase, {})\n phase_goal\
|
||||||
|
\ = phase_info.get(\"goal\", phase_goal)\n phase_instructions = phase_info.get(\"\
|
||||||
|
instructions\", phase_instructions)\n\nphase_context = \"Current Phase: \" + current_phase\
|
||||||
|
\ + \"\\n\"\nphase_context += \"Phase Goal: \" + phase_goal + \"\\n\"\nphase_context\
|
||||||
|
\ += \"Phase Instructions:\\n\" + phase_instructions\n"
|
||||||
|
output_var: phase_context, current_phase
|
||||||
|
- type: code
|
||||||
|
code: "import sys\nimport datetime as dt\ntimestamp = dt.datetime.now().strftime(\"\
|
||||||
|
%H:%M:%S\")\nfor msg in [f\"Phase: {current_phase}\", \"Calling AI provider...\"\
|
||||||
|
]:\n line = f\"[{timestamp}] [performance] {msg}\"\n print(line, file=sys.stderr)\n\
|
||||||
|
\ sys.stderr.flush()\n if log_file:\n with open(log_file, 'a') as\
|
||||||
|
\ f:\n f.write(line + \"\\n\")\n f.flush()\n"
|
||||||
|
output_var: _progress1
|
||||||
|
- type: prompt
|
||||||
|
prompt: "You are AI-Performance (also known as Perry), a performance optimization\
|
||||||
|
\ specialist\nwho ensures systems are fast, efficient, and scalable.\n\n## Your\
|
||||||
|
\ Role\n- Identify potential performance bottlenecks\n- Evaluate algorithmic efficiency\
|
||||||
|
\ and complexity\n- Recommend caching and optimization strategies\n- Consider\
|
||||||
|
\ resource utilization and cost\n- Plan for scale and load testing\n\n## Your\
|
||||||
|
\ Perspective\n- Premature optimization is the root of all evil, but known bottlenecks\
|
||||||
|
\ must be addressed\n- Measure first, optimize second\n- O(n) vs O(n^2) matters\
|
||||||
|
\ more at scale\n- Memory and CPU have different optimization strategies\n- The\
|
||||||
|
\ fastest code is code that doesn't run\n\n## Performance Checklist\n- Time complexity\
|
||||||
|
\ of algorithms\n- Space complexity and memory usage\n- Database query efficiency\
|
||||||
|
\ (indexes, joins)\n- Network round trips\n- Caching opportunities\n- Batch vs\
|
||||||
|
\ real-time processing\n- Concurrency and parallelization\n- Resource pooling\
|
||||||
|
\ and reuse\n\n## Phase Context\n{phase_context}\n\n## Current Discussion\n{input}\n\
|
||||||
|
\n## Your Task\n{callout}\n\nFollow the phase instructions. Analyze from a performance\
|
||||||
|
\ and scalability perspective.\nIdentify bottlenecks, suggest optimizations, and\
|
||||||
|
\ consider scaling implications.\n\n## Response Format\nRespond with valid JSON\
|
||||||
|
\ only. Use \\n for newlines in strings:\n{{\n \"comment\": \"Your performance\
|
||||||
|
\ analysis...\\n\\nOptimization opportunities:\\n1. ...\\n2. ...\",\n \"vote\"\
|
||||||
|
: \"READY\" or \"CHANGES\" or \"REJECT\" or null,\n \"diagram\": null\n}}\n\n\
|
||||||
|
Vote meanings:\n- READY: Performance is acceptable\n- CHANGES: Performance improvements\
|
||||||
|
\ needed\n- REJECT: Significant performance issues\n- null: Comment only, no vote\
|
||||||
|
\ change\n\nIf you have nothing meaningful to add, respond: {{\"sentinel\": \"\
|
||||||
|
NO_RESPONSE\"}}\n"
|
||||||
|
provider: opencode-reasoner
|
||||||
|
output_var: response
|
||||||
|
- type: code
|
||||||
|
code: "import sys\nimport datetime as dt\ntimestamp = dt.datetime.now().strftime(\"\
|
||||||
|
%H:%M:%S\")\nline = f\"[{timestamp}] [performance] AI response received\"\nprint(line,\
|
||||||
|
\ file=sys.stderr)\nsys.stderr.flush()\nif log_file:\n with open(log_file,\
|
||||||
|
\ 'a') as f:\n f.write(line + \"\\n\")\n f.flush()\n"
|
||||||
|
output_var: _progress2
|
||||||
|
- type: code
|
||||||
|
code: "import re\njson_text = response.strip()\nif json_text.startswith('```'):\n\
|
||||||
|
\ code_block = re.search(r'```(?:json)?\\s*(\\{.*\\})\\s*```', json_text, re.DOTALL)\n\
|
||||||
|
\ if code_block:\n json_text = code_block.group(1).strip()\n"
|
||||||
|
output_var: json_text
|
||||||
|
- type: code
|
||||||
|
code: "import json\ntry:\n parsed = json.loads(json_text)\nexcept json.JSONDecodeError\
|
||||||
|
\ as e:\n fixed = json_text.replace('\\n', '\\\\n')\n try:\n parsed\
|
||||||
|
\ = json.loads(fixed)\n except json.JSONDecodeError:\n import re\n \
|
||||||
|
\ comment_match = re.search(r'\"comment\"\\s*:\\s*\"(.*?)\"(?=\\s*[,}])',\
|
||||||
|
\ json_text, re.DOTALL)\n vote_match = re.search(r'\"vote\"\\s*:\\s*(\"\
|
||||||
|
?\\w+\"?|null)', json_text)\n parsed = {\n \"comment\": comment_match.group(1).replace('\\\
|
||||||
|
n', ' ') if comment_match else \"Parse error\",\n \"vote\": vote_match.group(1).strip('\"\
|
||||||
|
') if vote_match else None\n }\n if parsed[\"vote\"] == \"null\"\
|
||||||
|
:\n parsed[\"vote\"] = None\ncomment = parsed.get(\"comment\", \"\"\
|
||||||
|
)\nvote = parsed.get(\"vote\")\n"
|
||||||
|
output_var: comment, vote
|
||||||
|
- type: code
|
||||||
|
code: 'import json
|
||||||
|
|
||||||
|
result = {"comment": comment, "vote": vote}
|
||||||
|
|
||||||
|
final_response = json.dumps(result)
|
||||||
|
|
||||||
|
'
|
||||||
|
output_var: final_response
|
||||||
|
output: '{final_response}'
|
||||||
|
|
@ -0,0 +1,135 @@
|
||||||
|
name: discussion-qa
|
||||||
|
description: Quality assurance specialist participant for discussions
|
||||||
|
category: Discussion
|
||||||
|
meta:
|
||||||
|
display_name: AI-QA
|
||||||
|
alias: qa
|
||||||
|
type: voting
|
||||||
|
expertise:
|
||||||
|
- Test strategy
|
||||||
|
- Edge case identification
|
||||||
|
- Regression testing
|
||||||
|
- Error handling
|
||||||
|
- Quality metrics
|
||||||
|
- Bug prevention
|
||||||
|
- Test automation
|
||||||
|
concerns:
|
||||||
|
- What could go wrong?
|
||||||
|
- How do we test this?
|
||||||
|
- What are the edge cases?
|
||||||
|
- Is error handling sufficient?
|
||||||
|
voice: en-US-Neural2-D
|
||||||
|
provider: gemini
|
||||||
|
color:
|
||||||
|
- 180
|
||||||
|
- 255
|
||||||
|
- 100
|
||||||
|
arguments:
|
||||||
|
- flag: --callout
|
||||||
|
variable: callout
|
||||||
|
default: ''
|
||||||
|
description: Specific question or @mention context
|
||||||
|
- flag: --templates-dir
|
||||||
|
variable: templates_dir
|
||||||
|
default: templates
|
||||||
|
description: Path to templates directory
|
||||||
|
- flag: --diagrams-dir
|
||||||
|
variable: diagrams_dir
|
||||||
|
default: diagrams
|
||||||
|
description: Path to save diagrams
|
||||||
|
- flag: --log-file
|
||||||
|
variable: log_file
|
||||||
|
default: ''
|
||||||
|
description: Path to log file for progress updates
|
||||||
|
steps:
|
||||||
|
- type: code
|
||||||
|
code: "import re\nimport os\n\nphase_match = re.search(r'<!--\\s*Phase:\\s*(\\w+)\\\
|
||||||
|
s*-->', input, re.IGNORECASE)\ntemplate_match = re.search(r'<!--\\s*Template:\\\
|
||||||
|
s*(\\w+)\\s*-->', input, re.IGNORECASE)\n\ncurrent_phase = phase_match.group(1)\
|
||||||
|
\ if phase_match else \"initial_feedback\"\ntemplate_name = template_match.group(1)\
|
||||||
|
\ if template_match else \"feature\"\n\ntemplate_path = os.path.join(templates_dir,\
|
||||||
|
\ template_name + \".yaml\")\nphase_goal = \"Provide QA feedback\"\nphase_instructions\
|
||||||
|
\ = \"Review the proposal for testability and quality concerns.\"\n\nif os.path.exists(template_path):\n\
|
||||||
|
\ import yaml\n with open(template_path, 'r') as f:\n template =\
|
||||||
|
\ yaml.safe_load(f)\n phases = template.get(\"phases\", {})\n phase_info\
|
||||||
|
\ = phases.get(current_phase, {})\n phase_goal = phase_info.get(\"goal\", phase_goal)\n\
|
||||||
|
\ phase_instructions = phase_info.get(\"instructions\", phase_instructions)\n\
|
||||||
|
\nphase_context = \"Current Phase: \" + current_phase + \"\\n\"\nphase_context\
|
||||||
|
\ += \"Phase Goal: \" + phase_goal + \"\\n\"\nphase_context += \"Phase Instructions:\\\
|
||||||
|
n\" + phase_instructions\n"
|
||||||
|
output_var: phase_context, current_phase
|
||||||
|
- type: code
|
||||||
|
code: "import re\nimport os\n\ntitle_match = re.search(r'<!--\\s*Title:\\s*(.+?)\\\
|
||||||
|
s*-->', input)\ndiscussion_name = \"discussion\"\nif title_match:\n discussion_name\
|
||||||
|
\ = title_match.group(1).strip().lower()\n discussion_name = re.sub(r'[^a-z0-9]+',\
|
||||||
|
\ '-', discussion_name)\n\nos.makedirs(diagrams_dir, exist_ok=True)\n\nexisting\
|
||||||
|
\ = []\nif os.path.exists(diagrams_dir):\n for f in os.listdir(diagrams_dir):\n\
|
||||||
|
\ if f.startswith(discussion_name):\n existing.append(f)\n\n\
|
||||||
|
next_num = len(existing) + 1\ndiagram_path = diagrams_dir + \"/\" + discussion_name\
|
||||||
|
\ + \"_qa_\" + str(next_num) + \".puml\"\n"
|
||||||
|
output_var: diagram_path
|
||||||
|
- type: code
|
||||||
|
code: "import sys\nimport datetime as dt\ntimestamp = dt.datetime.now().strftime(\"\
|
||||||
|
%H:%M:%S\")\nfor msg in [f\"Phase: {current_phase}\", \"Calling AI provider...\"\
|
||||||
|
]:\n line = f\"[{timestamp}] [qa] {msg}\"\n print(line, file=sys.stderr)\n\
|
||||||
|
\ sys.stderr.flush()\n if log_file:\n with open(log_file, 'a') as\
|
||||||
|
\ f:\n f.write(line + \"\\n\")\n f.flush()\n"
|
||||||
|
output_var: _progress1
|
||||||
|
- type: prompt
|
||||||
|
prompt: "You are AI-QA (also known as Quinn), a quality assurance specialist who\
|
||||||
|
\ ensures\nsoftware is reliable, well-tested, and handles edge cases gracefully.\n\
|
||||||
|
\n## Your Role\n- Identify potential bugs and edge cases before they happen\n\
|
||||||
|
- Design comprehensive test strategies\n- Evaluate error handling and failure\
|
||||||
|
\ modes\n- Ensure testability of proposed implementations\n- Think about what\
|
||||||
|
\ could go wrong\n\n## Your Perspective\n- If it can break, it will break - in\
|
||||||
|
\ production, at 3 AM\n- Edge cases are where most bugs hide\n- Good error messages\
|
||||||
|
\ save hours of debugging\n- Tests are documentation that never goes stale\n-\
|
||||||
|
\ Prevention is cheaper than debugging\n\n## QA Checklist\n- Happy path testing\n\
|
||||||
|
- Error/exception handling\n- Boundary conditions (empty, null, max values)\n\
|
||||||
|
- Concurrency and race conditions\n- Integration points and failure modes\n- Rollback\
|
||||||
|
\ and recovery scenarios\n- Data validation and sanitization\n- Performance under\
|
||||||
|
\ load\n\n## Phase Context\n{phase_context}\n\n## Current Discussion\n{input}\n\
|
||||||
|
\n## Your Task\n{callout}\n\nFollow the phase instructions. Analyze from a quality\
|
||||||
|
\ assurance perspective.\nIdentify edge cases, failure modes, and testing requirements.\n\
|
||||||
|
\n## Response Format\nRespond with valid JSON only. Use \\n for newlines in strings:\n\
|
||||||
|
{{\n \"comment\": \"Your QA analysis...\\n\\nTest cases:\\n1. ...\\n2. ...\"\
|
||||||
|
,\n \"vote\": \"READY\" or \"CHANGES\" or \"REJECT\" or null,\n \"diagram\"\
|
||||||
|
: null\n}}\n\nVote meanings:\n- READY: Quality is assured, testable\n- CHANGES:\
|
||||||
|
\ Testing/quality improvements needed\n- REJECT: Untestable or high-risk implementation\n\
|
||||||
|
- null: Comment only, no vote change\n\nIf you have nothing meaningful to add,\
|
||||||
|
\ respond: {{\"sentinel\": \"NO_RESPONSE\"}}\n"
|
||||||
|
provider: gemini
|
||||||
|
output_var: response
|
||||||
|
- type: code
|
||||||
|
code: "import sys\nimport datetime as dt\ntimestamp = dt.datetime.now().strftime(\"\
|
||||||
|
%H:%M:%S\")\nline = f\"[{timestamp}] [qa] AI response received\"\nprint(line,\
|
||||||
|
\ file=sys.stderr)\nsys.stderr.flush()\nif log_file:\n with open(log_file,\
|
||||||
|
\ 'a') as f:\n f.write(line + \"\\n\")\n f.flush()\n"
|
||||||
|
output_var: _progress2
|
||||||
|
- type: code
|
||||||
|
code: "import re\njson_text = response.strip()\nif json_text.startswith('```'):\n\
|
||||||
|
\ code_block = re.search(r'```(?:json)?\\s*(\\{.*\\})\\s*```', json_text, re.DOTALL)\n\
|
||||||
|
\ if code_block:\n json_text = code_block.group(1).strip()\n"
|
||||||
|
output_var: json_text
|
||||||
|
- type: code
|
||||||
|
code: "import json\ntry:\n parsed = json.loads(json_text)\nexcept json.JSONDecodeError\
|
||||||
|
\ as e:\n fixed = json_text.replace('\\n', '\\\\n')\n try:\n parsed\
|
||||||
|
\ = json.loads(fixed)\n except json.JSONDecodeError:\n import re\n \
|
||||||
|
\ comment_match = re.search(r'\"comment\"\\s*:\\s*\"(.*?)\"(?=\\s*[,}])',\
|
||||||
|
\ json_text, re.DOTALL)\n vote_match = re.search(r'\"vote\"\\s*:\\s*(\"\
|
||||||
|
?\\w+\"?|null)', json_text)\n parsed = {\n \"comment\": comment_match.group(1).replace('\\\
|
||||||
|
n', ' ') if comment_match else \"Parse error\",\n \"vote\": vote_match.group(1).strip('\"\
|
||||||
|
') if vote_match else None\n }\n if parsed[\"vote\"] == \"null\"\
|
||||||
|
:\n parsed[\"vote\"] = None\ncomment = parsed.get(\"comment\", \"\"\
|
||||||
|
)\nvote = parsed.get(\"vote\")\n"
|
||||||
|
output_var: comment, vote
|
||||||
|
- type: code
|
||||||
|
code: 'import json
|
||||||
|
|
||||||
|
result = {"comment": comment, "vote": vote}
|
||||||
|
|
||||||
|
final_response = json.dumps(result)
|
||||||
|
|
||||||
|
'
|
||||||
|
output_var: final_response
|
||||||
|
output: '{final_response}'
|
||||||
|
|
@ -0,0 +1,141 @@
|
||||||
|
name: discussion-ux
|
||||||
|
description: User experience specialist participant for discussions
|
||||||
|
category: Discussion
|
||||||
|
meta:
|
||||||
|
display_name: AI-UX
|
||||||
|
alias: ux
|
||||||
|
type: voting
|
||||||
|
expertise:
|
||||||
|
- User research
|
||||||
|
- Usability testing
|
||||||
|
- User flows
|
||||||
|
- Information architecture
|
||||||
|
- Accessibility (WCAG)
|
||||||
|
- Interaction design
|
||||||
|
- User journey mapping
|
||||||
|
concerns:
|
||||||
|
- Is this intuitive for users?
|
||||||
|
- What's the cognitive load?
|
||||||
|
- Are we meeting accessibility standards?
|
||||||
|
- What user problems are we solving?
|
||||||
|
voice: en-AU-Neural2-A
|
||||||
|
provider: gemini-flash
|
||||||
|
color:
|
||||||
|
- 100
|
||||||
|
- 220
|
||||||
|
- 200
|
||||||
|
arguments:
|
||||||
|
- flag: --callout
|
||||||
|
variable: callout
|
||||||
|
default: ''
|
||||||
|
description: Specific question or @mention context
|
||||||
|
- flag: --templates-dir
|
||||||
|
variable: templates_dir
|
||||||
|
default: templates
|
||||||
|
description: Path to templates directory
|
||||||
|
- flag: --diagrams-dir
|
||||||
|
variable: diagrams_dir
|
||||||
|
default: diagrams
|
||||||
|
description: Path to save diagrams
|
||||||
|
- flag: --log-file
|
||||||
|
variable: log_file
|
||||||
|
default: ''
|
||||||
|
description: Path to log file for progress updates
|
||||||
|
steps:
|
||||||
|
- type: code
|
||||||
|
code: "import re\nimport os\n\nphase_match = re.search(r'<!--\\s*Phase:\\s*(\\w+)\\\
|
||||||
|
s*-->', input, re.IGNORECASE)\ntemplate_match = re.search(r'<!--\\s*Template:\\\
|
||||||
|
s*(\\w+)\\s*-->', input, re.IGNORECASE)\n\ncurrent_phase = phase_match.group(1)\
|
||||||
|
\ if phase_match else \"initial_feedback\"\ntemplate_name = template_match.group(1)\
|
||||||
|
\ if template_match else \"feature\"\n\ntemplate_path = os.path.join(templates_dir,\
|
||||||
|
\ template_name + \".yaml\")\nphase_goal = \"Provide UX feedback\"\nphase_instructions\
|
||||||
|
\ = \"Review the proposal for user experience concerns.\"\n\nif os.path.exists(template_path):\n\
|
||||||
|
\ import yaml\n with open(template_path, 'r') as f:\n template =\
|
||||||
|
\ yaml.safe_load(f)\n phases = template.get(\"phases\", {})\n phase_info\
|
||||||
|
\ = phases.get(current_phase, {})\n phase_goal = phase_info.get(\"goal\", phase_goal)\n\
|
||||||
|
\ phase_instructions = phase_info.get(\"instructions\", phase_instructions)\n\
|
||||||
|
\nphase_context = \"Current Phase: \" + current_phase + \"\\n\"\nphase_context\
|
||||||
|
\ += \"Phase Goal: \" + phase_goal + \"\\n\"\nphase_context += \"Phase Instructions:\\\
|
||||||
|
n\" + phase_instructions\n"
|
||||||
|
output_var: phase_context, current_phase
|
||||||
|
- type: code
|
||||||
|
code: "import re\nimport os\n\ntitle_match = re.search(r'<!--\\s*Title:\\s*(.+?)\\\
|
||||||
|
s*-->', input)\ndiscussion_name = \"discussion\"\nif title_match:\n discussion_name\
|
||||||
|
\ = title_match.group(1).strip().lower()\n discussion_name = re.sub(r'[^a-z0-9]+',\
|
||||||
|
\ '-', discussion_name)\n\nos.makedirs(diagrams_dir, exist_ok=True)\n\nexisting\
|
||||||
|
\ = []\nif os.path.exists(diagrams_dir):\n for f in os.listdir(diagrams_dir):\n\
|
||||||
|
\ if f.startswith(discussion_name):\n existing.append(f)\n\n\
|
||||||
|
next_num = len(existing) + 1\ndiagram_path = diagrams_dir + \"/\" + discussion_name\
|
||||||
|
\ + \"_ux_\" + str(next_num) + \".puml\"\n"
|
||||||
|
output_var: diagram_path
|
||||||
|
- type: code
|
||||||
|
code: "import sys\nimport datetime as dt\ntimestamp = dt.datetime.now().strftime(\"\
|
||||||
|
%H:%M:%S\")\nfor msg in [f\"Phase: {current_phase}\", \"Calling AI provider...\"\
|
||||||
|
]:\n line = f\"[{timestamp}] [ux] {msg}\"\n print(line, file=sys.stderr)\n\
|
||||||
|
\ sys.stderr.flush()\n if log_file:\n with open(log_file, 'a') as\
|
||||||
|
\ f:\n f.write(line + \"\\n\")\n f.flush()\n"
|
||||||
|
output_var: _progress1
|
||||||
|
- type: prompt
|
||||||
|
prompt: "You are AI-UX (also known as Uma), a user experience specialist who advocates\n\
|
||||||
|
for users and ensures products are intuitive, accessible, and delightful to use.\n\
|
||||||
|
\n## Your Role\n- Champion the user's perspective in all decisions\n- Evaluate\
|
||||||
|
\ usability and intuitiveness of proposals\n- Ensure accessibility compliance\
|
||||||
|
\ (WCAG 2.1)\n- Design user flows that minimize friction\n- Consider edge cases\
|
||||||
|
\ from the user's viewpoint\n\n## Your Perspective\n- Users don't read manuals\
|
||||||
|
\ - make it obvious\n- Every click/tap is a decision point that can lose users\n\
|
||||||
|
- Error states are part of the experience\n- Accessibility is not optional\n-\
|
||||||
|
\ Test assumptions with real user behavior\n\n## UX Checklist\n- User flow clarity\
|
||||||
|
\ (can users complete their goals?)\n- Error handling and recovery\n- Loading\
|
||||||
|
\ states and feedback\n- Keyboard navigation\n- Screen reader compatibility\n\
|
||||||
|
- Mobile/touch considerations\n- Onboarding and discoverability\n- Cognitive load\
|
||||||
|
\ assessment\n\n## Phase Context\n{phase_context}\n\n## Diagrams\nWhen creating\
|
||||||
|
\ user flow diagrams, include a reference marker.\nDiagram path to use: {diagram_path}\n\
|
||||||
|
\nIMPORTANT: When you create a diagram, your comment MUST include:\nDIAGRAM: {diagram_path}\n\
|
||||||
|
\n## Current Discussion\n{input}\n\n## Your Task\n{callout}\n\nFollow the phase\
|
||||||
|
\ instructions. Analyze from a user experience perspective.\n\n## Response Format\n\
|
||||||
|
Respond with valid JSON only. Use \\n for newlines in strings:\n{{\n \"comment\"\
|
||||||
|
: \"Your UX analysis...\\n\\nDIAGRAM: path/file.puml (if created)\",\n \"vote\"\
|
||||||
|
: \"READY\" or \"CHANGES\" or \"REJECT\" or null,\n \"diagram\": \"@startuml\\\
|
||||||
|
n...\\n@enduml\"\n}}\n\nVote meanings:\n- READY: Good user experience, accessible\n\
|
||||||
|
- CHANGES: UX improvements needed\n- REJECT: Significant usability issues\n- null:\
|
||||||
|
\ Comment only, no vote change\n\nIf you have nothing meaningful to add, respond:\
|
||||||
|
\ {{\"sentinel\": \"NO_RESPONSE\"}}\n"
|
||||||
|
provider: gemini-flash
|
||||||
|
output_var: response
|
||||||
|
- type: code
|
||||||
|
code: "import sys\nimport datetime as dt\ntimestamp = dt.datetime.now().strftime(\"\
|
||||||
|
%H:%M:%S\")\nline = f\"[{timestamp}] [ux] AI response received\"\nprint(line,\
|
||||||
|
\ file=sys.stderr)\nsys.stderr.flush()\nif log_file:\n with open(log_file,\
|
||||||
|
\ 'a') as f:\n f.write(line + \"\\n\")\n f.flush()\n"
|
||||||
|
output_var: _progress2
|
||||||
|
- type: code
|
||||||
|
code: "import re\njson_text = response.strip()\nif json_text.startswith('```'):\n\
|
||||||
|
\ code_block = re.search(r'```(?:json)?\\s*(\\{.*\\})\\s*```', json_text, re.DOTALL)\n\
|
||||||
|
\ if code_block:\n json_text = code_block.group(1).strip()\n"
|
||||||
|
output_var: json_text
|
||||||
|
- type: code
|
||||||
|
code: "import json\ntry:\n parsed = json.loads(json_text)\nexcept json.JSONDecodeError\
|
||||||
|
\ as e:\n fixed = json_text.replace('\\n', '\\\\n')\n try:\n parsed\
|
||||||
|
\ = json.loads(fixed)\n except json.JSONDecodeError:\n import re\n \
|
||||||
|
\ comment_match = re.search(r'\"comment\"\\s*:\\s*\"(.*?)\"(?=\\s*[,}])',\
|
||||||
|
\ json_text, re.DOTALL)\n vote_match = re.search(r'\"vote\"\\s*:\\s*(\"\
|
||||||
|
?\\w+\"?|null)', json_text)\n diagram_match = re.search(r'\"diagram\"\\\
|
||||||
|
s*:\\s*\"(.*?)\"(?=\\s*[,}])', json_text, re.DOTALL)\n parsed = {\n \
|
||||||
|
\ \"comment\": comment_match.group(1).replace('\\n', ' ') if comment_match\
|
||||||
|
\ else \"Parse error\",\n \"vote\": vote_match.group(1).strip('\"')\
|
||||||
|
\ if vote_match else None,\n \"diagram\": diagram_match.group(1) if\
|
||||||
|
\ diagram_match else None\n }\n if parsed[\"vote\"] == \"null\"\
|
||||||
|
:\n parsed[\"vote\"] = None\ncomment = parsed.get(\"comment\", \"\"\
|
||||||
|
)\nvote = parsed.get(\"vote\")\ndiagram_content = parsed.get(\"diagram\")\nhas_diagram\
|
||||||
|
\ = \"true\" if diagram_content else \"false\"\n"
|
||||||
|
output_var: comment, vote, diagram_content, has_diagram
|
||||||
|
- type: code
|
||||||
|
code: "if has_diagram == \"true\" and diagram_content:\n with open(diagram_path,\
|
||||||
|
\ 'w') as f:\n f.write(diagram_content)\n saved_diagram = diagram_path\n\
|
||||||
|
else:\n saved_diagram = \"\"\n"
|
||||||
|
output_var: saved_diagram
|
||||||
|
- type: code
|
||||||
|
code: "import json\nresult = {\"comment\": comment, \"vote\": vote}\nif saved_diagram:\n\
|
||||||
|
\ result[\"diagram_file\"] = saved_diagram\nfinal_response = json.dumps(result)\n"
|
||||||
|
output_var: final_response
|
||||||
|
output: '{final_response}'
|
||||||
Loading…
Reference in New Issue