Skip to content

Commit aedf2f3

Browse files
committed
fixes and adjustments after rebasing onto playground redesign
Signed-off-by: Akshat Batra <[email protected]>
1 parent 14a6971 commit aedf2f3

File tree

10 files changed

+87
-82
lines changed

10 files changed

+87
-82
lines changed

package-lock.json

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
"react-dropdown": "^1.11.0",
4646
"react-icons": "^5.5.0",
4747
"react-markdown": "^9.0.1",
48-
"react-resizable-panels": "^3.0.3",
48+
"react-resizable-panels": "^3.0.5",
4949
"react-router-dom": "^6.24.1",
5050
"react-shepherd": "^6.1.1",
5151
"react-spring": "^9.7.4",

src/ai-assistant/prompts.ts

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -52,27 +52,7 @@ export const prepareSystemPrompt = {
5252
},
5353

5454
default: (editorsContent: editorsContent, aiConfig?: any) => {
55-
let prompt = `You are a helpful assistant that answers questions about open source Accord Project. You assist the user
56-
in working with TemplateMark, Concerto models and JSON data. Code blocks returned by you should be enclosed in backticks, the
57-
language names that you can use after three backticks are- "concerto","templatemark" and "json", suffix 'Apply' to the
58-
language name if it is a complete code block that can be used to replace the corresponding editor content, precisely,
59-
concertoApply, templatemarkApply and jsonApply. You must always try to return complete code block that can be applied
60-
to the editors. Concerto code, TemplateMark code and JSON data are supplied to TemplateEngine to produce the final output.
61-
For instance, a data field that is not in Concerto data model can't be in JSON data and therefore can't be used in TemplateMark
62-
you generate. Analyze the JSON data and Concerto model (if provided) carefully, only the fields with simple data types
63-
(String, Integer etc.) present in concept annotated with @template decorator can be directly accessed anywhere in the template.
64-
Other complex data fields that have custom concept declaration in Concerto model and nested fields in JSON data, can only be used
65-
within {{#clause conceptName}} {{concept_property_name}} {{/clause}} tags. For enumerating through a list you can create a scope
66-
to access the properties in list items via {{#olist listName}} {{instancePropertyName}} {{/olist}} or {{#ulist listName}}
67-
{{instancePropertyName}} {{/ulist}}. For TemplateMark code, there's no such thing as 'this' keyword within list scope. You can also
68-
use Typescript within TemplateMark by enclosing the Typescript code in {{% %}}, you must write all of the Typescript code within a
69-
single line enclosed in a single pair of opening {{% and closing %}}. You may use Typescript to achieve an objective in TemplateMark
70-
only if TemplateMark syntax makes doing something hard, the data objects from JSON are readily available within {{% %}} enclosed
71-
Typescript using direct access, e.g. {{% return order.orderLines %}}. For e.g., you could use TypeScript to render ordered/unordered
72-
primitive list types such as String[]. Keep your focus on generating valid output based on current editors' contents but if you make
73-
a change that isn't compatible with the content of existing editors, you must return the full code for those editors as well. You
74-
mustn't add any placeholder in TemplateMark which isn't in Concerto model and JSON data unless you modify the Concerto and JSON data
75-
to have that field at the appropriate place.\n\n`;
55+
let prompt = `You are a helpful assistant that answers questions about open source Accord Project. You assist the user in working with TemplateMark, Concerto models and JSON data. Code blocks returned by you should be enclosed in backticks, the language names that you can use after three backticks are- "concerto","templatemark" and "json", suffix 'Apply' to the language name if it is a complete code block that can be used to replace the corresponding editor content, precisely, concertoApply, templatemarkApply and jsonApply. You must always try to return complete code block that can be applied to the editors. Concerto code, TemplateMark code and JSON data are supplied to TemplateEngine to produce the final output. For instance, a data field that is not in Concerto data model can't be in JSON data and therefore can't be used in TemplateMark you generate. Analyze the JSON data and Concerto model (if provided) carefully, only the fields with simple data types (String, Integer etc.) present in concept annotated with @template decorator can be directly accessed anywhere in the template. Other complex data fields that have custom concept declaration in the Concerto model and are represented as nested fields in JSON data, can only be used within {{#clause conceptName}} {{concept_property_name}} {{/clause}} tags. Therefore, in most cases you have to create a scope using clause tag in TemplateMark to access properties defined under a concept in Concerto. For enumerating through a list you can create a scope to access the properties in list items via {{#olist listName}} {{instancePropertyName}} {{/olist}} or {{#ulist listName}} {{instancePropertyName}} {{/ulist}}. For TemplateMark code, there's no such thing as 'this' keyword within list scope. Optional fields shouldn't be wrapped in an if or with block to check for their availability e.g. if Concerto model has age as optional don't wrap it in if block in TemplateMark. You can also use Typescript within TemplateMark by enclosing the Typescript code in {{% %}}, you must write all of the Typescript code within a single line enclosed in a single pair of opening {{% and closing %}}. You may use Typescript to achieve an objective in TemplateMark only if TemplateMark syntax makes doing something hard, the data objects from JSON are readily available within {{% %}} enclosed Typescript using direct access, e.g. {{% return order.orderLines %}}. For e.g., you could use TypeScript to render ordered/unordered primitive list types such as String[]. Keep your focus on generating valid output based on current editors' contents but if you make a change that isn't compatible with the content of existing editors, you must return the full code for those editors as well. You mustn't add any placeholder in TemplateMark which isn't in Concerto model and JSON data unless you modify the Concerto and JSON data to have that field at the appropriate place.\n\n`;
7656
return includeEditorContents(prompt, aiConfig, editorsContent);
7757
}
7858
};

