From d238f26b4e536f01f861300e35e50e9f5bdc7350 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 19 Nov 2025 18:23:20 +0000 Subject: [PATCH 01/30] Initial plan From 504712822ca46ad0c937164a24dcd3d814789e5f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 19 Nov 2025 18:29:09 +0000 Subject: [PATCH 02/30] Add agentic task log demo with chat bubbles and execution phases Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com> --- .../json/agentic-task-log.idoc.json | 727 ++++++++++++++++++ 1 file changed, 727 insertions(+) create mode 100644 packages/web-deploy/json/agentic-task-log.idoc.json diff --git a/packages/web-deploy/json/agentic-task-log.idoc.json b/packages/web-deploy/json/agentic-task-log.idoc.json new file mode 100644 index 00000000..ef9b9825 --- /dev/null +++ b/packages/web-deploy/json/agentic-task-log.idoc.json @@ -0,0 +1,727 @@ +{ + "$schema": "../../../docs/schema/idoc_v1.json", + "title": "Agentic Task Execution Log", + "style": { + "css": [ + "body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; margin: 0; padding: 20px; background: #f5f7fa; max-width: 900px; margin: 0 auto; }", + "h1 { color: #2c3e50; margin-bottom: 30px; text-align: center; }", + ".chat-container { margin: 20px 0; }", + ".chat-bubble { display: flex; margin: 15px 0; animation: fadeIn 0.3s ease-in; }", + "@keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }", + ".bubble-user { justify-content: flex-end; }", + ".bubble-assistant { justify-content: flex-start; }", + ".bubble-content { max-width: 70%; padding: 12px 18px; border-radius: 18px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); position: relative; }", + ".bubble-user .bubble-content { background: #007bff; color: white; border-bottom-right-radius: 4px; }", + ".bubble-assistant .bubble-content { background: #e9ecef; color: #333; border-bottom-left-radius: 4px; }", + ".bubble-sender { font-size: 0.75em; font-weight: 600; margin-bottom: 4px; opacity: 0.8; }", + ".bubble-user .bubble-sender { text-align: right; color: #007bff; }", + ".bubble-assistant .bubble-sender { text-align: left; color: #6c757d; }", + ".bubble-text { margin: 0; line-height: 1.4; word-wrap: break-word; }", + ".execution-log { background: #1e1e1e; color: #d4d4d4; padding: 20px; border-radius: 8px; margin: 25px 0; font-family: 'Consolas', 'Monaco', 'Courier New', monospace; font-size: 0.9em; box-shadow: 0 4px 8px rgba(0,0,0,0.2); }", + ".execution-log h3 { color: #4fc3f7; margin: 0 0 15px 0; font-size: 1.1em; font-weight: 600; border-bottom: 1px solid #333; padding-bottom: 8px; }", + ".log-entry { margin: 8px 0; padding: 6px 0; }", + ".log-timestamp { color: #858585; font-size: 0.85em; }", + ".log-level-info { color: #4fc3f7; }", + ".log-level-success { color: #66bb6a; }", + ".log-level-warning { color: #ffa726; }", + ".log-level-error { color: #ef5350; }", + ".log-message { margin-left: 12px; }", + ".phase-indicator { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 15px 20px; border-radius: 8px; margin: 30px 0; text-align: center; font-weight: 600; box-shadow: 0 3px 6px rgba(0,0,0,0.15); }", + ".status-badge { display: inline-block; padding: 4px 12px; border-radius: 12px; font-size: 0.85em; font-weight: 600; margin-left: 10px; }", + ".status-running { background: #fff3cd; color: #856404; }", + ".status-completed { background: #d4edda; color: #155724; }", + ".summary-box { background: white; border-left: 4px solid #667eea; padding: 20px; margin: 25px 0; border-radius: 4px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }", + ".summary-box h3 { margin: 0 0 15px 0; color: #667eea; }", + ".summary-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 15px; margin-top: 15px; }", + ".stat-item { text-align: center; padding: 10px; background: #f8f9fa; border-radius: 4px; }", + ".stat-value { font-size: 1.8em; font-weight: bold; color: #667eea; }", + ".stat-label { font-size: 0.9em; color: #6c757d; margin-top: 5px; }" + ] + }, + "variables": [ + { + "variableId": "chatMessages", + "type": "object", + "isArray": true, + "initialValue": [ + { + "sender": "User", + "type": "user", + "message": "Please analyze the sales data from Q4 and generate a summary report with visualizations." + }, + { + "sender": "Assistant", + "type": "assistant", + "message": "I'll help you analyze the Q4 sales data. Let me start by loading and examining the data structure." + } + ] + }, + { + "variableId": "executionLogs1", + "type": "object", + "isArray": true, + "initialValue": [ + { + "timestamp": "2024-11-19 10:15:23", + "level": "info", + "message": "Starting data analysis task..." + }, + { + "timestamp": "2024-11-19 10:15:24", + "level": "info", + "message": "Loading dataset: sales_q4_2024.csv" + }, + { + "timestamp": "2024-11-19 10:15:26", + "level": "success", + "message": "Dataset loaded successfully (15,234 rows, 12 columns)" + }, + { + "timestamp": "2024-11-19 10:15:27", + "level": "info", + "message": "Performing data validation and cleaning..." + }, + { + "timestamp": "2024-11-19 10:15:29", + "level": "success", + "message": "Data validation complete. No missing values detected." + } + ] + }, + { + "variableId": "chatMessages2", + "type": "object", + "isArray": true, + "initialValue": [ + { + "sender": "Assistant", + "type": "assistant", + "message": "I've successfully loaded the Q4 sales data. The dataset contains 15,234 transactions across 12 columns. Now I'll perform statistical analysis and identify key trends." + }, + { + "sender": "User", + "type": "user", + "message": "Great! Can you also break down the performance by region?" + } + ] + }, + { + "variableId": "executionLogs2", + "type": "object", + "isArray": true, + "initialValue": [ + { + "timestamp": "2024-11-19 10:16:05", + "level": "info", + "message": "Computing aggregate statistics..." + }, + { + "timestamp": "2024-11-19 10:16:07", + "level": "info", + "message": "Grouping data by region: North, South, East, West" + }, + { + "timestamp": "2024-11-19 10:16:09", + "level": "success", + "message": "Regional analysis complete" + }, + { + "timestamp": "2024-11-19 10:16:10", + "level": "info", + "message": "Generating revenue trends by month..." + }, + { + "timestamp": "2024-11-19 10:16:13", + "level": "success", + "message": "Trend analysis complete" + }, + { + "timestamp": "2024-11-19 10:16:14", + "level": "info", + "message": "Creating visualizations..." + }, + { + "timestamp": "2024-11-19 10:16:18", + "level": "success", + "message": "Generated 3 charts: revenue_by_region.png, monthly_trends.png, top_products.png" + } + ] + }, + { + "variableId": "chatMessages3", + "type": "object", + "isArray": true, + "initialValue": [ + { + "sender": "Assistant", + "type": "assistant", + "message": "Analysis complete! Here are the key findings:\n\n• Total Q4 Revenue: $4.2M (+18% vs Q3)\n• Best performing region: West ($1.3M)\n• Top product category: Electronics (42% of sales)\n• Peak sales month: December\n\nI've generated visualizations for each insight. Would you like me to create the summary report now?" + }, + { + "sender": "User", + "type": "user", + "message": "Yes, please generate the report in PDF format." + } + ] + }, + { + "variableId": "executionLogs3", + "type": "object", + "isArray": true, + "initialValue": [ + { + "timestamp": "2024-11-19 10:17:30", + "level": "info", + "message": "Initiating report generation..." + }, + { + "timestamp": "2024-11-19 10:17:31", + "level": "info", + "message": "Compiling data summaries and insights..." + }, + { + "timestamp": "2024-11-19 10:17:33", + "level": "info", + "message": "Embedding visualizations into report template..." + }, + { + "timestamp": "2024-11-19 10:17:38", + "level": "info", + "message": "Rendering report to PDF format..." + }, + { + "timestamp": "2024-11-19 10:17:42", + "level": "success", + "message": "Report generated successfully: Q4_Sales_Report_2024.pdf (2.4 MB)" + }, + { + "timestamp": "2024-11-19 10:17:43", + "level": "success", + "message": "Task completed in 4 minutes 20 seconds" + } + ] + }, + { + "variableId": "chatMessages4", + "type": "object", + "isArray": true, + "initialValue": [ + { + "sender": "Assistant", + "type": "assistant", + "message": "Perfect! I've generated the comprehensive Q4 Sales Report in PDF format. The report includes all the visualizations, regional breakdowns, and trend analysis. The file is ready for download: Q4_Sales_Report_2024.pdf" + }, + { + "sender": "User", + "type": "user", + "message": "Excellent work! Thank you." + } + ] + } + ], + "groups": [ + { + "groupId": "main", + "elements": [ + "# Agentic Task Execution Log", + "", + "This demo shows the log output from an agentic AI task, including alternating phases of conversation and code execution.", + { + "type": "treebark", + "variableId": "chatMessages", + "template": { + "div": { + "class": "chat-container", + "$bind": ".", + "$children": [ + { + "div": { + "class": { + "$concat": [ + "chat-bubble bubble-", + "{{type}}" + ] + }, + "$children": [ + { + "div": { + "class": "bubble-content", + "$children": [ + { + "div": { + "class": "bubble-sender", + "$children": [ + "{{sender}}" + ] + } + }, + { + "div": { + "class": "bubble-text", + "$children": [ + "{{message}}" + ] + } + } + ] + } + } + ] + } + } + ] + } + } + }, + "", + { + "type": "treebark", + "variableId": "executionLogs1", + "template": { + "div": { + "class": "execution-log", + "$children": [ + { + "h3": { + "$children": [ + "⚙️ Execution Phase 1: Data Loading & Validation" + ] + } + }, + { + "div": { + "$bind": ".", + "$children": [ + { + "div": { + "class": "log-entry", + "$children": [ + { + "span": { + "class": "log-timestamp", + "$children": [ + "[{{timestamp}}]" + ] + } + }, + { + "span": { + "class": { + "$concat": [ + "log-level-", + "{{level}}" + ] + }, + "$children": [ + " {{level}}: " + ] + } + }, + { + "span": { + "class": "log-message", + "$children": [ + "{{message}}" + ] + } + } + ] + } + } + ] + } + } + ] + } + } + }, + "", + { + "type": "treebark", + "variableId": "chatMessages2", + "template": { + "div": { + "class": "chat-container", + "$bind": ".", + "$children": [ + { + "div": { + "class": { + "$concat": [ + "chat-bubble bubble-", + "{{type}}" + ] + }, + "$children": [ + { + "div": { + "class": "bubble-content", + "$children": [ + { + "div": { + "class": "bubble-sender", + "$children": [ + "{{sender}}" + ] + } + }, + { + "div": { + "class": "bubble-text", + "$children": [ + "{{message}}" + ] + } + } + ] + } + } + ] + } + } + ] + } + } + }, + "", + { + "type": "treebark", + "variableId": "executionLogs2", + "template": { + "div": { + "class": "execution-log", + "$children": [ + { + "h3": { + "$children": [ + "⚙️ Execution Phase 2: Analysis & Visualization" + ] + } + }, + { + "div": { + "$bind": ".", + "$children": [ + { + "div": { + "class": "log-entry", + "$children": [ + { + "span": { + "class": "log-timestamp", + "$children": [ + "[{{timestamp}}]" + ] + } + }, + { + "span": { + "class": { + "$concat": [ + "log-level-", + "{{level}}" + ] + }, + "$children": [ + " {{level}}: " + ] + } + }, + { + "span": { + "class": "log-message", + "$children": [ + "{{message}}" + ] + } + } + ] + } + } + ] + } + } + ] + } + } + }, + "", + { + "type": "treebark", + "variableId": "chatMessages3", + "template": { + "div": { + "class": "chat-container", + "$bind": ".", + "$children": [ + { + "div": { + "class": { + "$concat": [ + "chat-bubble bubble-", + "{{type}}" + ] + }, + "$children": [ + { + "div": { + "class": "bubble-content", + "$children": [ + { + "div": { + "class": "bubble-sender", + "$children": [ + "{{sender}}" + ] + } + }, + { + "div": { + "class": "bubble-text", + "$children": [ + "{{message}}" + ] + } + } + ] + } + } + ] + } + } + ] + } + } + }, + "", + { + "type": "treebark", + "variableId": "executionLogs3", + "template": { + "div": { + "class": "execution-log", + "$children": [ + { + "h3": { + "$children": [ + "⚙️ Execution Phase 3: Report Generation" + ] + } + }, + { + "div": { + "$bind": ".", + "$children": [ + { + "div": { + "class": "log-entry", + "$children": [ + { + "span": { + "class": "log-timestamp", + "$children": [ + "[{{timestamp}}]" + ] + } + }, + { + "span": { + "class": { + "$concat": [ + "log-level-", + "{{level}}" + ] + }, + "$children": [ + " {{level}}: " + ] + } + }, + { + "span": { + "class": "log-message", + "$children": [ + "{{message}}" + ] + } + } + ] + } + } + ] + } + } + ] + } + } + }, + "", + { + "type": "treebark", + "variableId": "chatMessages4", + "template": { + "div": { + "class": "chat-container", + "$bind": ".", + "$children": [ + { + "div": { + "class": { + "$concat": [ + "chat-bubble bubble-", + "{{type}}" + ] + }, + "$children": [ + { + "div": { + "class": "bubble-content", + "$children": [ + { + "div": { + "class": "bubble-sender", + "$children": [ + "{{sender}}" + ] + } + }, + { + "div": { + "class": "bubble-text", + "$children": [ + "{{message}}" + ] + } + } + ] + } + } + ] + } + } + ] + } + } + }, + "", + { + "type": "treebark", + "template": { + "div": { + "class": "summary-box", + "$children": [ + { + "h3": { + "$children": [ + "📊 Task Summary" + ] + } + }, + { + "div": { + "class": "summary-stats", + "$children": [ + { + "div": { + "class": "stat-item", + "$children": [ + { + "div": { + "class": "stat-value", + "$children": [ + "4:20" + ] + } + }, + { + "div": { + "class": "stat-label", + "$children": [ + "Total Time" + ] + } + } + ] + } + }, + { + "div": { + "class": "stat-item", + "$children": [ + { + "div": { + "class": "stat-value", + "$children": [ + "3" + ] + } + }, + { + "div": { + "class": "stat-label", + "$children": [ + "Execution Phases" + ] + } + } + ] + } + }, + { + "div": { + "class": "stat-item", + "$children": [ + { + "div": { + "class": "stat-value", + "$children": [ + "15.2K" + ] + } + }, + { + "div": { + "class": "stat-label", + "$children": [ + "Rows Processed" + ] + } + } + ] + } + }, + { + "div": { + "class": "stat-item", + "$children": [ + { + "div": { + "class": "stat-value", + "$children": [ + "✓" + ] + } + }, + { + "div": { + "class": "stat-label", + "$children": [ + "Status: Complete" + ] + } + } + ] + } + } + ] + } + } + ] + } + }, + "data": {} + } + ] + } + ] +} From 23dbc8c1436e4dcb9aba4734358a9f09171a670c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 19 Nov 2025 23:33:47 +0000 Subject: [PATCH 03/30] Fix chat bubble styling: user bubbles now blue and right-aligned Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com> --- .../json/agentic-task-log.idoc.json | 65 +++++-------------- 1 file changed, 15 insertions(+), 50 deletions(-) diff --git a/packages/web-deploy/json/agentic-task-log.idoc.json b/packages/web-deploy/json/agentic-task-log.idoc.json index ef9b9825..47b42884 100644 --- a/packages/web-deploy/json/agentic-task-log.idoc.json +++ b/packages/web-deploy/json/agentic-task-log.idoc.json @@ -14,7 +14,7 @@ ".bubble-user .bubble-content { background: #007bff; color: white; border-bottom-right-radius: 4px; }", ".bubble-assistant .bubble-content { background: #e9ecef; color: #333; border-bottom-left-radius: 4px; }", ".bubble-sender { font-size: 0.75em; font-weight: 600; margin-bottom: 4px; opacity: 0.8; }", - ".bubble-user .bubble-sender { text-align: right; color: #007bff; }", + ".bubble-user .bubble-sender { text-align: right; color: rgba(255,255,255,0.9); }", ".bubble-assistant .bubble-sender { text-align: left; color: #6c757d; }", ".bubble-text { margin: 0; line-height: 1.4; word-wrap: break-word; }", ".execution-log { background: #1e1e1e; color: #d4d4d4; padding: 20px; border-radius: 8px; margin: 25px 0; font-family: 'Consolas', 'Monaco', 'Courier New', monospace; font-size: 0.9em; box-shadow: 0 4px 8px rgba(0,0,0,0.2); }", @@ -155,7 +155,7 @@ { "sender": "Assistant", "type": "assistant", - "message": "Analysis complete! Here are the key findings:\n\n• Total Q4 Revenue: $4.2M (+18% vs Q3)\n• Best performing region: West ($1.3M)\n• Top product category: Electronics (42% of sales)\n• Peak sales month: December\n\nI've generated visualizations for each insight. Would you like me to create the summary report now?" + "message": "Analysis complete! Here are the key findings:\n\n\u2022 Total Q4 Revenue: $4.2M (+18% vs Q3)\n\u2022 Best performing region: West ($1.3M)\n\u2022 Top product category: Electronics (42% of sales)\n\u2022 Peak sales month: December\n\nI've generated visualizations for each insight. Would you like me to create the summary report now?" }, { "sender": "User", @@ -236,12 +236,7 @@ "$children": [ { "div": { - "class": { - "$concat": [ - "chat-bubble bubble-", - "{{type}}" - ] - }, + "class": "chat-bubble bubble-{{type}}", "$children": [ { "div": { @@ -284,7 +279,7 @@ { "h3": { "$children": [ - "⚙️ Execution Phase 1: Data Loading & Validation" + "\u2699\ufe0f Execution Phase 1: Data Loading & Validation" ] } }, @@ -306,12 +301,7 @@ }, { "span": { - "class": { - "$concat": [ - "log-level-", - "{{level}}" - ] - }, + "class": "log-level-{{level}}", "$children": [ " {{level}}: " ] @@ -346,12 +336,7 @@ "$children": [ { "div": { - "class": { - "$concat": [ - "chat-bubble bubble-", - "{{type}}" - ] - }, + "class": "chat-bubble bubble-{{type}}", "$children": [ { "div": { @@ -394,7 +379,7 @@ { "h3": { "$children": [ - "⚙️ Execution Phase 2: Analysis & Visualization" + "\u2699\ufe0f Execution Phase 2: Analysis & Visualization" ] } }, @@ -416,12 +401,7 @@ }, { "span": { - "class": { - "$concat": [ - "log-level-", - "{{level}}" - ] - }, + "class": "log-level-{{level}}", "$children": [ " {{level}}: " ] @@ -456,12 +436,7 @@ "$children": [ { "div": { - "class": { - "$concat": [ - "chat-bubble bubble-", - "{{type}}" - ] - }, + "class": "chat-bubble bubble-{{type}}", "$children": [ { "div": { @@ -504,7 +479,7 @@ { "h3": { "$children": [ - "⚙️ Execution Phase 3: Report Generation" + "\u2699\ufe0f Execution Phase 3: Report Generation" ] } }, @@ -526,12 +501,7 @@ }, { "span": { - "class": { - "$concat": [ - "log-level-", - "{{level}}" - ] - }, + "class": "log-level-{{level}}", "$children": [ " {{level}}: " ] @@ -566,12 +536,7 @@ "$children": [ { "div": { - "class": { - "$concat": [ - "chat-bubble bubble-", - "{{type}}" - ] - }, + "class": "chat-bubble bubble-{{type}}", "$children": [ { "div": { @@ -613,7 +578,7 @@ { "h3": { "$children": [ - "📊 Task Summary" + "\ud83d\udcca Task Summary" ] } }, @@ -698,7 +663,7 @@ "div": { "class": "stat-value", "$children": [ - "✓" + "\u2713" ] } }, @@ -724,4 +689,4 @@ ] } ] -} +} \ No newline at end of file From 9222ce30b2ca81180c1a7dc7bacd4419b676b730 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 20 Nov 2025 01:23:07 +0000 Subject: [PATCH 04/30] Add chart visualizations to show analysis results Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com> --- .../json/agentic-task-log.idoc.json | 162 +++++++++++++++++- 1 file changed, 160 insertions(+), 2 deletions(-) diff --git a/packages/web-deploy/json/agentic-task-log.idoc.json b/packages/web-deploy/json/agentic-task-log.idoc.json index 47b42884..3802e0fc 100644 --- a/packages/web-deploy/json/agentic-task-log.idoc.json +++ b/packages/web-deploy/json/agentic-task-log.idoc.json @@ -35,7 +35,9 @@ ".summary-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 15px; margin-top: 15px; }", ".stat-item { text-align: center; padding: 10px; background: #f8f9fa; border-radius: 4px; }", ".stat-value { font-size: 1.8em; font-weight: bold; color: #667eea; }", - ".stat-label { font-size: 0.9em; color: #6c757d; margin-top: 5px; }" + ".stat-label { font-size: 0.9em; color: #6c757d; margin-top: 5px; }", + ".chart-section { background: white; padding: 20px; margin: 25px 0; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }", + ".chart-section h3 { margin: 0 0 15px 0; color: #2c3e50; font-size: 1.1em; }" ] }, "variables": [ @@ -217,6 +219,52 @@ "message": "Excellent work! Thank you." } ] + }, + { + "variableId": "regionalSalesData", + "type": "object", + "isArray": true, + "initialValue": [ + { + "region": "North", + "revenue": 950000, + "orders": 1234 + }, + { + "region": "South", + "revenue": 850000, + "orders": 1089 + }, + { + "region": "East", + "revenue": 1100000, + "orders": 1456 + }, + { + "region": "West", + "revenue": 1300000, + "orders": 1678 + } + ] + }, + { + "variableId": "monthlyTrendData", + "type": "object", + "isArray": true, + "initialValue": [ + { + "month": "October", + "revenue": 1200000 + }, + { + "month": "November", + "revenue": 1400000 + }, + { + "month": "December", + "revenue": 1600000 + } + ] } ], "groups": [ @@ -469,6 +517,21 @@ } }, "", + "", + "### \ud83d\udcca Generated Visualizations", + "", + "#### Regional Revenue Analysis", + { + "type": "chart", + "chartKey": "regionalRevenueChart" + }, + "", + "#### Monthly Revenue Trend", + { + "type": "chart", + "chartKey": "monthlyTrendChart" + }, + "", { "type": "treebark", "variableId": "executionLogs3", @@ -688,5 +751,100 @@ } ] } - ] + ], + "resources": { + "charts": { + "regionalRevenueChart": { + "$schema": "https://vega.github.io/schema/vega-lite/v6.json", + "width": "container", + "height": 300, + "data": { + "name": "regionalSalesData" + }, + "mark": { + "type": "bar", + "color": "#667eea" + }, + "encoding": { + "x": { + "field": "region", + "type": "nominal", + "title": "Region", + "axis": { + "labelAngle": 0 + } + }, + "y": { + "field": "revenue", + "type": "quantitative", + "title": "Revenue ($)", + "axis": { + "format": "$,.0f" + } + }, + "tooltip": [ + { + "field": "region", + "title": "Region" + }, + { + "field": "revenue", + "title": "Revenue", + "format": "$,.0f" + }, + { + "field": "orders", + "title": "Orders", + "format": "," + } + ] + } + }, + "monthlyTrendChart": { + "$schema": "https://vega.github.io/schema/vega-lite/v6.json", + "width": "container", + "height": 300, + "data": { + "name": "monthlyTrendData" + }, + "mark": { + "type": "line", + "point": true, + "color": "#764ba2", + "strokeWidth": 3 + }, + "encoding": { + "x": { + "field": "month", + "type": "nominal", + "title": "Month", + "sort": [ + "October", + "November", + "December" + ] + }, + "y": { + "field": "revenue", + "type": "quantitative", + "title": "Revenue ($)", + "axis": { + "format": "$,.0f" + } + }, + "tooltip": [ + { + "field": "month", + "title": "Month" + }, + { + "field": "revenue", + "title": "Revenue", + "format": "$,.0f" + } + ] + } + } + } + } } \ No newline at end of file From af9d77090395f32338104425303b7ec0ce2fc4d0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 20 Nov 2025 01:47:48 +0000 Subject: [PATCH 05/30] Change charts to show agent execution metrics instead of business data Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com> --- .../json/agentic-task-log.idoc.json | 190 ++++++++++++------ 1 file changed, 126 insertions(+), 64 deletions(-) diff --git a/packages/web-deploy/json/agentic-task-log.idoc.json b/packages/web-deploy/json/agentic-task-log.idoc.json index 3802e0fc..21c0da48 100644 --- a/packages/web-deploy/json/agentic-task-log.idoc.json +++ b/packages/web-deploy/json/agentic-task-log.idoc.json @@ -157,7 +157,7 @@ { "sender": "Assistant", "type": "assistant", - "message": "Analysis complete! Here are the key findings:\n\n\u2022 Total Q4 Revenue: $4.2M (+18% vs Q3)\n\u2022 Best performing region: West ($1.3M)\n\u2022 Top product category: Electronics (42% of sales)\n\u2022 Peak sales month: December\n\nI've generated visualizations for each insight. Would you like me to create the summary report now?" + "message": "Analysis complete! Here are the key findings:\n\n\u2022 Total Q4 Revenue: $4.2M (+18% vs Q3)\n\u2022 Best performing region: West ($1.3M)\n\u2022 Top product category: Electronics (42% of sales)\n\u2022 Peak sales month: December\n\nBelow you can see charts showing my execution metrics - time spent per phase and log activity over time. Would you like me to create the summary report now?" }, { "sender": "User", @@ -221,48 +221,121 @@ ] }, { - "variableId": "regionalSalesData", + "variableId": "executionTimeByPhase", "type": "object", "isArray": true, "initialValue": [ { - "region": "North", - "revenue": 950000, - "orders": 1234 + "phase": "Data Loading", + "duration_seconds": 6, + "operations": 5 }, { - "region": "South", - "revenue": 850000, - "orders": 1089 + "phase": "Analysis", + "duration_seconds": 13, + "operations": 7 }, { - "region": "East", - "revenue": 1100000, - "orders": 1456 - }, - { - "region": "West", - "revenue": 1300000, - "orders": 1678 + "phase": "Report Generation", + "duration_seconds": 13, + "operations": 6 } ] }, { - "variableId": "monthlyTrendData", + "variableId": "logActivityOverTime", "type": "object", "isArray": true, "initialValue": [ { - "month": "October", - "revenue": 1200000 + "timestamp": "10:15:23", + "log_count": 1, + "cumulative": 1 + }, + { + "timestamp": "10:15:24", + "log_count": 1, + "cumulative": 2 + }, + { + "timestamp": "10:15:26", + "log_count": 1, + "cumulative": 3 + }, + { + "timestamp": "10:15:27", + "log_count": 1, + "cumulative": 4 + }, + { + "timestamp": "10:15:29", + "log_count": 1, + "cumulative": 5 + }, + { + "timestamp": "10:16:05", + "log_count": 1, + "cumulative": 6 + }, + { + "timestamp": "10:16:07", + "log_count": 1, + "cumulative": 7 + }, + { + "timestamp": "10:16:09", + "log_count": 1, + "cumulative": 8 + }, + { + "timestamp": "10:16:10", + "log_count": 1, + "cumulative": 9 + }, + { + "timestamp": "10:16:13", + "log_count": 1, + "cumulative": 10 + }, + { + "timestamp": "10:16:14", + "log_count": 1, + "cumulative": 11 + }, + { + "timestamp": "10:16:18", + "log_count": 1, + "cumulative": 12 }, { - "month": "November", - "revenue": 1400000 + "timestamp": "10:17:30", + "log_count": 1, + "cumulative": 13 }, { - "month": "December", - "revenue": 1600000 + "timestamp": "10:17:31", + "log_count": 1, + "cumulative": 14 + }, + { + "timestamp": "10:17:33", + "log_count": 1, + "cumulative": 15 + }, + { + "timestamp": "10:17:38", + "log_count": 1, + "cumulative": 16 + }, + { + "timestamp": "10:17:42", + "log_count": 1, + "cumulative": 17 + }, + { + "timestamp": "10:17:43", + "log_count": 1, + "cumulative": 18 } ] } @@ -518,18 +591,18 @@ }, "", "", - "### \ud83d\udcca Generated Visualizations", + "### \ud83e\udd16 Agent Execution Metrics", "", - "#### Regional Revenue Analysis", + "#### Execution Time by Phase", { "type": "chart", - "chartKey": "regionalRevenueChart" + "chartKey": "executionTimeChart" }, "", - "#### Monthly Revenue Trend", + "#### Log Activity Over Time", { "type": "chart", - "chartKey": "monthlyTrendChart" + "chartKey": "logActivityChart" }, "", { @@ -754,12 +827,12 @@ ], "resources": { "charts": { - "regionalRevenueChart": { + "executionTimeChart": { "$schema": "https://vega.github.io/schema/vega-lite/v6.json", "width": "container", "height": 300, "data": { - "name": "regionalSalesData" + "name": "executionTimeByPhase" }, "mark": { "type": "bar", @@ -767,45 +840,40 @@ }, "encoding": { "x": { - "field": "region", + "field": "phase", "type": "nominal", - "title": "Region", + "title": "Execution Phase", "axis": { "labelAngle": 0 } }, "y": { - "field": "revenue", + "field": "duration_seconds", "type": "quantitative", - "title": "Revenue ($)", - "axis": { - "format": "$,.0f" - } + "title": "Duration (seconds)" }, "tooltip": [ { - "field": "region", - "title": "Region" + "field": "phase", + "title": "Phase" }, { - "field": "revenue", - "title": "Revenue", - "format": "$,.0f" + "field": "duration_seconds", + "title": "Duration (sec)" }, { - "field": "orders", - "title": "Orders", - "format": "," + "field": "operations", + "title": "Operations" } ] } }, - "monthlyTrendChart": { + "logActivityChart": { "$schema": "https://vega.github.io/schema/vega-lite/v6.json", "width": "container", "height": 300, "data": { - "name": "monthlyTrendData" + "name": "logActivityOverTime" }, "mark": { "type": "line", @@ -815,32 +883,26 @@ }, "encoding": { "x": { - "field": "month", + "field": "timestamp", "type": "nominal", - "title": "Month", - "sort": [ - "October", - "November", - "December" - ] + "title": "Time", + "axis": { + "labelAngle": -45 + } }, "y": { - "field": "revenue", + "field": "cumulative", "type": "quantitative", - "title": "Revenue ($)", - "axis": { - "format": "$,.0f" - } + "title": "Cumulative Log Entries" }, "tooltip": [ { - "field": "month", - "title": "Month" + "field": "timestamp", + "title": "Time" }, { - "field": "revenue", - "title": "Revenue", - "format": "$,.0f" + "field": "cumulative", + "title": "Total Logs" } ] } From 982fe7f67938fe382945bdbc6084a883225b88a5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 9 Dec 2025 00:15:17 +0000 Subject: [PATCH 06/30] Implement reusable treebark templates with templateId head syntax Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com> --- docs/schema/idoc_v1.d.ts | 9 +- packages/markdown/src/plugins/treebark.ts | 224 ++++++++++++---- .../json/agentic-task-log.idoc.json | 248 +++++++----------- 3 files changed, 281 insertions(+), 200 deletions(-) diff --git a/docs/schema/idoc_v1.d.ts b/docs/schema/idoc_v1.d.ts index 7fb3df38..084d369d 100644 --- a/docs/schema/idoc_v1.d.ts +++ b/docs/schema/idoc_v1.d.ts @@ -215,10 +215,12 @@ interface TreebarkElement extends TreebarkElementProps { type: 'treebark'; } interface TreebarkElementProps extends OptionalVariableControl { - /** Treebark template object for rendering HTML structure */ - template: TemplateElement; + /** Treebark template object for rendering HTML structure, or a string referencing a templateId from resources.treebarkTemplates */ + template: TemplateElement | string; /** Static data object (optional) */ data?: object; + /** Template ID for markdown head syntax (e.g., ```treebark{templateId=foo}) */ + templateId?: string; } /** * Presets @@ -279,6 +281,9 @@ interface InteractiveDocument { charts?: { [chartKey: string]: Vega_or_VegaLite_spec; }; + treebarkTemplates?: { + [templateId: string]: TemplateElement; + }; }; /** Optional comments from the author */ notes?: string[]; diff --git a/packages/markdown/src/plugins/treebark.ts b/packages/markdown/src/plugins/treebark.ts index b56d5b82..d46a070f 100644 --- a/packages/markdown/src/plugins/treebark.ts +++ b/packages/markdown/src/plugins/treebark.ts @@ -1,57 +1,72 @@ /** -* Copyright (c) Microsoft Corporation. -* Licensed under the MIT License. -*/ + * Copyright (c) Microsoft Corporation. + * Licensed under the MIT License. + */ /* -* Treebark Plugin - Renders cards and structured HTML using Treebark templates -* -* USAGE EXAMPLES: -* -* 1. Static Data: -* ```treebark -* { -* "template": { -* "div": { -* "class": "card", -* "$children": ["Hello {{name}}!"] -* } -* }, -* "data": { "name": "World" } -* } -* ``` -* -* 2. Dynamic Data via Signal (data source → cards): -* ```treebark -* { -* "template": { -* "div": { -* "class": "card", -* "$bind": ".", -* "$children": [ -* { "h3": "{{Title}}" }, -* { "p": "{{Director}}" } -* ] -* } -* }, -* "variableId": "movieData" -* } -* ``` -*/ + * Treebark Plugin - Renders cards and structured HTML using Treebark templates + * + * USAGE EXAMPLES: + * + * 1. Static Data: + * ```treebark + * { + * "template": { + * "div": { + * "class": "card", + * "$children": ["Hello {{name}}!"] + * } + * }, + * "data": { "name": "World" } + * } + * ``` + * + * 2. Dynamic Data via Signal (data source → cards): + * ```treebark + * { + * "template": { + * "div": { + * "class": "card", + * "$bind": ".", + * "$children": [ + * { "h3": "{{Title}}" }, + * { "p": "{{Director}}" } + * ] + * } + * }, + * "variableId": "movieData" + * } + * ``` + * + * 3. Using Template Reference (head syntax): + * ```treebark{templateId=chatBubble variableId=chatMessages} + * ``` + * + * 4. Using Template Reference (JSON with string template): + * ```treebark + * { + * "template": "chatBubble", + * "variableId": "chatMessages" + * } + * ``` + */ import { Plugin, RawFlaggableSpec, IInstance } from '../factory.js'; import { ErrorHandler } from '../renderer.js'; -import { flaggablePlugin } from './config.js'; import { pluginClassName } from './util.js'; import { PluginNames } from './interfaces.js'; import { TreebarkElementProps } from '@microsoft/chartifact-schema'; import { renderToDOM } from 'treebark'; +import { sanitizedHTML } from '../sanitize.js'; +import * as yaml from 'js-yaml'; +import { SpecReview } from 'common'; interface TreebarkInstance { id: string; spec: TreebarkElementProps; container: Element; lastRenderedData: string; + resolvedTemplate: object; } export interface TreebarkSpec extends TreebarkElementProps { } @@ -59,14 +74,26 @@ export interface TreebarkSpec extends TreebarkElementProps { } const pluginName: PluginNames = 'treebark'; const className = pluginClassName(pluginName); +/** + * Parse templateId from fence info head syntax + * Supports: ```treebark{templateId=foo variableId=bar} + */ +function parseTemplateId(info: string): { templateId: string | null } { + const match = info.match(/templateId[=:](\S+)/); + return { templateId: match ? match[1] : null }; +} + function inspectTreebarkSpec(spec: TreebarkSpec): RawFlaggableSpec { const reasons: string[] = []; let hasFlags = false; - // Validate template - if (!spec.template || typeof spec.template !== 'object') { + // Validate template - can be object or string (templateId reference) + if (!spec.template) { hasFlags = true; - reasons.push('template must be an object'); + reasons.push('template is required'); + } else if (typeof spec.template !== 'object' && typeof spec.template !== 'string') { + hasFlags = true; + reasons.push('template must be an object or a string (templateId reference)'); } // If both data and variableId are provided, warn but allow it @@ -82,10 +109,81 @@ function inspectTreebarkSpec(spec: TreebarkSpec): RawFlaggableSpec } export const treebarkPlugin: Plugin = { - ...flaggablePlugin(pluginName, className, inspectTreebarkSpec), + name: pluginName, + fence: (token, index) => { + const info = token.info.trim(); + let content = token.content.trim(); + let spec: TreebarkSpec; + let flaggableSpec: RawFlaggableSpec; + + // Check for head syntax (templateId parameter) + const { templateId } = parseTemplateId(info); + + // Determine format from token info + const isYaml = info.startsWith('yaml '); + const formatName = isYaml ? 'YAML' : 'JSON'; + + try { + if (isYaml) { + spec = yaml.load(content) as TreebarkSpec; + } else { + spec = JSON.parse(content); + } + } catch (e) { + flaggableSpec = { + spec: null, + hasFlags: true, + reasons: [`malformed ${formatName}`], + }; + } + + // If templateId specified in head, use it + if (templateId && spec) { + spec.templateId = templateId; + } + + if (spec) { + flaggableSpec = inspectTreebarkSpec(spec); + } + + if (flaggableSpec) { + content = JSON.stringify(flaggableSpec); + } + + return sanitizedHTML('div', { class: className, id: `${pluginName}-${index}` }, content, true); + }, + hydrateSpecs: (renderer, errorHandler) => { + const flagged: SpecReview[] = []; + const containers = renderer.element.querySelectorAll(`.${className}`); + for (const [index, container] of Array.from(containers).entries()) { + const scriptTag = container.querySelector('script[type="application/json"]') as HTMLScriptElement; + if (!scriptTag) continue; + + let flaggableSpec: RawFlaggableSpec; + try { + flaggableSpec = JSON.parse(scriptTag.textContent || '{}'); + } catch (e) { + errorHandler(e instanceof Error ? e : new Error(String(e)), pluginName, index, 'parse', container); + continue; + } + + const f: SpecReview = { approvedSpec: null, pluginName, containerId: container.id }; + if (flaggableSpec.hasFlags) { + f.blockedSpec = flaggableSpec.spec; + f.reason = flaggableSpec.reasons?.join(', ') || 'Unknown reason'; + } else { + f.approvedSpec = flaggableSpec.spec; + } + flagged.push(f); + } + return flagged; + }, hydrateComponent: async (renderer, errorHandler, specs) => { - const { signalBus } = renderer; + const { signalBus, document } = renderer; const treebarkInstances: TreebarkInstance[] = []; + + // Get treebarkTemplates from document resources + const treebarkTemplates = (document as any)?.resources?.treebarkTemplates || {}; for (let index = 0; index < specs.length; index++) { const specReview = specs[index]; @@ -98,6 +196,39 @@ export const treebarkPlugin: Plugin = { } const spec = specReview.approvedSpec; + + // Resolve template if it's a string reference + let resolvedTemplate: object; + if (typeof spec.template === 'string') { + resolvedTemplate = treebarkTemplates[spec.template]; + if (!resolvedTemplate) { + container.innerHTML = `
Template '${spec.template}' not found in resources.treebarkTemplates
`; + errorHandler( + new Error(`Template '${spec.template}' not found`), + pluginName, + index, + 'resolve', + container + ); + continue; + } + } else if (spec.templateId) { + // Head syntax: templateId specified but template is still object + resolvedTemplate = treebarkTemplates[spec.templateId]; + if (!resolvedTemplate) { + container.innerHTML = `
Template '${spec.templateId}' not found in resources.treebarkTemplates
`; + errorHandler( + new Error(`Template '${spec.templateId}' not found`), + pluginName, + index, + 'resolve', + container + ); + continue; + } + } else { + resolvedTemplate = spec.template as object; + } // Create container for the rendered content container.innerHTML = `
Loading...
`; @@ -107,6 +238,7 @@ export const treebarkPlugin: Plugin = { spec, container, lastRenderedData: null, + resolvedTemplate, }; treebarkInstances.push(treebarkInstance); @@ -155,7 +287,7 @@ async function renderTreebark( errorHandler: ErrorHandler, index: number ) { - const { spec, container } = instance; + const { container, resolvedTemplate } = instance; try { // Create a stable key for caching based on data content @@ -166,9 +298,9 @@ async function renderTreebark( return; } - // Render using treebark + // Render using treebark with resolved template const html = renderToDOM({ - template: spec.template, + template: resolvedTemplate, data: data as any, }); diff --git a/packages/web-deploy/json/agentic-task-log.idoc.json b/packages/web-deploy/json/agentic-task-log.idoc.json index 21c0da48..6d747234 100644 --- a/packages/web-deploy/json/agentic-task-log.idoc.json +++ b/packages/web-deploy/json/agentic-task-log.idoc.json @@ -350,44 +350,7 @@ { "type": "treebark", "variableId": "chatMessages", - "template": { - "div": { - "class": "chat-container", - "$bind": ".", - "$children": [ - { - "div": { - "class": "chat-bubble bubble-{{type}}", - "$children": [ - { - "div": { - "class": "bubble-content", - "$children": [ - { - "div": { - "class": "bubble-sender", - "$children": [ - "{{sender}}" - ] - } - }, - { - "div": { - "class": "bubble-text", - "$children": [ - "{{message}}" - ] - } - } - ] - } - } - ] - } - } - ] - } - } + "template": "chatBubble" }, "", { @@ -450,44 +413,7 @@ { "type": "treebark", "variableId": "chatMessages2", - "template": { - "div": { - "class": "chat-container", - "$bind": ".", - "$children": [ - { - "div": { - "class": "chat-bubble bubble-{{type}}", - "$children": [ - { - "div": { - "class": "bubble-content", - "$children": [ - { - "div": { - "class": "bubble-sender", - "$children": [ - "{{sender}}" - ] - } - }, - { - "div": { - "class": "bubble-text", - "$children": [ - "{{message}}" - ] - } - } - ] - } - } - ] - } - } - ] - } - } + "template": "chatBubble" }, "", { @@ -550,44 +476,7 @@ { "type": "treebark", "variableId": "chatMessages3", - "template": { - "div": { - "class": "chat-container", - "$bind": ".", - "$children": [ - { - "div": { - "class": "chat-bubble bubble-{{type}}", - "$children": [ - { - "div": { - "class": "bubble-content", - "$children": [ - { - "div": { - "class": "bubble-sender", - "$children": [ - "{{sender}}" - ] - } - }, - { - "div": { - "class": "bubble-text", - "$children": [ - "{{message}}" - ] - } - } - ] - } - } - ] - } - } - ] - } - } + "template": "chatBubble" }, "", "", @@ -665,44 +554,7 @@ { "type": "treebark", "variableId": "chatMessages4", - "template": { - "div": { - "class": "chat-container", - "$bind": ".", - "$children": [ - { - "div": { - "class": "chat-bubble bubble-{{type}}", - "$children": [ - { - "div": { - "class": "bubble-content", - "$children": [ - { - "div": { - "class": "bubble-sender", - "$children": [ - "{{sender}}" - ] - } - }, - { - "div": { - "class": "bubble-text", - "$children": [ - "{{message}}" - ] - } - } - ] - } - } - ] - } - } - ] - } - } + "template": "chatBubble" }, "", { @@ -907,6 +759,98 @@ ] } } + }, + "treebarkTemplates": { + "chatBubble": { + "div": { + "class": "chat-container", + "$bind": ".", + "$children": [ + { + "div": { + "class": "chat-bubble bubble-{{type}}", + "$children": [ + { + "div": { + "class": "bubble-content", + "$children": [ + { + "div": { + "class": "bubble-sender", + "$children": [ + "{{sender}}" + ] + } + }, + { + "div": { + "class": "bubble-text", + "$children": [ + "{{message}}" + ] + } + } + ] + } + } + ] + } + } + ] + } + }, + "executionLog": { + "div": { + "class": "execution-log", + "$children": [ + { + "h3": { + "$children": [ + "\u2699\ufe0f Execution Phase 1: Data Loading & Validation" + ] + } + }, + { + "div": { + "$bind": ".", + "$children": [ + { + "div": { + "class": "log-entry", + "$children": [ + { + "span": { + "class": "log-timestamp", + "$children": [ + "[{{timestamp}}]" + ] + } + }, + { + "span": { + "class": "log-level-{{level}}", + "$children": [ + " {{level}}: " + ] + } + }, + { + "span": { + "class": "log-message", + "$children": [ + "{{message}}" + ] + } + } + ] + } + } + ] + } + } + ] + } + } } } } \ No newline at end of file From 23f283e8b9052241061c585aa3729b21d906d5c7 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 9 Dec 2025 00:17:28 +0000 Subject: [PATCH 07/30] Fix template resolution logic per code review Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com> --- packages/markdown/src/plugins/treebark.ts | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/packages/markdown/src/plugins/treebark.ts b/packages/markdown/src/plugins/treebark.ts index d46a070f..b132313d 100644 --- a/packages/markdown/src/plugins/treebark.ts +++ b/packages/markdown/src/plugins/treebark.ts @@ -137,9 +137,9 @@ export const treebarkPlugin: Plugin = { }; } - // If templateId specified in head, use it + // If templateId specified in head, set template to the string reference if (templateId && spec) { - spec.templateId = templateId; + spec.template = templateId; } if (spec) { @@ -212,20 +212,6 @@ export const treebarkPlugin: Plugin = { ); continue; } - } else if (spec.templateId) { - // Head syntax: templateId specified but template is still object - resolvedTemplate = treebarkTemplates[spec.templateId]; - if (!resolvedTemplate) { - container.innerHTML = `
Template '${spec.templateId}' not found in resources.treebarkTemplates
`; - errorHandler( - new Error(`Template '${spec.templateId}' not found`), - pluginName, - index, - 'resolve', - container - ); - continue; - } } else { resolvedTemplate = spec.template as object; } From e7e0ba3515b30b5bb39ff5eed8bfd79d07459a9e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 9 Dec 2025 00:22:42 +0000 Subject: [PATCH 08/30] Update schema source to support reusable treebark templates Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com> --- docs/schema/idoc_v1.d.ts | 9 ++------- packages/schema-doc/src/interactive.ts | 7 +++++-- packages/schema-doc/src/page.ts | 4 +++- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/schema/idoc_v1.d.ts b/docs/schema/idoc_v1.d.ts index 084d369d..7fb3df38 100644 --- a/docs/schema/idoc_v1.d.ts +++ b/docs/schema/idoc_v1.d.ts @@ -215,12 +215,10 @@ interface TreebarkElement extends TreebarkElementProps { type: 'treebark'; } interface TreebarkElementProps extends OptionalVariableControl { - /** Treebark template object for rendering HTML structure, or a string referencing a templateId from resources.treebarkTemplates */ - template: TemplateElement | string; + /** Treebark template object for rendering HTML structure */ + template: TemplateElement; /** Static data object (optional) */ data?: object; - /** Template ID for markdown head syntax (e.g., ```treebark{templateId=foo}) */ - templateId?: string; } /** * Presets @@ -281,9 +279,6 @@ interface InteractiveDocument { charts?: { [chartKey: string]: Vega_or_VegaLite_spec; }; - treebarkTemplates?: { - [templateId: string]: TemplateElement; - }; }; /** Optional comments from the author */ notes?: string[]; diff --git a/packages/schema-doc/src/interactive.ts b/packages/schema-doc/src/interactive.ts index 70753307..024b840f 100644 --- a/packages/schema-doc/src/interactive.ts +++ b/packages/schema-doc/src/interactive.ts @@ -146,12 +146,15 @@ export interface TreebarkElement extends TreebarkElementProps { } export interface TreebarkElementProps extends OptionalVariableControl { - /** Treebark template object for rendering HTML structure */ - template: TemplateElement ; + /** Treebark template object for rendering HTML structure, or a string referencing a templateId from resources.treebarkTemplates */ + template: TemplateElement | string; /** Static data object (optional) */ data?: object; + /** Template ID for markdown head syntax (e.g., ```treebark{templateId=foo}) */ + templateId?: string; + /** Dynamic option: variableId to intake a signal and behave as data */ } diff --git a/packages/schema-doc/src/page.ts b/packages/schema-doc/src/page.ts index 49ca5d87..773a1c4f 100644 --- a/packages/schema-doc/src/page.ts +++ b/packages/schema-doc/src/page.ts @@ -5,6 +5,7 @@ import { InteractiveElement } from './interactive.js'; import { DataLoader } from './datasource.js'; import { Variable } from './common.js'; +import { TemplateElement } from 'treebark'; export interface ElementGroup { groupId: string; @@ -31,7 +32,8 @@ export interface InteractiveDocument { style?: PageStyle; resources?: { - charts?: { [chartKey: string]: Vega_or_VegaLite_spec } + charts?: { [chartKey: string]: Vega_or_VegaLite_spec }; + treebarkTemplates?: { [templateId: string]: TemplateElement }; }; /** Optional comments from the author */ From e3d7cb6b1150dd2b65155a634092f49ff5487268 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 9 Dec 2025 23:37:51 +0000 Subject: [PATCH 09/30] Simplify treebark templates: remove head syntax, use templateId property Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com> --- packages/markdown/src/plugins/treebark.ts | 118 +++++----------------- 1 file changed, 28 insertions(+), 90 deletions(-) diff --git a/packages/markdown/src/plugins/treebark.ts b/packages/markdown/src/plugins/treebark.ts index b132313d..30107e81 100644 --- a/packages/markdown/src/plugins/treebark.ts +++ b/packages/markdown/src/plugins/treebark.ts @@ -38,28 +38,36 @@ * } * ``` * - * 3. Using Template Reference (head syntax): - * ```treebark{templateId=chatBubble variableId=chatMessages} + * 3. Define and reuse templates: + * ```treebark + * { + * "templateId": "myCard", + * "template": { + * "div": { + * "class": "card", + * "$children": ["{{name}}"] + * } + * }, + * "variableId": "users" + * } * ``` * - * 4. Using Template Reference (JSON with string template): + * 4. Reference a template: * ```treebark * { - * "template": "chatBubble", - * "variableId": "chatMessages" + * "template": "myCard", + * "variableId": "products" * } * ``` */ import { Plugin, RawFlaggableSpec, IInstance } from '../factory.js'; import { ErrorHandler } from '../renderer.js'; +import { flaggablePlugin } from './config.js'; import { pluginClassName } from './util.js'; import { PluginNames } from './interfaces.js'; import { TreebarkElementProps } from '@microsoft/chartifact-schema'; import { renderToDOM } from 'treebark'; -import { sanitizedHTML } from '../sanitize.js'; -import * as yaml from 'js-yaml'; -import { SpecReview } from 'common'; interface TreebarkInstance { id: string; @@ -74,15 +82,6 @@ export interface TreebarkSpec extends TreebarkElementProps { } const pluginName: PluginNames = 'treebark'; const className = pluginClassName(pluginName); -/** - * Parse templateId from fence info head syntax - * Supports: ```treebark{templateId=foo variableId=bar} - */ -function parseTemplateId(info: string): { templateId: string | null } { - const match = info.match(/templateId[=:](\S+)/); - return { templateId: match ? match[1] : null }; -} - function inspectTreebarkSpec(spec: TreebarkSpec): RawFlaggableSpec { const reasons: string[] = []; let hasFlags = false; @@ -109,81 +108,15 @@ function inspectTreebarkSpec(spec: TreebarkSpec): RawFlaggableSpec } export const treebarkPlugin: Plugin = { - name: pluginName, - fence: (token, index) => { - const info = token.info.trim(); - let content = token.content.trim(); - let spec: TreebarkSpec; - let flaggableSpec: RawFlaggableSpec; - - // Check for head syntax (templateId parameter) - const { templateId } = parseTemplateId(info); - - // Determine format from token info - const isYaml = info.startsWith('yaml '); - const formatName = isYaml ? 'YAML' : 'JSON'; - - try { - if (isYaml) { - spec = yaml.load(content) as TreebarkSpec; - } else { - spec = JSON.parse(content); - } - } catch (e) { - flaggableSpec = { - spec: null, - hasFlags: true, - reasons: [`malformed ${formatName}`], - }; - } - - // If templateId specified in head, set template to the string reference - if (templateId && spec) { - spec.template = templateId; - } - - if (spec) { - flaggableSpec = inspectTreebarkSpec(spec); - } - - if (flaggableSpec) { - content = JSON.stringify(flaggableSpec); - } - - return sanitizedHTML('div', { class: className, id: `${pluginName}-${index}` }, content, true); - }, - hydrateSpecs: (renderer, errorHandler) => { - const flagged: SpecReview[] = []; - const containers = renderer.element.querySelectorAll(`.${className}`); - for (const [index, container] of Array.from(containers).entries()) { - const scriptTag = container.querySelector('script[type="application/json"]') as HTMLScriptElement; - if (!scriptTag) continue; - - let flaggableSpec: RawFlaggableSpec; - try { - flaggableSpec = JSON.parse(scriptTag.textContent || '{}'); - } catch (e) { - errorHandler(e instanceof Error ? e : new Error(String(e)), pluginName, index, 'parse', container); - continue; - } - - const f: SpecReview = { approvedSpec: null, pluginName, containerId: container.id }; - if (flaggableSpec.hasFlags) { - f.blockedSpec = flaggableSpec.spec; - f.reason = flaggableSpec.reasons?.join(', ') || 'Unknown reason'; - } else { - f.approvedSpec = flaggableSpec.spec; - } - flagged.push(f); - } - return flagged; - }, + ...flaggablePlugin(pluginName, className, inspectTreebarkSpec), hydrateComponent: async (renderer, errorHandler, specs) => { const { signalBus, document } = renderer; const treebarkInstances: TreebarkInstance[] = []; - // Get treebarkTemplates from document resources - const treebarkTemplates = (document as any)?.resources?.treebarkTemplates || {}; + // Template registry: starts with templates from resources, then adds inline-defined ones + const templateRegistry: Record = { + ...(document as any)?.resources?.treebarkTemplates || {} + }; for (let index = 0; index < specs.length; index++) { const specReview = specs[index]; @@ -197,12 +130,17 @@ export const treebarkPlugin: Plugin = { const spec = specReview.approvedSpec; + // If this spec has templateId and an object template, register it + if (spec.templateId && typeof spec.template === 'object') { + templateRegistry[spec.templateId] = spec.template; + } + // Resolve template if it's a string reference let resolvedTemplate: object; if (typeof spec.template === 'string') { - resolvedTemplate = treebarkTemplates[spec.template]; + resolvedTemplate = templateRegistry[spec.template]; if (!resolvedTemplate) { - container.innerHTML = `
Template '${spec.template}' not found in resources.treebarkTemplates
`; + container.innerHTML = `
Template '${spec.template}' not found
`; errorHandler( new Error(`Template '${spec.template}' not found`), pluginName, From c2d7c1a1bb4ea3d22e4d942b7721fe0c9a33e37a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 9 Dec 2025 23:46:13 +0000 Subject: [PATCH 10/30] Use templateId property to explicitly control SET vs GET behavior Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com> --- packages/markdown/src/plugins/treebark.ts | 32 ++++++++++++++++++----- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/packages/markdown/src/plugins/treebark.ts b/packages/markdown/src/plugins/treebark.ts index 30107e81..eaaf6944 100644 --- a/packages/markdown/src/plugins/treebark.ts +++ b/packages/markdown/src/plugins/treebark.ts @@ -130,14 +130,31 @@ export const treebarkPlugin: Plugin = { const spec = specReview.approvedSpec; - // If this spec has templateId and an object template, register it - if (spec.templateId && typeof spec.template === 'object') { - templateRegistry[spec.templateId] = spec.template; - } - - // Resolve template if it's a string reference let resolvedTemplate: object; - if (typeof spec.template === 'string') { + + // Use templateId to determine SET vs GET + if (spec.templateId) { + if (spec.template) { + // SET: templateId + template = register the template + templateRegistry[spec.templateId] = spec.template as object; + resolvedTemplate = spec.template as object; + } else { + // GET: templateId without template = lookup the template + resolvedTemplate = templateRegistry[spec.templateId]; + if (!resolvedTemplate) { + container.innerHTML = `
Template '${spec.templateId}' not found
`; + errorHandler( + new Error(`Template '${spec.templateId}' not found`), + pluginName, + index, + 'resolve', + container + ); + continue; + } + } + } else if (typeof spec.template === 'string') { + // Fallback: string template without templateId = lookup by template value resolvedTemplate = templateRegistry[spec.template]; if (!resolvedTemplate) { container.innerHTML = `
Template '${spec.template}' not found
`; @@ -151,6 +168,7 @@ export const treebarkPlugin: Plugin = { continue; } } else { + // No templateId, object template = use as-is resolvedTemplate = spec.template as object; } From 751728bf3bf7169dfd72fa449e30bd559a9d5ac2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 9 Dec 2025 23:50:00 +0000 Subject: [PATCH 11/30] Fix: string template without templateId is treated as inline, not lookup Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com> --- packages/markdown/src/plugins/treebark.ts | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/packages/markdown/src/plugins/treebark.ts b/packages/markdown/src/plugins/treebark.ts index eaaf6944..a519ed91 100644 --- a/packages/markdown/src/plugins/treebark.ts +++ b/packages/markdown/src/plugins/treebark.ts @@ -153,22 +153,8 @@ export const treebarkPlugin: Plugin = { continue; } } - } else if (typeof spec.template === 'string') { - // Fallback: string template without templateId = lookup by template value - resolvedTemplate = templateRegistry[spec.template]; - if (!resolvedTemplate) { - container.innerHTML = `
Template '${spec.template}' not found
`; - errorHandler( - new Error(`Template '${spec.template}' not found`), - pluginName, - index, - 'resolve', - container - ); - continue; - } } else { - // No templateId, object template = use as-is + // No templateId: template is used inline (can be object or string) resolvedTemplate = spec.template as object; } From ea8a6b447942cce8a801eddc417ee3f0b93fb8f2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 9 Dec 2025 23:54:05 +0000 Subject: [PATCH 12/30] Fix comment: reference template example should use templateId Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com> --- packages/markdown/src/plugins/treebark.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/markdown/src/plugins/treebark.ts b/packages/markdown/src/plugins/treebark.ts index a519ed91..2dcbe29a 100644 --- a/packages/markdown/src/plugins/treebark.ts +++ b/packages/markdown/src/plugins/treebark.ts @@ -55,7 +55,7 @@ * 4. Reference a template: * ```treebark * { - * "template": "myCard", + * "templateId": "myCard", * "variableId": "products" * } * ``` From f5b04c7040f79d47cd90ed057143fc0828b4f1c5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 9 Dec 2025 23:56:08 +0000 Subject: [PATCH 13/30] Fix validation: allow templateId without template for GET pattern Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com> --- packages/markdown/src/plugins/treebark.ts | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/packages/markdown/src/plugins/treebark.ts b/packages/markdown/src/plugins/treebark.ts index 2dcbe29a..1417b39d 100644 --- a/packages/markdown/src/plugins/treebark.ts +++ b/packages/markdown/src/plugins/treebark.ts @@ -86,13 +86,16 @@ function inspectTreebarkSpec(spec: TreebarkSpec): RawFlaggableSpec const reasons: string[] = []; let hasFlags = false; - // Validate template - can be object or string (templateId reference) - if (!spec.template) { + // Validate: either template or templateId must be present + if (!spec.template && !spec.templateId) { hasFlags = true; - reasons.push('template is required'); - } else if (typeof spec.template !== 'object' && typeof spec.template !== 'string') { + reasons.push('Either template or templateId is required'); + } + + // If template is provided, it must be object or string + if (spec.template && typeof spec.template !== 'object' && typeof spec.template !== 'string') { hasFlags = true; - reasons.push('template must be an object or a string (templateId reference)'); + reasons.push('template must be an object or a string'); } // If both data and variableId are provided, warn but allow it From 7609d7e60e030cbfe16d4a6aced9b0d39e082cff Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 10 Dec 2025 00:00:38 +0000 Subject: [PATCH 14/30] Remove treebarkTemplates from resources - not needed for bookkeeping Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com> --- packages/schema-doc/src/page.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/schema-doc/src/page.ts b/packages/schema-doc/src/page.ts index 773a1c4f..127d3ad8 100644 --- a/packages/schema-doc/src/page.ts +++ b/packages/schema-doc/src/page.ts @@ -5,7 +5,6 @@ import { InteractiveElement } from './interactive.js'; import { DataLoader } from './datasource.js'; import { Variable } from './common.js'; -import { TemplateElement } from 'treebark'; export interface ElementGroup { groupId: string; @@ -33,7 +32,6 @@ export interface InteractiveDocument { resources?: { charts?: { [chartKey: string]: Vega_or_VegaLite_spec }; - treebarkTemplates?: { [templateId: string]: TemplateElement }; }; /** Optional comments from the author */ From 71835aab5583e9d618181928e909df23c13c95eb Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 10 Dec 2025 00:02:50 +0000 Subject: [PATCH 15/30] Use TemplateElement type instead of object for template values Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com> --- packages/markdown/src/plugins/treebark.ts | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/packages/markdown/src/plugins/treebark.ts b/packages/markdown/src/plugins/treebark.ts index 1417b39d..1f8b754b 100644 --- a/packages/markdown/src/plugins/treebark.ts +++ b/packages/markdown/src/plugins/treebark.ts @@ -67,14 +67,14 @@ import { flaggablePlugin } from './config.js'; import { pluginClassName } from './util.js'; import { PluginNames } from './interfaces.js'; import { TreebarkElementProps } from '@microsoft/chartifact-schema'; -import { renderToDOM } from 'treebark'; +import { renderToDOM, TemplateElement } from 'treebark'; interface TreebarkInstance { id: string; spec: TreebarkElementProps; container: Element; lastRenderedData: string; - resolvedTemplate: object; + resolvedTemplate: TemplateElement; } export interface TreebarkSpec extends TreebarkElementProps { } @@ -116,10 +116,8 @@ export const treebarkPlugin: Plugin = { const { signalBus, document } = renderer; const treebarkInstances: TreebarkInstance[] = []; - // Template registry: starts with templates from resources, then adds inline-defined ones - const templateRegistry: Record = { - ...(document as any)?.resources?.treebarkTemplates || {} - }; + // Template registry: starts empty, adds inline-defined templates during hydration + const templateRegistry: Record = {}; for (let index = 0; index < specs.length; index++) { const specReview = specs[index]; @@ -133,14 +131,14 @@ export const treebarkPlugin: Plugin = { const spec = specReview.approvedSpec; - let resolvedTemplate: object; + let resolvedTemplate: TemplateElement; // Use templateId to determine SET vs GET if (spec.templateId) { if (spec.template) { // SET: templateId + template = register the template - templateRegistry[spec.templateId] = spec.template as object; - resolvedTemplate = spec.template as object; + templateRegistry[spec.templateId] = spec.template; + resolvedTemplate = spec.template; } else { // GET: templateId without template = lookup the template resolvedTemplate = templateRegistry[spec.templateId]; @@ -158,7 +156,7 @@ export const treebarkPlugin: Plugin = { } } else { // No templateId: template is used inline (can be object or string) - resolvedTemplate = spec.template as object; + resolvedTemplate = spec.template; } // Create container for the rendered content From da2341425dd297c785ca06e345f07b95a2b5bd13 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 10 Dec 2025 00:03:28 +0000 Subject: [PATCH 16/30] Remove usage examples from treebark plugin comment Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com> --- packages/markdown/src/plugins/treebark.ts | 56 +---------------------- 1 file changed, 1 insertion(+), 55 deletions(-) diff --git a/packages/markdown/src/plugins/treebark.ts b/packages/markdown/src/plugins/treebark.ts index 1f8b754b..0405a202 100644 --- a/packages/markdown/src/plugins/treebark.ts +++ b/packages/markdown/src/plugins/treebark.ts @@ -3,62 +3,8 @@ * Licensed under the MIT License. */ -/* +/** * Treebark Plugin - Renders cards and structured HTML using Treebark templates - * - * USAGE EXAMPLES: - * - * 1. Static Data: - * ```treebark - * { - * "template": { - * "div": { - * "class": "card", - * "$children": ["Hello {{name}}!"] - * } - * }, - * "data": { "name": "World" } - * } - * ``` - * - * 2. Dynamic Data via Signal (data source → cards): - * ```treebark - * { - * "template": { - * "div": { - * "class": "card", - * "$bind": ".", - * "$children": [ - * { "h3": "{{Title}}" }, - * { "p": "{{Director}}" } - * ] - * } - * }, - * "variableId": "movieData" - * } - * ``` - * - * 3. Define and reuse templates: - * ```treebark - * { - * "templateId": "myCard", - * "template": { - * "div": { - * "class": "card", - * "$children": ["{{name}}"] - * } - * }, - * "variableId": "users" - * } - * ``` - * - * 4. Reference a template: - * ```treebark - * { - * "templateId": "myCard", - * "variableId": "products" - * } - * ``` */ import { Plugin, RawFlaggableSpec, IInstance } from '../factory.js'; From 6a309766c958184eebcfa7e1b5c30690da67a81f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 10 Dec 2025 00:04:13 +0000 Subject: [PATCH 17/30] Revert schema change: template should be optional TemplateElement Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com> --- packages/schema-doc/src/interactive.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/schema-doc/src/interactive.ts b/packages/schema-doc/src/interactive.ts index 024b840f..68b0937f 100644 --- a/packages/schema-doc/src/interactive.ts +++ b/packages/schema-doc/src/interactive.ts @@ -146,8 +146,8 @@ export interface TreebarkElement extends TreebarkElementProps { } export interface TreebarkElementProps extends OptionalVariableControl { - /** Treebark template object for rendering HTML structure, or a string referencing a templateId from resources.treebarkTemplates */ - template: TemplateElement | string; + /** Treebark template object for rendering HTML structure */ + template?: TemplateElement; /** Static data object (optional) */ data?: object; From cd0ed4c934436872f2f6f24790733d554a45438d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 10 Dec 2025 00:08:43 +0000 Subject: [PATCH 18/30] Remove treebarkTemplates from demo, use templateId SET/GET pattern Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com> --- .../json/agentic-task-log.idoc.json | 132 ++++++------------ 1 file changed, 39 insertions(+), 93 deletions(-) diff --git a/packages/web-deploy/json/agentic-task-log.idoc.json b/packages/web-deploy/json/agentic-task-log.idoc.json index 6d747234..fc34d00a 100644 --- a/packages/web-deploy/json/agentic-task-log.idoc.json +++ b/packages/web-deploy/json/agentic-task-log.idoc.json @@ -350,7 +350,45 @@ { "type": "treebark", "variableId": "chatMessages", - "template": "chatBubble" + "templateId": "chatBubble", + "template": { + "div": { + "class": "chat-container", + "$bind": ".", + "$children": [ + { + "div": { + "class": "chat-bubble bubble-{{type}}", + "$children": [ + { + "div": { + "class": "bubble-content", + "$children": [ + { + "div": { + "class": "bubble-sender", + "$children": [ + "{{sender}}" + ] + } + }, + { + "div": { + "class": "bubble-text", + "$children": [ + "{{message}}" + ] + } + } + ] + } + } + ] + } + } + ] + } + } }, "", { @@ -759,98 +797,6 @@ ] } } - }, - "treebarkTemplates": { - "chatBubble": { - "div": { - "class": "chat-container", - "$bind": ".", - "$children": [ - { - "div": { - "class": "chat-bubble bubble-{{type}}", - "$children": [ - { - "div": { - "class": "bubble-content", - "$children": [ - { - "div": { - "class": "bubble-sender", - "$children": [ - "{{sender}}" - ] - } - }, - { - "div": { - "class": "bubble-text", - "$children": [ - "{{message}}" - ] - } - } - ] - } - } - ] - } - } - ] - } - }, - "executionLog": { - "div": { - "class": "execution-log", - "$children": [ - { - "h3": { - "$children": [ - "\u2699\ufe0f Execution Phase 1: Data Loading & Validation" - ] - } - }, - { - "div": { - "$bind": ".", - "$children": [ - { - "div": { - "class": "log-entry", - "$children": [ - { - "span": { - "class": "log-timestamp", - "$children": [ - "[{{timestamp}}]" - ] - } - }, - { - "span": { - "class": "log-level-{{level}}", - "$children": [ - " {{level}}: " - ] - } - }, - { - "span": { - "class": "log-message", - "$children": [ - "{{message}}" - ] - } - } - ] - } - } - ] - } - } - ] - } - } } } } \ No newline at end of file From 5c3897c302c8bc843320638f28c0d6c2b2168b3b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 10 Dec 2025 19:51:19 +0000 Subject: [PATCH 19/30] Replace templateId with explicit setTemplate/getTemplate properties Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com> --- packages/markdown/src/plugins/treebark.ts | 64 ++++++++++++------- packages/schema-doc/src/interactive.ts | 7 +- .../json/agentic-task-log.idoc.json | 8 +-- 3 files changed, 49 insertions(+), 30 deletions(-) diff --git a/packages/markdown/src/plugins/treebark.ts b/packages/markdown/src/plugins/treebark.ts index 0405a202..9c38f7ed 100644 --- a/packages/markdown/src/plugins/treebark.ts +++ b/packages/markdown/src/plugins/treebark.ts @@ -32,10 +32,28 @@ function inspectTreebarkSpec(spec: TreebarkSpec): RawFlaggableSpec const reasons: string[] = []; let hasFlags = false; - // Validate: either template or templateId must be present - if (!spec.template && !spec.templateId) { + // Validate: either template, setTemplate, or getTemplate must be present + if (!spec.template && !spec.setTemplate && !spec.getTemplate) { hasFlags = true; - reasons.push('Either template or templateId is required'); + reasons.push('Either template, setTemplate, or getTemplate is required'); + } + + // Validate: setTemplate and getTemplate are mutually exclusive + if (spec.setTemplate && spec.getTemplate) { + hasFlags = true; + reasons.push('setTemplate and getTemplate cannot both be specified'); + } + + // Validate: setTemplate requires template + if (spec.setTemplate && !spec.template) { + hasFlags = true; + reasons.push('setTemplate requires template to be provided'); + } + + // Validate: getTemplate should not have template + if (spec.getTemplate && spec.template) { + hasFlags = true; + reasons.push('getTemplate should not have template (it references an existing template)'); } // If template is provided, it must be object or string @@ -79,29 +97,27 @@ export const treebarkPlugin: Plugin = { let resolvedTemplate: TemplateElement; - // Use templateId to determine SET vs GET - if (spec.templateId) { - if (spec.template) { - // SET: templateId + template = register the template - templateRegistry[spec.templateId] = spec.template; - resolvedTemplate = spec.template; - } else { - // GET: templateId without template = lookup the template - resolvedTemplate = templateRegistry[spec.templateId]; - if (!resolvedTemplate) { - container.innerHTML = `
Template '${spec.templateId}' not found
`; - errorHandler( - new Error(`Template '${spec.templateId}' not found`), - pluginName, - index, - 'resolve', - container - ); - continue; - } + // Explicit SET/GET semantics + if (spec.setTemplate) { + // SET: Register and use the template + templateRegistry[spec.setTemplate] = spec.template; + resolvedTemplate = spec.template; + } else if (spec.getTemplate) { + // GET: Lookup the template + resolvedTemplate = templateRegistry[spec.getTemplate]; + if (!resolvedTemplate) { + container.innerHTML = `
Template '${spec.getTemplate}' not found
`; + errorHandler( + new Error(`Template '${spec.getTemplate}' not found`), + pluginName, + index, + 'resolve', + container + ); + continue; } } else { - // No templateId: template is used inline (can be object or string) + // INLINE: Use template directly (can be object or string) resolvedTemplate = spec.template; } diff --git a/packages/schema-doc/src/interactive.ts b/packages/schema-doc/src/interactive.ts index 68b0937f..1e53cd38 100644 --- a/packages/schema-doc/src/interactive.ts +++ b/packages/schema-doc/src/interactive.ts @@ -152,8 +152,11 @@ export interface TreebarkElementProps extends OptionalVariableControl { /** Static data object (optional) */ data?: object; - /** Template ID for markdown head syntax (e.g., ```treebark{templateId=foo}) */ - templateId?: string; + /** Register a template with this name for reuse (SET operation) */ + setTemplate?: string; + + /** Use a previously registered template by name (GET operation) */ + getTemplate?: string; /** Dynamic option: variableId to intake a signal and behave as data */ } diff --git a/packages/web-deploy/json/agentic-task-log.idoc.json b/packages/web-deploy/json/agentic-task-log.idoc.json index fc34d00a..23d44c69 100644 --- a/packages/web-deploy/json/agentic-task-log.idoc.json +++ b/packages/web-deploy/json/agentic-task-log.idoc.json @@ -350,7 +350,7 @@ { "type": "treebark", "variableId": "chatMessages", - "templateId": "chatBubble", + "setTemplate": "chatBubble", "template": { "div": { "class": "chat-container", @@ -451,7 +451,7 @@ { "type": "treebark", "variableId": "chatMessages2", - "template": "chatBubble" + "getTemplate": "chatBubble" }, "", { @@ -514,7 +514,7 @@ { "type": "treebark", "variableId": "chatMessages3", - "template": "chatBubble" + "getTemplate": "chatBubble" }, "", "", @@ -592,7 +592,7 @@ { "type": "treebark", "variableId": "chatMessages4", - "template": "chatBubble" + "getTemplate": "chatBubble" }, "", { From e3a0d3d1c20761610a1732be163f21062d23e153 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 10 Dec 2025 22:29:29 +0000 Subject: [PATCH 20/30] Use reusable templates for execution logs and replace variables with dataLoaders Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com> --- .../json/agentic-task-log.idoc.json | 249 ++++++------------ 1 file changed, 74 insertions(+), 175 deletions(-) diff --git a/packages/web-deploy/json/agentic-task-log.idoc.json b/packages/web-deploy/json/agentic-task-log.idoc.json index 23d44c69..6b01bdf1 100644 --- a/packages/web-deploy/json/agentic-task-log.idoc.json +++ b/packages/web-deploy/json/agentic-task-log.idoc.json @@ -40,12 +40,11 @@ ".chart-section h3 { margin: 0 0 15px 0; color: #2c3e50; font-size: 1.1em; }" ] }, - "variables": [ + "dataLoaders": [ { - "variableId": "chatMessages", - "type": "object", - "isArray": true, - "initialValue": [ + "dataLoaderId": "chatMessages", + "type": "json", + "data": [ { "sender": "User", "type": "user", @@ -59,15 +58,16 @@ ] }, { - "variableId": "executionLogs1", - "type": "object", - "isArray": true, - "initialValue": [ - { - "timestamp": "2024-11-19 10:15:23", - "level": "info", - "message": "Starting data analysis task..." - }, + "dataLoaderId": "executionLogs1", + "type": "json", + "data": { + "phase": "⚙️ Execution Phase 1: Data Loading & Validation", + "logs": [ + { + "timestamp": "2024-11-19 10:15:23", + "level": "info", + "message": "Starting data analysis task..." + }, { "timestamp": "2024-11-19 10:15:24", "level": "info", @@ -83,18 +83,18 @@ "level": "info", "message": "Performing data validation and cleaning..." }, - { - "timestamp": "2024-11-19 10:15:29", - "level": "success", - "message": "Data validation complete. No missing values detected." - } - ] + { + "timestamp": "2024-11-19 10:15:29", + "level": "success", + "message": "Data validation complete. No missing values detected." + } + ] + } }, { - "variableId": "chatMessages2", - "type": "object", - "isArray": true, - "initialValue": [ + "dataLoaderId": "chatMessages2", + "type": "json", + "data": [ { "sender": "Assistant", "type": "assistant", @@ -108,10 +108,11 @@ ] }, { - "variableId": "executionLogs2", - "type": "object", - "isArray": true, - "initialValue": [ + "dataLoaderId": "executionLogs2", + "type": "json", + "data": { + "phase": "⚙️ Execution Phase 2: Analysis & Visualization", + "logs": [ { "timestamp": "2024-11-19 10:16:05", "level": "info", @@ -142,18 +143,18 @@ "level": "info", "message": "Creating visualizations..." }, - { - "timestamp": "2024-11-19 10:16:18", - "level": "success", - "message": "Generated 3 charts: revenue_by_region.png, monthly_trends.png, top_products.png" - } - ] + { + "timestamp": "2024-11-19 10:16:18", + "level": "success", + "message": "Generated 3 charts: revenue_by_region.png, monthly_trends.png, top_products.png" + } + ] + } }, { - "variableId": "chatMessages3", - "type": "object", - "isArray": true, - "initialValue": [ + "dataLoaderId": "chatMessages3", + "type": "json", + "data": [ { "sender": "Assistant", "type": "assistant", @@ -167,15 +168,16 @@ ] }, { - "variableId": "executionLogs3", - "type": "object", - "isArray": true, - "initialValue": [ - { - "timestamp": "2024-11-19 10:17:30", - "level": "info", - "message": "Initiating report generation..." - }, + "dataLoaderId": "executionLogs3", + "type": "json", + "data": { + "phase": "⚙️ Execution Phase 3: Report Generation", + "logs": [ + { + "timestamp": "2024-11-19 10:17:30", + "level": "info", + "message": "Initiating report generation..." + }, { "timestamp": "2024-11-19 10:17:31", "level": "info", @@ -196,18 +198,18 @@ "level": "success", "message": "Report generated successfully: Q4_Sales_Report_2024.pdf (2.4 MB)" }, - { - "timestamp": "2024-11-19 10:17:43", - "level": "success", - "message": "Task completed in 4 minutes 20 seconds" - } - ] + { + "timestamp": "2024-11-19 10:17:43", + "level": "success", + "message": "Task completed in 4 minutes 20 seconds" + } + ] + } }, { - "variableId": "chatMessages4", - "type": "object", - "isArray": true, - "initialValue": [ + "dataLoaderId": "chatMessages4", + "type": "json", + "data": [ { "sender": "Assistant", "type": "assistant", @@ -222,9 +224,8 @@ }, { "variableId": "executionTimeByPhase", - "type": "object", - "isArray": true, - "initialValue": [ + "type": "json", + "data": [ { "phase": "Data Loading", "duration_seconds": 6, @@ -244,9 +245,8 @@ }, { "variableId": "logActivityOverTime", - "type": "object", - "isArray": true, - "initialValue": [ + "type": "json", + "data": [ { "timestamp": "10:15:23", "log_count": 1, @@ -393,7 +393,8 @@ "", { "type": "treebark", - "variableId": "executionLogs1", + "dataLoaderId": "executionLogs1", + "setTemplate": "executionLog", "template": { "div": { "class": "execution-log", @@ -401,13 +402,13 @@ { "h3": { "$children": [ - "\u2699\ufe0f Execution Phase 1: Data Loading & Validation" + "{{phase}}" ] } }, { "div": { - "$bind": ".", + "$bind": "logs", "$children": [ { "div": { @@ -450,70 +451,19 @@ "", { "type": "treebark", - "variableId": "chatMessages2", + "dataLoaderId": "chatMessages2", "getTemplate": "chatBubble" }, "", { "type": "treebark", - "variableId": "executionLogs2", - "template": { - "div": { - "class": "execution-log", - "$children": [ - { - "h3": { - "$children": [ - "\u2699\ufe0f Execution Phase 2: Analysis & Visualization" - ] - } - }, - { - "div": { - "$bind": ".", - "$children": [ - { - "div": { - "class": "log-entry", - "$children": [ - { - "span": { - "class": "log-timestamp", - "$children": [ - "[{{timestamp}}]" - ] - } - }, - { - "span": { - "class": "log-level-{{level}}", - "$children": [ - " {{level}}: " - ] - } - }, - { - "span": { - "class": "log-message", - "$children": [ - "{{message}}" - ] - } - } - ] - } - } - ] - } - } - ] - } - } + "dataLoaderId": "executionLogs2", + "getTemplate": "executionLog" }, "", { "type": "treebark", - "variableId": "chatMessages3", + "dataLoaderId": "chatMessages3", "getTemplate": "chatBubble" }, "", @@ -534,64 +484,13 @@ "", { "type": "treebark", - "variableId": "executionLogs3", - "template": { - "div": { - "class": "execution-log", - "$children": [ - { - "h3": { - "$children": [ - "\u2699\ufe0f Execution Phase 3: Report Generation" - ] - } - }, - { - "div": { - "$bind": ".", - "$children": [ - { - "div": { - "class": "log-entry", - "$children": [ - { - "span": { - "class": "log-timestamp", - "$children": [ - "[{{timestamp}}]" - ] - } - }, - { - "span": { - "class": "log-level-{{level}}", - "$children": [ - " {{level}}: " - ] - } - }, - { - "span": { - "class": "log-message", - "$children": [ - "{{message}}" - ] - } - } - ] - } - } - ] - } - } - ] - } - } + "dataLoaderId": "executionLogs3", + "getTemplate": "executionLog" }, "", { "type": "treebark", - "variableId": "chatMessages4", + "dataLoaderId": "chatMessages4", "getTemplate": "chatBubble" }, "", From dde4540c2c46de3a1796d22053548c4eeb36bf2a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 10 Dec 2025 22:38:51 +0000 Subject: [PATCH 21/30] Fix schema validation: use dataSourceName/content and variableId Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com> --- .../json/agentic-task-log.idoc.json | 66 +++++++++---------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/packages/web-deploy/json/agentic-task-log.idoc.json b/packages/web-deploy/json/agentic-task-log.idoc.json index 6b01bdf1..edca610b 100644 --- a/packages/web-deploy/json/agentic-task-log.idoc.json +++ b/packages/web-deploy/json/agentic-task-log.idoc.json @@ -42,9 +42,9 @@ }, "dataLoaders": [ { - "dataLoaderId": "chatMessages", - "type": "json", - "data": [ + "dataSourceName": "chatMessages", + "type": "inline", + "content": [ { "sender": "User", "type": "user", @@ -58,9 +58,9 @@ ] }, { - "dataLoaderId": "executionLogs1", - "type": "json", - "data": { + "dataSourceName": "executionLogs1", + "type": "inline", + "content": { "phase": "⚙️ Execution Phase 1: Data Loading & Validation", "logs": [ { @@ -92,9 +92,9 @@ } }, { - "dataLoaderId": "chatMessages2", - "type": "json", - "data": [ + "dataSourceName": "chatMessages2", + "type": "inline", + "content": [ { "sender": "Assistant", "type": "assistant", @@ -108,9 +108,9 @@ ] }, { - "dataLoaderId": "executionLogs2", - "type": "json", - "data": { + "dataSourceName": "executionLogs2", + "type": "inline", + "content": { "phase": "⚙️ Execution Phase 2: Analysis & Visualization", "logs": [ { @@ -152,9 +152,9 @@ } }, { - "dataLoaderId": "chatMessages3", - "type": "json", - "data": [ + "dataSourceName": "chatMessages3", + "type": "inline", + "content": [ { "sender": "Assistant", "type": "assistant", @@ -168,9 +168,9 @@ ] }, { - "dataLoaderId": "executionLogs3", - "type": "json", - "data": { + "dataSourceName": "executionLogs3", + "type": "inline", + "content": { "phase": "⚙️ Execution Phase 3: Report Generation", "logs": [ { @@ -207,9 +207,9 @@ } }, { - "dataLoaderId": "chatMessages4", - "type": "json", - "data": [ + "dataSourceName": "chatMessages4", + "type": "inline", + "content": [ { "sender": "Assistant", "type": "assistant", @@ -223,9 +223,9 @@ ] }, { - "variableId": "executionTimeByPhase", - "type": "json", - "data": [ + "dataSourceName": "executionTimeByPhase", + "type": "inline", + "content": [ { "phase": "Data Loading", "duration_seconds": 6, @@ -244,9 +244,9 @@ ] }, { - "variableId": "logActivityOverTime", - "type": "json", - "data": [ + "dataSourceName": "logActivityOverTime", + "type": "inline", + "content": [ { "timestamp": "10:15:23", "log_count": 1, @@ -393,7 +393,7 @@ "", { "type": "treebark", - "dataLoaderId": "executionLogs1", + "variableId": "executionLogs1", "setTemplate": "executionLog", "template": { "div": { @@ -451,19 +451,19 @@ "", { "type": "treebark", - "dataLoaderId": "chatMessages2", + "variableId": "chatMessages2", "getTemplate": "chatBubble" }, "", { "type": "treebark", - "dataLoaderId": "executionLogs2", + "variableId": "executionLogs2", "getTemplate": "executionLog" }, "", { "type": "treebark", - "dataLoaderId": "chatMessages3", + "variableId": "chatMessages3", "getTemplate": "chatBubble" }, "", @@ -484,13 +484,13 @@ "", { "type": "treebark", - "dataLoaderId": "executionLogs3", + "variableId": "executionLogs3", "getTemplate": "executionLog" }, "", { "type": "treebark", - "dataLoaderId": "chatMessages4", + "variableId": "chatMessages4", "getTemplate": "chatBubble" }, "", From 7e94893ae2db0e435efd2edba589f2c3624a6600 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 10 Dec 2025 22:44:31 +0000 Subject: [PATCH 22/30] Wrap execution log content in arrays as required by schema Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com> --- .../json/agentic-task-log.idoc.json | 275 +++++++++--------- 1 file changed, 144 insertions(+), 131 deletions(-) diff --git a/packages/web-deploy/json/agentic-task-log.idoc.json b/packages/web-deploy/json/agentic-task-log.idoc.json index edca610b..f6eb4d5d 100644 --- a/packages/web-deploy/json/agentic-task-log.idoc.json +++ b/packages/web-deploy/json/agentic-task-log.idoc.json @@ -60,36 +60,38 @@ { "dataSourceName": "executionLogs1", "type": "inline", - "content": { - "phase": "⚙️ Execution Phase 1: Data Loading & Validation", - "logs": [ - { - "timestamp": "2024-11-19 10:15:23", - "level": "info", - "message": "Starting data analysis task..." - }, - { - "timestamp": "2024-11-19 10:15:24", - "level": "info", - "message": "Loading dataset: sales_q4_2024.csv" - }, - { - "timestamp": "2024-11-19 10:15:26", - "level": "success", - "message": "Dataset loaded successfully (15,234 rows, 12 columns)" - }, + "content": [ { - "timestamp": "2024-11-19 10:15:27", - "level": "info", - "message": "Performing data validation and cleaning..." - }, - { - "timestamp": "2024-11-19 10:15:29", - "level": "success", - "message": "Data validation complete. No missing values detected." - } - ] - } + "phase": "⚙️ Execution Phase 1: Data Loading & Validation", + "logs": [ + { + "timestamp": "2024-11-19 10:15:23", + "level": "info", + "message": "Starting data analysis task..." + }, + { + "timestamp": "2024-11-19 10:15:24", + "level": "info", + "message": "Loading dataset: sales_q4_2024.csv" + }, + { + "timestamp": "2024-11-19 10:15:26", + "level": "success", + "message": "Dataset loaded successfully (15,234 rows, 12 columns)" + }, + { + "timestamp": "2024-11-19 10:15:27", + "level": "info", + "message": "Performing data validation and cleaning..." + }, + { + "timestamp": "2024-11-19 10:15:29", + "level": "success", + "message": "Data validation complete. No missing values detected." + } + ] + } + ] }, { "dataSourceName": "chatMessages2", @@ -110,46 +112,48 @@ { "dataSourceName": "executionLogs2", "type": "inline", - "content": { - "phase": "⚙️ Execution Phase 2: Analysis & Visualization", - "logs": [ - { - "timestamp": "2024-11-19 10:16:05", - "level": "info", - "message": "Computing aggregate statistics..." - }, - { - "timestamp": "2024-11-19 10:16:07", - "level": "info", - "message": "Grouping data by region: North, South, East, West" - }, - { - "timestamp": "2024-11-19 10:16:09", - "level": "success", - "message": "Regional analysis complete" - }, - { - "timestamp": "2024-11-19 10:16:10", - "level": "info", - "message": "Generating revenue trends by month..." - }, - { - "timestamp": "2024-11-19 10:16:13", - "level": "success", - "message": "Trend analysis complete" - }, + "content": [ { - "timestamp": "2024-11-19 10:16:14", - "level": "info", - "message": "Creating visualizations..." - }, - { - "timestamp": "2024-11-19 10:16:18", - "level": "success", - "message": "Generated 3 charts: revenue_by_region.png, monthly_trends.png, top_products.png" - } - ] - } + "phase": "⚙️ Execution Phase 2: Analysis & Visualization", + "logs": [ + { + "timestamp": "2024-11-19 10:16:05", + "level": "info", + "message": "Computing aggregate statistics..." + }, + { + "timestamp": "2024-11-19 10:16:07", + "level": "info", + "message": "Grouping data by region: North, South, East, West" + }, + { + "timestamp": "2024-11-19 10:16:09", + "level": "success", + "message": "Regional analysis complete" + }, + { + "timestamp": "2024-11-19 10:16:10", + "level": "info", + "message": "Generating revenue trends by month..." + }, + { + "timestamp": "2024-11-19 10:16:13", + "level": "success", + "message": "Trend analysis complete" + }, + { + "timestamp": "2024-11-19 10:16:14", + "level": "info", + "message": "Creating visualizations..." + }, + { + "timestamp": "2024-11-19 10:16:18", + "level": "success", + "message": "Generated 3 charts: revenue_by_region.png, monthly_trends.png, top_products.png" + } + ] + } + ] }, { "dataSourceName": "chatMessages3", @@ -170,41 +174,43 @@ { "dataSourceName": "executionLogs3", "type": "inline", - "content": { - "phase": "⚙️ Execution Phase 3: Report Generation", - "logs": [ - { - "timestamp": "2024-11-19 10:17:30", - "level": "info", - "message": "Initiating report generation..." - }, - { - "timestamp": "2024-11-19 10:17:31", - "level": "info", - "message": "Compiling data summaries and insights..." - }, - { - "timestamp": "2024-11-19 10:17:33", - "level": "info", - "message": "Embedding visualizations into report template..." - }, - { - "timestamp": "2024-11-19 10:17:38", - "level": "info", - "message": "Rendering report to PDF format..." - }, + "content": [ { - "timestamp": "2024-11-19 10:17:42", - "level": "success", - "message": "Report generated successfully: Q4_Sales_Report_2024.pdf (2.4 MB)" - }, - { - "timestamp": "2024-11-19 10:17:43", - "level": "success", - "message": "Task completed in 4 minutes 20 seconds" - } - ] - } + "phase": "⚙️ Execution Phase 3: Report Generation", + "logs": [ + { + "timestamp": "2024-11-19 10:17:30", + "level": "info", + "message": "Initiating report generation..." + }, + { + "timestamp": "2024-11-19 10:17:31", + "level": "info", + "message": "Compiling data summaries and insights..." + }, + { + "timestamp": "2024-11-19 10:17:33", + "level": "info", + "message": "Embedding visualizations into report template..." + }, + { + "timestamp": "2024-11-19 10:17:38", + "level": "info", + "message": "Rendering report to PDF format..." + }, + { + "timestamp": "2024-11-19 10:17:42", + "level": "success", + "message": "Report generated successfully: Q4_Sales_Report_2024.pdf (2.4 MB)" + }, + { + "timestamp": "2024-11-19 10:17:43", + "level": "success", + "message": "Task completed in 4 minutes 20 seconds" + } + ] + } + ] }, { "dataSourceName": "chatMessages4", @@ -397,44 +403,51 @@ "setTemplate": "executionLog", "template": { "div": { - "class": "execution-log", + "$bind": ".", "$children": [ - { - "h3": { - "$children": [ - "{{phase}}" - ] - } - }, { "div": { - "$bind": "logs", + "class": "execution-log", "$children": [ + { + "h3": { + "$children": [ + "{{phase}}" + ] + } + }, { "div": { - "class": "log-entry", + "$bind": "logs", "$children": [ { - "span": { - "class": "log-timestamp", - "$children": [ - "[{{timestamp}}]" - ] - } - }, - { - "span": { - "class": "log-level-{{level}}", - "$children": [ - " {{level}}: " - ] - } - }, - { - "span": { - "class": "log-message", + "div": { + "class": "log-entry", "$children": [ - "{{message}}" + { + "span": { + "class": "log-timestamp", + "$children": [ + "[{{timestamp}}]" + ] + } + }, + { + "span": { + "class": "log-level-{{level}}", + "$children": [ + " {{level}}: " + ] + } + }, + { + "span": { + "class": "log-message", + "$children": [ + "{{message}}" + ] + } + } ] } } From 16ecc87745a7748e0b94231b29a49bb5280cecbb Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 10 Dec 2025 22:47:32 +0000 Subject: [PATCH 23/30] Use Vega formula transform to add phase field instead of nesting data Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com> --- .../json/agentic-task-log.idoc.json | 269 +++++++++--------- 1 file changed, 134 insertions(+), 135 deletions(-) diff --git a/packages/web-deploy/json/agentic-task-log.idoc.json b/packages/web-deploy/json/agentic-task-log.idoc.json index f6eb4d5d..4605f543 100644 --- a/packages/web-deploy/json/agentic-task-log.idoc.json +++ b/packages/web-deploy/json/agentic-task-log.idoc.json @@ -62,34 +62,36 @@ "type": "inline", "content": [ { - "phase": "⚙️ Execution Phase 1: Data Loading & Validation", - "logs": [ - { - "timestamp": "2024-11-19 10:15:23", - "level": "info", - "message": "Starting data analysis task..." - }, - { - "timestamp": "2024-11-19 10:15:24", - "level": "info", - "message": "Loading dataset: sales_q4_2024.csv" - }, - { - "timestamp": "2024-11-19 10:15:26", - "level": "success", - "message": "Dataset loaded successfully (15,234 rows, 12 columns)" - }, - { - "timestamp": "2024-11-19 10:15:27", - "level": "info", - "message": "Performing data validation and cleaning..." - }, - { - "timestamp": "2024-11-19 10:15:29", - "level": "success", - "message": "Data validation complete. No missing values detected." - } - ] + "timestamp": "2024-11-19 10:15:23", + "level": "info", + "message": "Starting data analysis task..." + }, + { + "timestamp": "2024-11-19 10:15:24", + "level": "info", + "message": "Loading dataset: sales_q4_2024.csv" + }, + { + "timestamp": "2024-11-19 10:15:26", + "level": "success", + "message": "Dataset loaded successfully (15,234 rows, 12 columns)" + }, + { + "timestamp": "2024-11-19 10:15:27", + "level": "info", + "message": "Performing data validation and cleaning..." + }, + { + "timestamp": "2024-11-19 10:15:29", + "level": "success", + "message": "Data validation complete. No missing values detected." + } + ], + "dataFrameTransformations": [ + { + "type": "formula", + "as": "phase", + "expr": "'⚙️ Execution Phase 1: Data Loading & Validation'" } ] }, @@ -114,44 +116,46 @@ "type": "inline", "content": [ { - "phase": "⚙️ Execution Phase 2: Analysis & Visualization", - "logs": [ - { - "timestamp": "2024-11-19 10:16:05", - "level": "info", - "message": "Computing aggregate statistics..." - }, - { - "timestamp": "2024-11-19 10:16:07", - "level": "info", - "message": "Grouping data by region: North, South, East, West" - }, - { - "timestamp": "2024-11-19 10:16:09", - "level": "success", - "message": "Regional analysis complete" - }, - { - "timestamp": "2024-11-19 10:16:10", - "level": "info", - "message": "Generating revenue trends by month..." - }, - { - "timestamp": "2024-11-19 10:16:13", - "level": "success", - "message": "Trend analysis complete" - }, - { - "timestamp": "2024-11-19 10:16:14", - "level": "info", - "message": "Creating visualizations..." - }, - { - "timestamp": "2024-11-19 10:16:18", - "level": "success", - "message": "Generated 3 charts: revenue_by_region.png, monthly_trends.png, top_products.png" - } - ] + "timestamp": "2024-11-19 10:16:05", + "level": "info", + "message": "Computing aggregate statistics..." + }, + { + "timestamp": "2024-11-19 10:16:07", + "level": "info", + "message": "Grouping data by region: North, South, East, West" + }, + { + "timestamp": "2024-11-19 10:16:09", + "level": "success", + "message": "Regional analysis complete" + }, + { + "timestamp": "2024-11-19 10:16:10", + "level": "info", + "message": "Generating revenue trends by month..." + }, + { + "timestamp": "2024-11-19 10:16:13", + "level": "success", + "message": "Trend analysis complete" + }, + { + "timestamp": "2024-11-19 10:16:14", + "level": "info", + "message": "Creating visualizations..." + }, + { + "timestamp": "2024-11-19 10:16:18", + "level": "success", + "message": "Generated 3 charts: revenue_by_region.png, monthly_trends.png, top_products.png" + } + ], + "dataFrameTransformations": [ + { + "type": "formula", + "as": "phase", + "expr": "'⚙️ Execution Phase 2: Analysis & Visualization'" } ] }, @@ -176,39 +180,41 @@ "type": "inline", "content": [ { - "phase": "⚙️ Execution Phase 3: Report Generation", - "logs": [ - { - "timestamp": "2024-11-19 10:17:30", - "level": "info", - "message": "Initiating report generation..." - }, - { - "timestamp": "2024-11-19 10:17:31", - "level": "info", - "message": "Compiling data summaries and insights..." - }, - { - "timestamp": "2024-11-19 10:17:33", - "level": "info", - "message": "Embedding visualizations into report template..." - }, - { - "timestamp": "2024-11-19 10:17:38", - "level": "info", - "message": "Rendering report to PDF format..." - }, - { - "timestamp": "2024-11-19 10:17:42", - "level": "success", - "message": "Report generated successfully: Q4_Sales_Report_2024.pdf (2.4 MB)" - }, - { - "timestamp": "2024-11-19 10:17:43", - "level": "success", - "message": "Task completed in 4 minutes 20 seconds" - } - ] + "timestamp": "2024-11-19 10:17:30", + "level": "info", + "message": "Initiating report generation..." + }, + { + "timestamp": "2024-11-19 10:17:31", + "level": "info", + "message": "Compiling data summaries and insights..." + }, + { + "timestamp": "2024-11-19 10:17:33", + "level": "info", + "message": "Embedding visualizations into report template..." + }, + { + "timestamp": "2024-11-19 10:17:38", + "level": "info", + "message": "Rendering report to PDF format..." + }, + { + "timestamp": "2024-11-19 10:17:42", + "level": "success", + "message": "Report generated successfully: Q4_Sales_Report_2024.pdf (2.4 MB)" + }, + { + "timestamp": "2024-11-19 10:17:43", + "level": "success", + "message": "Task completed in 4 minutes 20 seconds" + } + ], + "dataFrameTransformations": [ + { + "type": "formula", + "as": "phase", + "expr": "'⚙️ Execution Phase 3: Report Generation'" } ] }, @@ -403,51 +409,44 @@ "setTemplate": "executionLog", "template": { "div": { - "$bind": ".", + "class": "execution-log", "$children": [ + { + "h3": { + "$children": [ + "{{0.phase}}" + ] + } + }, { "div": { - "class": "execution-log", + "$bind": ".", "$children": [ - { - "h3": { - "$children": [ - "{{phase}}" - ] - } - }, { "div": { - "$bind": "logs", + "class": "log-entry", "$children": [ { - "div": { - "class": "log-entry", + "span": { + "class": "log-timestamp", + "$children": [ + "[{{timestamp}}]" + ] + } + }, + { + "span": { + "class": "log-level-{{level}}", "$children": [ - { - "span": { - "class": "log-timestamp", - "$children": [ - "[{{timestamp}}]" - ] - } - }, - { - "span": { - "class": "log-level-{{level}}", - "$children": [ - " {{level}}: " - ] - } - }, - { - "span": { - "class": "log-message", - "$children": [ - "{{message}}" - ] - } - } + " {{level}}: " + ] + } + }, + { + "span": { + "class": "log-message", + "$children": [ + "{{message}}" ] } } From 075e4e92320606d7d08852757611252b43062cdf Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 10 Dec 2025 22:52:58 +0000 Subject: [PATCH 24/30] Consolidate execution logs into single phases array data source Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com> --- .../json/agentic-task-log.idoc.json | 243 ++++++++---------- 1 file changed, 107 insertions(+), 136 deletions(-) diff --git a/packages/web-deploy/json/agentic-task-log.idoc.json b/packages/web-deploy/json/agentic-task-log.idoc.json index 4605f543..77488a6f 100644 --- a/packages/web-deploy/json/agentic-task-log.idoc.json +++ b/packages/web-deploy/json/agentic-task-log.idoc.json @@ -58,40 +58,113 @@ ] }, { - "dataSourceName": "executionLogs1", + "dataSourceName": "executionPhases", "type": "inline", "content": [ { - "timestamp": "2024-11-19 10:15:23", - "level": "info", - "message": "Starting data analysis task..." - }, - { - "timestamp": "2024-11-19 10:15:24", - "level": "info", - "message": "Loading dataset: sales_q4_2024.csv" - }, - { - "timestamp": "2024-11-19 10:15:26", - "level": "success", - "message": "Dataset loaded successfully (15,234 rows, 12 columns)" + "phase": "⚙️ Execution Phase 1: Data Loading & Validation", + "logs": [ + { + "timestamp": "2024-11-19 10:15:23", + "level": "info", + "message": "Starting data analysis task..." + }, + { + "timestamp": "2024-11-19 10:15:24", + "level": "info", + "message": "Loading dataset: sales_q4_2024.csv" + }, + { + "timestamp": "2024-11-19 10:15:26", + "level": "success", + "message": "Dataset loaded successfully (15,234 rows, 12 columns)" + }, + { + "timestamp": "2024-11-19 10:15:27", + "level": "info", + "message": "Performing data validation and cleaning..." + }, + { + "timestamp": "2024-11-19 10:15:29", + "level": "success", + "message": "Data validation complete. No missing values detected." + } + ] }, { - "timestamp": "2024-11-19 10:15:27", - "level": "info", - "message": "Performing data validation and cleaning..." + "phase": "⚙️ Execution Phase 2: Analysis & Visualization", + "logs": [ + { + "timestamp": "2024-11-19 10:16:05", + "level": "info", + "message": "Computing aggregate statistics..." + }, + { + "timestamp": "2024-11-19 10:16:07", + "level": "info", + "message": "Grouping data by region: North, South, East, West" + }, + { + "timestamp": "2024-11-19 10:16:09", + "level": "success", + "message": "Regional analysis complete" + }, + { + "timestamp": "2024-11-19 10:16:10", + "level": "info", + "message": "Generating revenue trends by month..." + }, + { + "timestamp": "2024-11-19 10:16:13", + "level": "success", + "message": "Trend analysis complete" + }, + { + "timestamp": "2024-11-19 10:16:14", + "level": "info", + "message": "Creating visualizations..." + }, + { + "timestamp": "2024-11-19 10:16:18", + "level": "success", + "message": "Generated 3 charts: revenue_by_region.png, monthly_trends.png, top_products.png" + } + ] }, { - "timestamp": "2024-11-19 10:15:29", - "level": "success", - "message": "Data validation complete. No missing values detected." - } - ], - "dataFrameTransformations": [ - { - "type": "formula", - "as": "phase", - "expr": "'⚙️ Execution Phase 1: Data Loading & Validation'" + "phase": "⚙️ Execution Phase 3: Report Generation", + "logs": [ + { + "timestamp": "2024-11-19 10:17:30", + "level": "info", + "message": "Initiating report generation..." + }, + { + "timestamp": "2024-11-19 10:17:31", + "level": "info", + "message": "Compiling data summaries and insights..." + }, + { + "timestamp": "2024-11-19 10:17:33", + "level": "info", + "message": "Embedding visualizations into report template..." + }, + { + "timestamp": "2024-11-19 10:17:38", + "level": "info", + "message": "Rendering report to PDF format..." + }, + { + "timestamp": "2024-11-19 10:17:42", + "level": "success", + "message": "Report generated successfully: Q4_Sales_Report_2024.pdf (2.4 MB)" + }, + { + "timestamp": "2024-11-19 10:17:43", + "level": "success", + "message": "Task completed in 4 minutes 20 seconds" + } + ] } ] }, @@ -111,54 +184,6 @@ } ] }, - { - "dataSourceName": "executionLogs2", - "type": "inline", - "content": [ - { - "timestamp": "2024-11-19 10:16:05", - "level": "info", - "message": "Computing aggregate statistics..." - }, - { - "timestamp": "2024-11-19 10:16:07", - "level": "info", - "message": "Grouping data by region: North, South, East, West" - }, - { - "timestamp": "2024-11-19 10:16:09", - "level": "success", - "message": "Regional analysis complete" - }, - { - "timestamp": "2024-11-19 10:16:10", - "level": "info", - "message": "Generating revenue trends by month..." - }, - { - "timestamp": "2024-11-19 10:16:13", - "level": "success", - "message": "Trend analysis complete" - }, - { - "timestamp": "2024-11-19 10:16:14", - "level": "info", - "message": "Creating visualizations..." - }, - { - "timestamp": "2024-11-19 10:16:18", - "level": "success", - "message": "Generated 3 charts: revenue_by_region.png, monthly_trends.png, top_products.png" - } - ], - "dataFrameTransformations": [ - { - "type": "formula", - "as": "phase", - "expr": "'⚙️ Execution Phase 2: Analysis & Visualization'" - } - ] - }, { "dataSourceName": "chatMessages3", "type": "inline", @@ -175,49 +200,6 @@ } ] }, - { - "dataSourceName": "executionLogs3", - "type": "inline", - "content": [ - { - "timestamp": "2024-11-19 10:17:30", - "level": "info", - "message": "Initiating report generation..." - }, - { - "timestamp": "2024-11-19 10:17:31", - "level": "info", - "message": "Compiling data summaries and insights..." - }, - { - "timestamp": "2024-11-19 10:17:33", - "level": "info", - "message": "Embedding visualizations into report template..." - }, - { - "timestamp": "2024-11-19 10:17:38", - "level": "info", - "message": "Rendering report to PDF format..." - }, - { - "timestamp": "2024-11-19 10:17:42", - "level": "success", - "message": "Report generated successfully: Q4_Sales_Report_2024.pdf (2.4 MB)" - }, - { - "timestamp": "2024-11-19 10:17:43", - "level": "success", - "message": "Task completed in 4 minutes 20 seconds" - } - ], - "dataFrameTransformations": [ - { - "type": "formula", - "as": "phase", - "expr": "'⚙️ Execution Phase 3: Report Generation'" - } - ] - }, { "dataSourceName": "chatMessages4", "type": "inline", @@ -405,22 +387,23 @@ "", { "type": "treebark", - "variableId": "executionLogs1", - "setTemplate": "executionLog", + "variableId": "executionPhases", "template": { "div": { - "class": "execution-log", + "$bind": ".", "$children": [ { - "h3": { + "div": { + "class": "phase-indicator", "$children": [ - "{{0.phase}}" + "{{phase}}" ] } }, { "div": { - "$bind": ".", + "class": "execution-log", + "$bind": "logs", "$children": [ { "div": { @@ -467,12 +450,6 @@ "getTemplate": "chatBubble" }, "", - { - "type": "treebark", - "variableId": "executionLogs2", - "getTemplate": "executionLog" - }, - "", { "type": "treebark", "variableId": "chatMessages3", @@ -494,12 +471,6 @@ "chartKey": "logActivityChart" }, "", - { - "type": "treebark", - "variableId": "executionLogs3", - "getTemplate": "executionLog" - }, - "", { "type": "treebark", "variableId": "chatMessages4", From e3cacf9111076960ed666bd8e4fa6f39758ddb82 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 10 Dec 2025 23:32:50 +0000 Subject: [PATCH 25/30] Update compiler validation for treebark setTemplate/getTemplate Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com> --- packages/compiler/src/validate/element.ts | 42 ++++++++++++++++++++--- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/packages/compiler/src/validate/element.ts b/packages/compiler/src/validate/element.ts index a8b3307b..2623271a 100644 --- a/packages/compiler/src/validate/element.ts +++ b/packages/compiler/src/validate/element.ts @@ -137,11 +137,33 @@ export async function validateElement(element: PageElement, groupIndex: number, case 'treebark': { const treebarkElement = element as TreebarkElement; - // Template is required - if (!treebarkElement.template) { - errors.push('Treebark element must have a template property'); - } else { - errors.push(...validateOptionalObject(treebarkElement.template, 'template', 'Treebark')); + // Validate: either template, setTemplate, or getTemplate must be present + if (!treebarkElement.template && !treebarkElement.setTemplate && !treebarkElement.getTemplate) { + errors.push('Treebark element must have either template, setTemplate, or getTemplate'); + } + + // Validate: setTemplate and getTemplate are mutually exclusive + if (treebarkElement.setTemplate && treebarkElement.getTemplate) { + errors.push('Treebark element cannot have both setTemplate and getTemplate'); + } + + // Validate: setTemplate requires template + if (treebarkElement.setTemplate && !treebarkElement.template) { + errors.push('Treebark element with setTemplate must have a template property'); + } + + // Validate: getTemplate should not have template + if (treebarkElement.getTemplate && treebarkElement.template) { + errors.push('Treebark element with getTemplate should not have a template property (it references an existing template)'); + } + + // Validate template if present - can be object or string + if (treebarkElement.template !== undefined) { + if (typeof treebarkElement.template !== 'object' && typeof treebarkElement.template !== 'string') { + errors.push('Treebark element template must be an object or a string'); + } else if (typeof treebarkElement.template === 'object' && treebarkElement.template !== null) { + errors.push(...validateOptionalObject(treebarkElement.template, 'template', 'Treebark')); + } } // Validate data if present @@ -153,6 +175,16 @@ export async function validateElement(element: PageElement, groupIndex: number, if (treebarkElement.variableId) { errors.push(...validateVariableID(treebarkElement.variableId)); } + + // Validate setTemplate if present + if (treebarkElement.setTemplate) { + errors.push(...validateRequiredString(treebarkElement.setTemplate, 'setTemplate', 'Treebark')); + } + + // Validate getTemplate if present + if (treebarkElement.getTemplate) { + errors.push(...validateRequiredString(treebarkElement.getTemplate, 'getTemplate', 'Treebark')); + } break; } From 1f072e6de9e50221e943b08fa4568594f16808d9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 11 Dec 2025 00:20:27 +0000 Subject: [PATCH 26/30] Fix validation logic order and improve error message clarity Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com> --- packages/compiler/src/validate/element.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/compiler/src/validate/element.ts b/packages/compiler/src/validate/element.ts index 2623271a..51d0273c 100644 --- a/packages/compiler/src/validate/element.ts +++ b/packages/compiler/src/validate/element.ts @@ -137,16 +137,16 @@ export async function validateElement(element: PageElement, groupIndex: number, case 'treebark': { const treebarkElement = element as TreebarkElement; - // Validate: either template, setTemplate, or getTemplate must be present - if (!treebarkElement.template && !treebarkElement.setTemplate && !treebarkElement.getTemplate) { - errors.push('Treebark element must have either template, setTemplate, or getTemplate'); - } - - // Validate: setTemplate and getTemplate are mutually exclusive + // Validate: setTemplate and getTemplate are mutually exclusive (check first) if (treebarkElement.setTemplate && treebarkElement.getTemplate) { errors.push('Treebark element cannot have both setTemplate and getTemplate'); } + // Validate: at least one of template, setTemplate, or getTemplate must be present + if (!treebarkElement.template && !treebarkElement.setTemplate && !treebarkElement.getTemplate) { + errors.push('Treebark element must have at least one of: template, setTemplate, or getTemplate'); + } + // Validate: setTemplate requires template if (treebarkElement.setTemplate && !treebarkElement.template) { errors.push('Treebark element with setTemplate must have a template property'); From 2299b475516e13c4cdff5f9ce72f1dec656bee5c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 11 Dec 2025 01:45:28 +0000 Subject: [PATCH 27/30] Relax validation: reorder checks to show clearer error messages for treebark Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com> --- packages/compiler/src/validate/element.ts | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/compiler/src/validate/element.ts b/packages/compiler/src/validate/element.ts index 51d0273c..fe561e07 100644 --- a/packages/compiler/src/validate/element.ts +++ b/packages/compiler/src/validate/element.ts @@ -142,11 +142,6 @@ export async function validateElement(element: PageElement, groupIndex: number, errors.push('Treebark element cannot have both setTemplate and getTemplate'); } - // Validate: at least one of template, setTemplate, or getTemplate must be present - if (!treebarkElement.template && !treebarkElement.setTemplate && !treebarkElement.getTemplate) { - errors.push('Treebark element must have at least one of: template, setTemplate, or getTemplate'); - } - // Validate: setTemplate requires template if (treebarkElement.setTemplate && !treebarkElement.template) { errors.push('Treebark element with setTemplate must have a template property'); @@ -157,6 +152,12 @@ export async function validateElement(element: PageElement, groupIndex: number, errors.push('Treebark element with getTemplate should not have a template property (it references an existing template)'); } + // Validate: at least one of template, setTemplate, or getTemplate must be present + // (Check this after setTemplate/getTemplate-specific validations to avoid confusing messages) + if (!treebarkElement.template && !treebarkElement.setTemplate && !treebarkElement.getTemplate) { + errors.push('Treebark element must have at least one of: template, setTemplate, or getTemplate'); + } + // Validate template if present - can be object or string if (treebarkElement.template !== undefined) { if (typeof treebarkElement.template !== 'object' && typeof treebarkElement.template !== 'string') { From 583e0763b73d82707dff140e0034375633a7bf32 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 11 Dec 2025 16:37:22 +0000 Subject: [PATCH 28/30] Add reusable template example to treebark primer document Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com> --- .../json/features/11.treebark.idoc.json | 94 +++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/packages/web-deploy/json/features/11.treebark.idoc.json b/packages/web-deploy/json/features/11.treebark.idoc.json index e12ce378..b36d0330 100644 --- a/packages/web-deploy/json/features/11.treebark.idoc.json +++ b/packages/web-deploy/json/features/11.treebark.idoc.json @@ -301,6 +301,100 @@ } ] }, + { + "groupId": "reusable-templates", + "elements": [ + "## Reusable Templates", + "Templates can be defined once and reused multiple times with different data sources. Use `setTemplate` to register a template and `getTemplate` to reference it:", + { + "type": "treebark", + "setTemplate": "memberCard", + "template": { + "div": { + "class": "card", + "$children": [ + { + "div": { + "class": "card-header", + "$children": [ + "{{name}}" + ] + } + }, + { + "div": { + "class": "card-body", + "$children": [ + { + "p": { + "$children": [ + { + "strong": { + "$children": [ + "Role: " + ] + } + }, + "{{role}}" + ] + } + }, + { + "p": { + "$children": [ + { + "strong": { + "$children": [ + "Score: " + ] + } + }, + { + "span": { + "class": "score-{{status}}", + "$children": [ + "{{score}}" + ] + } + } + ] + } + }, + { + "p": { + "$children": [ + { + "span": { + "class": "badge badge-{{status}}", + "$children": [ + "{{status}}" + ] + } + } + ] + } + } + ] + } + } + ] + } + }, + "variableId": "teamMembers" + }, + "The same template can be reused with `getTemplate` for different data sources (templates are pure presentation and don't carry data bindings):", + { + "type": "treebark", + "getTemplate": "memberCard", + "variableId": "teamMembers" + }, + "### Benefits of Reusable Templates", + "- **DRY Principle**: Define once, use many times", + "- **Maintainability**: Update the template in one place", + "- **Pure Presentation**: Templates don't carry data, only structure", + "- **Clear Intent**: `setTemplate` and `getTemplate` make template usage explicit" + ] + }, { "groupId": "learn-more", "elements": [ From f34bb14854754c9b220a6e29002f599503180356 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 11 Dec 2025 18:16:37 +0000 Subject: [PATCH 29/30] Add setTemplate and getTemplate to compiler markdown output Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com> --- packages/compiler/src/md.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/compiler/src/md.ts b/packages/compiler/src/md.ts index 1c49d9fd..c636e9aa 100644 --- a/packages/compiler/src/md.ts +++ b/packages/compiler/src/md.ts @@ -306,7 +306,7 @@ function groupMarkdown(group: ElementGroup, variables: Variable[], vegaScope: Ve break; } case 'treebark': { - const { template, data, variableId } = element; + const { template, data, variableId, setTemplate, getTemplate } = element; const treebarkSpec: Plugins.TreebarkSpec = { template, }; @@ -316,6 +316,12 @@ function groupMarkdown(group: ElementGroup, variables: Variable[], vegaScope: Ve if (variableId) { treebarkSpec.variableId = variableId; } + if (setTemplate) { + treebarkSpec.setTemplate = setTemplate; + } + if (getTemplate) { + treebarkSpec.getTemplate = getTemplate; + } addSpec('treebark', treebarkSpec); break; } From 1f3d7c28a695a553e32ee1c8a3fa49392caea789 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 11 Dec 2025 23:14:49 +0000 Subject: [PATCH 30/30] Fix execution phases: use flat arrays and add phase headers to markdown Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com> --- .../json/agentic-task-log.idoc.json | 356 +++++++++++------- 1 file changed, 222 insertions(+), 134 deletions(-) diff --git a/packages/web-deploy/json/agentic-task-log.idoc.json b/packages/web-deploy/json/agentic-task-log.idoc.json index 77488a6f..96792acc 100644 --- a/packages/web-deploy/json/agentic-task-log.idoc.json +++ b/packages/web-deploy/json/agentic-task-log.idoc.json @@ -58,113 +58,110 @@ ] }, { - "dataSourceName": "executionPhases", + "dataSourceName": "executionLogs1", "type": "inline", "content": [ { - "phase": "⚙️ Execution Phase 1: Data Loading & Validation", - "logs": [ - { - "timestamp": "2024-11-19 10:15:23", - "level": "info", - "message": "Starting data analysis task..." - }, - { - "timestamp": "2024-11-19 10:15:24", - "level": "info", - "message": "Loading dataset: sales_q4_2024.csv" - }, - { - "timestamp": "2024-11-19 10:15:26", - "level": "success", - "message": "Dataset loaded successfully (15,234 rows, 12 columns)" - }, - { - "timestamp": "2024-11-19 10:15:27", - "level": "info", - "message": "Performing data validation and cleaning..." - }, - { - "timestamp": "2024-11-19 10:15:29", - "level": "success", - "message": "Data validation complete. No missing values detected." - } - ] + "timestamp": "2024-11-19 10:15:23", + "level": "info", + "message": "Starting data analysis task..." }, { - "phase": "⚙️ Execution Phase 2: Analysis & Visualization", - "logs": [ - { - "timestamp": "2024-11-19 10:16:05", - "level": "info", - "message": "Computing aggregate statistics..." - }, - { - "timestamp": "2024-11-19 10:16:07", - "level": "info", - "message": "Grouping data by region: North, South, East, West" - }, - { - "timestamp": "2024-11-19 10:16:09", - "level": "success", - "message": "Regional analysis complete" - }, - { - "timestamp": "2024-11-19 10:16:10", - "level": "info", - "message": "Generating revenue trends by month..." - }, - { - "timestamp": "2024-11-19 10:16:13", - "level": "success", - "message": "Trend analysis complete" - }, - { - "timestamp": "2024-11-19 10:16:14", - "level": "info", - "message": "Creating visualizations..." - }, - { - "timestamp": "2024-11-19 10:16:18", - "level": "success", - "message": "Generated 3 charts: revenue_by_region.png, monthly_trends.png, top_products.png" - } - ] + "timestamp": "2024-11-19 10:15:24", + "level": "info", + "message": "Loading dataset: sales_q4_2024.csv" }, { - "phase": "⚙️ Execution Phase 3: Report Generation", - "logs": [ - { - "timestamp": "2024-11-19 10:17:30", - "level": "info", - "message": "Initiating report generation..." - }, - { - "timestamp": "2024-11-19 10:17:31", - "level": "info", - "message": "Compiling data summaries and insights..." - }, - { - "timestamp": "2024-11-19 10:17:33", - "level": "info", - "message": "Embedding visualizations into report template..." - }, - { - "timestamp": "2024-11-19 10:17:38", - "level": "info", - "message": "Rendering report to PDF format..." - }, - { - "timestamp": "2024-11-19 10:17:42", - "level": "success", - "message": "Report generated successfully: Q4_Sales_Report_2024.pdf (2.4 MB)" - }, - { - "timestamp": "2024-11-19 10:17:43", - "level": "success", - "message": "Task completed in 4 minutes 20 seconds" - } - ] + "timestamp": "2024-11-19 10:15:26", + "level": "success", + "message": "Dataset loaded successfully (15,234 rows, 12 columns)" + }, + { + "timestamp": "2024-11-19 10:15:27", + "level": "info", + "message": "Performing data validation and cleaning..." + }, + { + "timestamp": "2024-11-19 10:15:29", + "level": "success", + "message": "Data validation complete. No missing values detected." + } + ] + }, + { + "dataSourceName": "executionLogs2", + "type": "inline", + "content": [ + { + "timestamp": "2024-11-19 10:16:05", + "level": "info", + "message": "Computing aggregate statistics..." + }, + { + "timestamp": "2024-11-19 10:16:07", + "level": "info", + "message": "Grouping data by region: North, South, East, West" + }, + { + "timestamp": "2024-11-19 10:16:09", + "level": "success", + "message": "Regional analysis complete" + }, + { + "timestamp": "2024-11-19 10:16:10", + "level": "info", + "message": "Generating revenue trends by month..." + }, + { + "timestamp": "2024-11-19 10:16:13", + "level": "success", + "message": "Trend analysis complete" + }, + { + "timestamp": "2024-11-19 10:16:14", + "level": "info", + "message": "Creating visualizations..." + }, + { + "timestamp": "2024-11-19 10:16:18", + "level": "success", + "message": "Generated 3 charts: revenue_by_region.png, monthly_trends.png, top_products.png" + } + ] + }, + { + "dataSourceName": "executionLogs3", + "type": "inline", + "content": [ + { + "timestamp": "2024-11-19 10:17:30", + "level": "info", + "message": "Initiating report generation..." + }, + { + "timestamp": "2024-11-19 10:17:31", + "level": "info", + "message": "Compiling data summaries and insights..." + }, + { + "timestamp": "2024-11-19 10:17:33", + "level": "info", + "message": "Embedding visualizations into report template..." + }, + { + "timestamp": "2024-11-19 10:17:38", + "level": "info", + "message": "Rendering report to PDF format..." + }, + { + "timestamp": "2024-11-19 10:17:42", + "level": "success", + "message": "Report generated successfully: Q4_Sales_Report_2024.pdf (2.4 MB)" + }, + { + "timestamp": "2024-11-19 10:17:43", + "level": "success", + "message": "Task completed in 4 minutes 20 seconds" } ] }, @@ -385,54 +382,97 @@ } }, "", + { + "type": "text", + "value": "
⚙️ Execution Phase 1: Data Loading & Validation
" + }, { "type": "treebark", - "variableId": "executionPhases", + "variableId": "executionLogs1", "template": { "div": { + "class": "execution-log", "$bind": ".", "$children": [ { "div": { - "class": "phase-indicator", + "class": "log-entry", "$children": [ - "{{phase}}" + { + "span": { + "class": "log-timestamp", + "$children": [ + "[{{timestamp}}]" + ] + } + }, + { + "span": { + "class": "log-level-{{level}}", + "$children": [ + " {{level}}: " + ] + } + }, + { + "span": { + "class": "log-message", + "$children": [ + "{{message}}" + ] + } + } ] } - }, + } + ] + } + } + }, + "", + { + "type": "treebark", + "variableId": "chatMessages2", + "getTemplate": "chatBubble" + }, + "", + { + "type": "text", + "value": "
⚙️ Execution Phase 2: Analysis & Visualization
" + }, + { + "type": "treebark", + "variableId": "executionLogs2", + "template": { + "div": { + "class": "execution-log", + "$bind": ".", + "$children": [ { "div": { - "class": "execution-log", - "$bind": "logs", + "class": "log-entry", "$children": [ { - "div": { - "class": "log-entry", + "span": { + "class": "log-timestamp", "$children": [ - { - "span": { - "class": "log-timestamp", - "$children": [ - "[{{timestamp}}]" - ] - } - }, - { - "span": { - "class": "log-level-{{level}}", - "$children": [ - " {{level}}: " - ] - } - }, - { - "span": { - "class": "log-message", - "$children": [ - "{{message}}" - ] - } - } + "[{{timestamp}}]" + ] + } + }, + { + "span": { + "class": "log-level-{{level}}", + "$children": [ + " {{level}}: " + ] + } + }, + { + "span": { + "class": "log-message", + "$children": [ + "{{message}}" ] } } @@ -446,13 +486,61 @@ "", { "type": "treebark", - "variableId": "chatMessages2", + "variableId": "chatMessages3", "getTemplate": "chatBubble" }, "", + { + "type": "text", + "value": "
⚙️ Execution Phase 3: Report Generation
" + }, { "type": "treebark", - "variableId": "chatMessages3", + "variableId": "executionLogs3", + "template": { + "div": { + "class": "execution-log", + "$bind": ".", + "$children": [ + { + "div": { + "class": "log-entry", + "$children": [ + { + "span": { + "class": "log-timestamp", + "$children": [ + "[{{timestamp}}]" + ] + } + }, + { + "span": { + "class": "log-level-{{level}}", + "$children": [ + " {{level}}: " + ] + } + }, + { + "span": { + "class": "log-message", + "$children": [ + "{{message}}" + ] + } + } + ] + } + } + ] + } + } + }, + "", + { + "type": "treebark", + "variableId": "chatMessages4", "getTemplate": "chatBubble" }, "",