Skip to content
This repository was archived by the owner on Jul 22, 2025. It is now read-only.

Commit 8c30b7c

Browse files
committed
linting and basic functioning version
even though it does not perform fancy edits it at least works consistently
1 parent 5a4e89b commit 8c30b7c

File tree

14 files changed

+125
-154
lines changed

14 files changed

+125
-154
lines changed

app/controllers/discourse_ai/ai_bot/artifacts_controller.rb

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,20 @@ def show
1919
raise Discourse::NotFound if !guardian.can_see?(post)
2020
end
2121

22+
name = artifact.name
23+
24+
if params[:version].present?
25+
artifact = artifact.versions.find_by(version_number: params[:version])
26+
raise Discourse::NotFound if !artifact
27+
end
28+
2229
# Prepare the inner (untrusted) HTML document
2330
untrusted_html = <<~HTML
2431
<!DOCTYPE html>
2532
<html>
2633
<head>
2734
<meta charset="UTF-8">
28-
<title>#{ERB::Util.html_escape(artifact.name)}</title>
35+
<title>#{ERB::Util.html_escape(name)}</title>
2936
<style>
3037
#{artifact.css}
3138
</style>
@@ -45,7 +52,7 @@ def show
4552
<html>
4653
<head>
4754
<meta charset="UTF-8">
48-
<title>#{ERB::Util.html_escape(artifact.name)}</title>
55+
<title>#{ERB::Util.html_escape(name)}</title>
4956
<style>
5057
html, body, iframe {
5158
margin: 0;

app/models/ai_artifact.rb

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,22 @@ class AiArtifact < ActiveRecord::Base
88
validates :css, length: { maximum: 65_535 }
99
validates :js, length: { maximum: 65_535 }
1010

11-
def self.iframe_for(id)
11+
def self.iframe_for(id, version = nil)
1212
<<~HTML
1313
<div class='ai-artifact'>
14-
<iframe src='#{url(id)}' frameborder="0" height="100%" width="100%"></iframe>
15-
<a href='#{url(id)}' target='_blank'>#{I18n.t("discourse_ai.ai_artifact.link")}</a>
14+
<iframe src='#{url(id, version)}' frameborder="0" height="100%" width="100%"></iframe>
15+
<a href='#{url(id, version)}' target='_blank'>#{I18n.t("discourse_ai.ai_artifact.link")}</a>
1616
</div>
1717
HTML
1818
end
1919

20-
def self.url(id)
21-
Discourse.base_url + "/discourse-ai/ai-bot/artifacts/#{id}"
20+
def self.url(id, version = nil)
21+
url = Discourse.base_url + "/discourse-ai/ai-bot/artifacts/#{id}"
22+
if version
23+
"#{url}/#{version}"
24+
else
25+
url
26+
end
2227
end
2328

2429
def self.share_publicly(id:, post:)
@@ -48,23 +53,22 @@ def apply_diff(html_diff: nil, css_diff: nil, js_diff: nil, change_description:
4853
def create_new_version(html: nil, css: nil, js: nil, change_description: nil)
4954
latest_version = versions.order(version_number: :desc).first
5055
new_version_number = latest_version ? latest_version.version_number + 1 : 1
56+
version = nil
5157

5258
transaction do
5359
# Create the version record
54-
versions.create!(
55-
version_number: new_version_number,
56-
html: self.html,
57-
css: self.css,
58-
js: self.js,
59-
change_description: change_description,
60-
)
61-
62-
# Update the main artifact
63-
self.html = html if html.present?
64-
self.css = css if css.present?
65-
self.js = js if js.present?
60+
version =
61+
versions.create!(
62+
version_number: new_version_number,
63+
html: html || self.html,
64+
css: css || self.css,
65+
js: js || self.js,
66+
change_description: change_description,
67+
)
6668
save!
6769
end
70+
71+
version
6872
end
6973
end
7074

app/models/shared_ai_conversation.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,9 +190,11 @@ def self.cook_artifacts(post)
190190
.css("div.ai-artifact")
191191
.each do |node|
192192
id = node["data-ai-artifact-id"].to_i
193+
version = node["data-ai-artifact-version"]
194+
version_number = version.to_i if version
193195
if id > 0
194196
AiArtifact.share_publicly(id: id, post: post)
195-
node.replace(AiArtifact.iframe_for(id))
197+
node.replace(AiArtifact.iframe_for(id, version_number))
196198
end
197199
end
198200

assets/javascripts/discourse/components/ai-artifact.gjs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,13 @@ export default class AiArtifactComponent extends Component {
3737
}
3838

3939
get artifactUrl() {
40-
return getURL(`/discourse-ai/ai-bot/artifacts/${this.args.artifactId}`);
40+
const url = getURL(`/discourse-ai/ai-bot/artifacts/${this.args.artifactId}`);
41+
42+
if (this.args.artifactVersion) {
43+
return `${url}?version=${this.args.artifactVersion}`;
44+
} else {
45+
return url;
46+
}
4147
}
4248

4349
@action

assets/javascripts/initializers/ai-artifacts.gjs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,15 @@ function initializeAiArtifacts(api) {
1414
"data-ai-artifact-id"
1515
);
1616

17+
const artifactVersion = artifactElement.getAttribute(
18+
"data-ai-artifact-version"
19+
);
20+
1721
helper.renderGlimmer(artifactElement, <template>
18-
<AiArtifact @artifactId={{artifactId}} />
22+
<AiArtifact
23+
@artifactId={{artifactId}}
24+
@artifactVersion={{artifactVersion}}
25+
/>
1926
</template>);
2027
}
2128
);
Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
export function setup(helper) {
22
helper.allowList(["details[class=ai-quote]"]);
3-
helper.allowList(["div[class=ai-artifact]", "div[data-ai-artifact-id]"]);
3+
helper.allowList([
4+
"div[class=ai-artifact]",
5+
"div[data-ai-artifact-id]",
6+
"div[data-ai-artifact-version]",
7+
]);
48
}