src/components/AIChatPanel.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ export const AIChatPanel = () => {
291291
</button>
292292
</div>
293293
</div>
294-
<div className="w-full h-[calc(100%-3rem)] flex flex-col">
294+
<div className="w-full h-[calc(100%-1rem)] flex flex-col">
295295
<div className="flex-1 overflow-y-auto mb-4 px-2 mt-4">
296296
<div className="space-y-2">
297297
{chatState.messages.length === 0 ? (

src/components/CodeSelectionMenu.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,8 @@ const CodeSelectionMenu: React.FC<CodeSelectionMenuProps> = ({
125125
};
126126

127127
const popupPosition = {
128-
left: Math.max(10, Math.min(position.x, window.innerWidth - 350)),
129-
top: Math.max(10, Math.min(position.y - 20, window.innerHeight - 300)),
128+
left: Math.max(300, Math.min(position.x, window.innerWidth - 350)),
129+
top: isExplaining ? position.y-20 : Math.max(10, Math.min(position.y - 20, window.innerHeight - 300)),
130130
};
131131

132132
useEffect(() => {
@@ -165,7 +165,7 @@ const CodeSelectionMenu: React.FC<CodeSelectionMenuProps> = ({
165165
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
166166
</svg>
167167
</button>
168-
<div className={`max-h-[60vh] pr-6 ${isExplaining ? 'overflow-hidden' : 'overflow-y-auto'}`}>
168+
<div className={`max-h-64 pr-6 ${isExplaining ? 'overflow-hidden' : 'overflow-y-auto'}`}>
169169
{isExplaining ? (
170170
<div className="flex items-center text-gray-500 text-sm">
171171
<svg className="animate-spin h-4 w-4 mr-2" viewBox="0 0 24 24">

src/components/PlaygroundSidebar.tsx

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { IoCodeSlash } from "react-icons/io5";
33
import { VscOutput } from "react-icons/vsc";
44
import { FiTerminal, FiShare2, FiSettings } from "react-icons/fi";
55
import { FaCirclePlay } from "react-icons/fa6";
6+
import { IoChatbubbleEllipsesOutline } from "react-icons/io5";
67
import useAppStore from "../store/store";
78
import { message } from "antd";
89
import FullScreenModal from "./FullScreenModal";
@@ -14,17 +15,21 @@ const PlaygroundSidebar = () => {
1415
isEditorsVisible,
1516
isPreviewVisible,
1617
isProblemPanelVisible,
18+
isAIChatOpen,
1719
setEditorsVisible,
1820
setPreviewVisible,
1921
setProblemPanelVisible,
22+
setAIChatOpen,
2023
generateShareableLink,
2124
} = useAppStore((state) => ({
2225
isEditorsVisible: state.isEditorsVisible,
2326
isPreviewVisible: state.isPreviewVisible,
2427
isProblemPanelVisible: state.isProblemPanelVisible,
28+
isAIChatOpen: state.isAIChatOpen,
2529
setEditorsVisible: state.setEditorsVisible,
2630
setPreviewVisible: state.setPreviewVisible,
2731
setProblemPanelVisible: state.setProblemPanelVisible,
32+
setAIChatOpen: state.setAIChatOpen,
2833
generateShareableLink: state.generateShareableLink,
2934
}));
3035

@@ -95,6 +100,26 @@ const PlaygroundSidebar = () => {
95100
onClick: () => setProblemPanelVisible(!isProblemPanelVisible),
96101
active: isProblemPanelVisible
97102
},
103+
{
104+
title: "AI Assistant",
105+
component: (
106+
<div className="flex items-center justify-center">
107+
<div className="relative w-6 h-6">
108+
<IoChatbubbleEllipsesOutline size={24} />
109+
<div
110+
className="absolute -top-3 -right-3.5 text-[12.5px] font-bold px-1 py-0 rounded bg-white text-transparent bg-gradient-to-r from-[#a78bfa] via-[#ec4899] to-[#ef4444] bg-clip-text shadow-sm"
111+
style={{
112+
WebkitBackgroundClip: "text"
113+
}}
114+
>
115+
AI
116+
</div>
117+
</div>
118+
</div>
119+
),
120+
onClick: () => setAIChatOpen(!isAIChatOpen),
121+
active: isAIChatOpen
122+
},
98123
{
99124
title: "Fullscreen",
100125
component: <FullScreenModal />

src/components/ProblemPanel.tsx

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
import React, { useMemo } from 'react';
1+
import React, { useMemo, useState } from 'react';
22
import useAppStore from '../store/store';
33
import '../styles/components/ProblemPanel.css';
4+
import { sendMessage } from '../ai-assistant/chatRelay';
5+
import { IoChatbubbleEllipsesOutline } from "react-icons/io5";
46

57
export interface ProblemItem {
68
id: string;
@@ -18,6 +20,30 @@ const ProblemPanel: React.FC = () => {
1820
backgroundColor: state.backgroundColor,
1921
textColor: state.textColor
2022
}));
23+
const [isSending, setIsSending] = useState(false);
24+
25+
const editorsContent = useAppStore((state) => ({
26+
editorTemplateMark: state.editorValue,
27+
editorModelCto: state.editorModelCto,
28+
editorAgreementData: state.editorAgreementData,
29+
}));
30+
31+
const handleFixProblem = async (problem: ProblemItem) => {
32+
if (isSending) return;
33+
34+
setIsSending(true);
35+
try {
36+
const prompt = `Fix this ${problem.type}: ${problem.message}
37+
Source: ${problem.source || 'Unknown'}
38+
${problem.line ? `Line: ${problem.line}` : ''}
39+
${problem.column ? `Column: ${problem.column}` : ''}`;
40+
41+
await sendMessage(prompt, null, editorsContent);
42+
useAppStore.getState().setAIChatOpen(true);
43+
} finally {
44+
setIsSending(false);
45+
}
46+
};
2147

2248
const parseError = (errorMessage: string) => {
2349
const errors: Omit<ProblemItem, 'id' | 'timestamp'>[] = [];
@@ -84,6 +110,27 @@ const ProblemPanel: React.FC = () => {
84110
<div className="problem-panel-container" style={{ backgroundColor }}>
85111
<div className={`problem-panel-header ${backgroundColor === '#ffffff' ? 'problem-panel-header-light' : 'problem-panel-header-dark'}`}>
86112
<span className="problem-panel-title">Problems</span>
113+
{problems.length > 0 && (
114+
<button
115+
onClick={() => handleFixProblem(problems[0])}
116+
disabled={isSending}
117+
className="relative flex items-center px-2 py-1 bg-blue-400 hover:bg-blue-600 text-white rounded-md text-sm"
118+
title="Ask AI to fix this problem"
119+
>
120+
<div className="relative w-5 h-5 mr-1.5">
121+
<IoChatbubbleEllipsesOutline size={20} />
122+
<div
123+
className="absolute -top-2.5 -right-3 text-[10px] font-bold px-0.5 py-0 bg-white rounded shadow-sm text-transparent bg-gradient-to-r from-[#bdff68ff] via-[#e6fc6dff] to-[#ebb6b6ff] bg-clip-text"
124+
style={{
125+
WebkitBackgroundClip: "text"
126+
}}
127+
>
128+
AI
129+
</div>
130+
</div>
131+
<span className="ml-2">{isSending ? "Suggesting a fix..." : "Fix"}</span>
132+
</button>
133+
)}
87134
</div>
88135
<div className="problem-panel-content" style={{ backgroundColor }}>
89136
{problems.length === 0 ? (

src/pages/MainContainer.tsx

Lines changed: 2 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,11 @@ const MainContainer = () => {
1515
const textColor = useAppStore((state) => state.textColor);
1616
const {
1717
isAIChatOpen,
18-
setAIChatOpen,
1918
isEditorsVisible,
2019
isPreviewVisible,
2120
isProblemPanelVisible,
2221
} = useAppStore((state) => ({
2322
isAIChatOpen: state.isAIChatOpen,
24-
setAIChatOpen: state.setAIChatOpen,
2523
isEditorsVisible: state.isEditorsVisible,
2624
isPreviewVisible: state.isPreviewVisible,
2725
isProblemPanelVisible: state.isProblemPanelVisible,
@@ -31,7 +29,7 @@ const MainContainer = () => {
3129

3230
return (
3331
<div className="main-container" style={{ backgroundColor }}>
34-
<PanelGroup direction="horizontal" className="main-container-panel-group">
32+
<PanelGroup direction="horizontal" className="main-container-panel-group" style={{position: "fixed", width: "calc(100% - 64px)", height: "calc(100% - 64px)"}}>
3533
{isEditorsVisible && (
3634
<>
3735
<Panel defaultSize={50} minSize={30}>
@@ -45,51 +43,6 @@ const MainContainer = () => {
4543
<span>Concerto Model</span>
4644
<SampleDropdown setLoading={setLoading} />
4745
</div>
48-
<button
49-
id="ai-assistant"
50-
onClick={() => setAIChatOpen(!isAIChatOpen)}
51-
className="main-container-ai-assistant-button tour-ai-assistant"
52-
>
53-
<svg
54-
xmlns="http://www.w3.org/2000/svg"
55-
viewBox="0 0 45 20"
56-
fill="none"
57-
className="main-container-ai-assistant-icon"
58-
>
59-
<path
60-
strokeLinecap="round"
61-
strokeLinejoin="round"
62-
strokeWidth={1.5}
63-
stroke="currentColor"
64-
d="M12 13.25c4.97 0 9-3.694 9-8.25s-4.03-8.25-9-8.25S3 0.444 3 5c0 2.104.859 4.023 2.273 5.48.432.447.74 1.04.586 1.641a4.483 4.483 0 01-.923 1.785A5.969 5.969 0 006 14c1.282 0 2.47-.402 3.445-1.087.81.22 1.668.337 2.555.337z"
65-
transform="translate(0, 3)"
66-
/>
67-
<defs>
68-
<linearGradient
69-
id="ai-gradient"
70-
x1="0%"
71-
y1="0%"
72-
x2="100%"
73-
y2="0%"
74-
>
75-
<stop offset="0%" stopColor="#a78bfa" />
76-
<stop offset="50%" stopColor="#ec4899" />
77-
<stop offset="100%" stopColor="#ef4444" />
78-
</linearGradient>
79-
</defs>
80-
<text
81-
x="32"
82-
y="6"
83-
fontSize="16"
84-
fontWeight="bold"
85-
fill="url(#ai-gradient)"
86-
textAnchor="middle"
87-
>
88-
AI
89-
</text>
90-
</svg>
91-
<span>Assistant</span>
92-
</button>
9346
</div>
9447
<div className="main-container-editor-content" style={{ backgroundColor }}>
9548
<TemplateModel />
@@ -161,7 +114,7 @@ const MainContainer = () => {
161114
)}
162115
{isAIChatOpen && (
163116
<>
164-
<Panel defaultSize={25} minSize={20}>
117+
<Panel defaultSize={25} minSize={25}>
165118
<AIChatPanel />
166119
</Panel>
167120
</>

src/styles/components/ProblemPanel.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
}
44

55
.problem-panel-header {
6-
@apply flex items-center px-4 py-2 border-b border-gray-200;
6+
@apply flex items-center justify-between px-4 py-2 border-b border-gray-200;
77
}
88

99
.problem-panel-header-light {

src/utils/helpers/Errors.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ function Errors() {
1414

1515
const handleFixError = async () => {
1616
if (!error || isSending) return;
17-
17+
1818
setIsSending(true);
1919
try {
2020
await sendMessage(`Fix this error: ${error}`, null, editorsContent);

0 commit comments

Comments
 (0)