config/locales/server.en.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,7 @@ en:
310310
name: "Base Search Query"
311311
description: "Base query to use when searching. Example: '#urgent' will prepend '#urgent' to the search query and only include topics with the urgent category or tag."
312312
tool_summary:
313+
update_artifact: "Update a web artifact"
313314
create_artifact: "Create web artifact"
314315
web_browser: "Browse Web"
315316
github_search_files: "GitHub search files"
@@ -332,6 +333,7 @@ en:
332333
search_meta_discourse: "Search Meta Discourse"
333334
javascript_evaluator: "Evaluate JavaScript"
334335
tool_help:
336+
update_artifact: "Update a web artifact using the AI Bot"
335337
create_artifact: "Create a web artifact using the AI Bot"
336338
web_browser: "Browse web page using the AI Bot"
337339
github_search_code: "Search for code in a GitHub repository"
@@ -354,6 +356,7 @@ en:
354356
search_meta_discourse: "Search Meta Discourse"
355357
javascript_evaluator: "Evaluate JavaScript"
356358
tool_description:
359+
update_artifact: "Updated a web artifact using the AI Bot"
357360
create_artifact: "Created a web artifact using the AI Bot"
358361
web_browser: "Reading <a href='%{url}'>%{url}</a>"
359362
github_search_files: "Searched for '%{keywords}' in %{repo}/%{branch}"

config/routes.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636

3737
scope module: :ai_bot, path: "/ai-bot/artifacts" do
3838
get "/:id" => "artifacts#show"
39+
get "/:id/:version" => "artifacts#show"
3940
end
4041

4142
scope module: :summarization, path: "/summarization", defaults: { format: :json } do

db/migrate/20241130003808_add_artifact_versions.rb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@ def change
44
create_table :ai_artifact_versions do |t|
55
t.bigint :ai_artifact_id, null: false
66
t.integer :version_number, null: false
7-
t.string :html, limit: 65535
8-
t.string :css, limit: 65535
9-
t.string :js, limit: 65535
7+
t.string :html, limit: 65_535
8+
t.string :css, limit: 65_535
9+
t.string :js, limit: 65_535
1010
t.jsonb :metadata
1111
t.string :change_description
1212
t.timestamps
1313

14-
t.index [:ai_artifact_id, :version_number], unique: true
14+
t.index %i[ai_artifact_id version_number], unique: true
1515
end
1616
end
1717
end

lib/ai_bot/tools/update_artifact.rb

Lines changed: 25 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ def self.name
88
"update_artifact"
99
end
1010

11+
# this is not working that well, we support it, but I am leaving it dormant for now
1112
def self.unified_diff_tip
1213
<<~TIP
1314
When updating and artifact in diff mode unified diffs can be applied:
@@ -50,7 +51,7 @@ def self.signature
5051
{
5152
name: "update_artifact",
5253
description:
53-
"Updates an existing web artifact with new HTML, CSS, or JavaScript content.\n#{unified_diff_tip}",
54+
"Updates an existing web artifact with new HTML, CSS, or JavaScript content.",
5455
parameters: [
5556
{
5657
name: "artifact_id",
@@ -59,18 +60,18 @@ def self.signature
5960
required: true,
6061
},
6162
{
62-
name: "html_diff",
63-
description: "A unified diff of HTML changes to apply",
63+
name: "html",
64+
description: "(Optional) new HTML content for the artifact",
6465
type: "string",
6566
},
6667
{
67-
name: "css_diff",
68-
description: "A unified diff of CSS changes to apply",
68+
name: "css",
69+
description: "(Optional) new CSS content for the artifact",
6970
type: "string",
7071
},
7172
{
72-
name: "js_diff",
73-
description: "A unified diff of JavaScript changes to apply",
73+
name: "js",
74+
description: "(Optional) new JavaScript content for the artifact",
7475
type: "string",
7576
},
7677
{
@@ -79,14 +80,6 @@ def self.signature
7980
type: "string",
8081
required: true,
8182
},
82-
{
83-
name: "diff_mode",
84-
description:
85-
"How would you like to apply the diff? (replace, append or diff) default is diff",
86-
type: "string",
87-
required: false,
88-
enum: %w[replace append diff],
89-
},
9083
],
9184
}
9285
end
@@ -100,7 +93,7 @@ def chain_next_response?
10093
end
10194

10295
def partial_invoke
103-
@selected_tab = :html_diff
96+
@selected_tab = :html
10497
if @prev_parameters
10598
@selected_tab = parameters.keys.find { |k| @prev_parameters[k] != parameters[k] }
10699
end
@@ -122,31 +115,16 @@ def invoke
122115
end
123116

124117
begin
125-
if parameters[:diff_mode] == "diff"
126-
artifact.apply_diff(
127-
html_diff: parameters[:html_diff],
128-
css_diff: parameters[:css_diff],
129-
js_diff: parameters[:js_diff],
130-
change_description: parameters[:change_description],
131-
)
132-
elsif parameters[:diff_mode] == "replace"
133-
artifact.create_new_version(
134-
html: parameters[:html_diff] || artifact.html,
135-
css: parameters[:css_diff] || artifact.css,
136-
js: parameters[:js_diff] || artifact.js,
137-
change_description: parameters[:change_description],
138-
)
139-
else
118+
version =
140119
artifact.create_new_version(
141-
html: (artifact.html + "\n" + parameters[:html_diff].to_s).strip,
142-
css: (artifact.css + "\n" + parameters[:css_diff].to_s).strip,
143-
js: (artifact.js + "\n" + parameters[:js_diff].to_s).strip,
120+
html: parameters[:html] || artifact.html,
121+
css: parameters[:css] || artifact.css,
122+
js: parameters[:js] || artifact.js,
144123
change_description: parameters[:change_description],
145124
)
146-
end
147125

148-
update_custom_html(artifact)
149-
success_response(artifact)
126+
update_custom_html(artifact, version)
127+
success_response(artifact, version)
150128
rescue DiscourseAi::Utils::DiffUtils::DiffError => e
151129
error_response(e.to_llm_message)
152130
rescue => e
@@ -156,19 +134,19 @@ def invoke
156134

157135
private
158136

159-
def update_custom_html(artifact = nil)
137+
def update_custom_html(artifact = nil, version = nil)
160138
content = []
161139

162-
if parameters[:html_diff].present?
163-
content << [:html_diff, "### HTML Changes\n\n```diff\n#{parameters[:html_diff]}\n```"]
140+
if parameters[:html].present?
141+
content << [:html, "### HTML Changes\n\n```html\n#{parameters[:html]}\n```"]
164142
end
165143

166-
if parameters[:css_diff].present?
167-
content << [:css_diff, "### CSS Changes\n\n```diff\n#{parameters[:css_diff]}\n```"]
144+
if parameters[:css].present?
145+
content << [:css, "### CSS Changes\n\n```css\n#{parameters[:css]}\n```"]
168146
end
169147

170-
if parameters[:js_diff].present?
171-
content << [:js_diff, "### JavaScript Changes\n\n```diff\n#{parameters[:js_diff]}\n```"]
148+
if parameters[:js].present?
149+
content << [:js, "### JavaScript Changes\n\n```javascript\n#{parameters[:js]}\n```"]
172150
end
173151

174152
if parameters[:change_description].present?
@@ -184,7 +162,7 @@ def update_custom_html(artifact = nil)
184162
content << [nil, "[/details]"]
185163
content << [
186164
:preview,
187-
"### Preview\n\n<div class=\"ai-artifact\" data-ai-artifact-id=\"#{artifact.id}\"></div>",
165+
"### Preview\n\n<div class=\"ai-artifact\" data-ai-artifact-version=\"#{version.version_number}\" data-ai-artifact-id=\"#{artifact.id}\"></div>",
188166
]
189167
end
190168

@@ -193,28 +171,16 @@ def update_custom_html(artifact = nil)
193171
self.custom_raw = content.map { |c| c[1] }.join("\n\n")
194172
end
195173

196-
def success_response(artifact)
174+
def success_response(artifact, version)
197175
@chain_next_response = false
198176

199177
hash = {
200178
status: "success",
201179
artifact_id: artifact.id,
202-
version: artifact.versions.last.version_number,
180+
version: version.version_number,
203181
message: "Artifact updated successfully and rendered to user.",
204182
}
205183

206-
if parameters[:html_diff].present?
207-
hash[:new_artifact_html] = artifact.html
208-
end
209-
210-
if parameters[:css_diff].present?
211-
hash[:new_artifact_css] = artifact.css
212-
end
213-
214-
if parameters[:js_diff].present?
215-
hash[:new_artifact_js] = artifact.js
216-
end
217-
218184
hash
219185
end
220186

0 commit comments

Comments
 (0)