1
0
mirror of synced 2026-08-05 07:16:54 +00:00

FEATURE: hybrid artifact security mode (#1431)

In hybrid mode ai artifacts can optionally automatically run.

This is useful for cases where you may want to embed a survey and so on.

Additionally, artifacts now allow for better fidelity around display:

<div class="ai-artifact" data-ai-artifact-id="501" data-ai-artifact-height="300px" data-ai-artifact-autorun data-ai-artifact-seamless></div>

User can supply height and seamless mode to be seamlessly rendered with no box shadow and show full screen button.
This commit is contained in:
Sam
2025-06-12 20:04:48 +10:00
committed by GitHub
parent b5a2ee31ab
commit 02bc9f645e
9 changed files with 83 additions and 11 deletions
@@ -3,6 +3,7 @@ import { tracked } from "@glimmer/tracking";
import { action } from "@ember/object";
import didInsert from "@ember/render-modifiers/modifiers/did-insert";
import { service } from "@ember/service";
import { htmlSafe } from "@ember/template";
import DButton from "discourse/components/d-button";
import htmlClass from "discourse/helpers/html-class";
import getURL from "discourse/lib/get-url";
@@ -51,7 +52,21 @@ export default class AiArtifactComponent extends Component {
if (this.showingArtifact) {
return false;
}
return this.siteSettings.ai_artifact_security === "strict";
if (this.siteSettings.ai_artifact_security === "strict") {
return true;
}
if (this.siteSettings.ai_artifact_security === "hybrid") {
const shouldAutorun =
this.args.autorun === "true" ||
this.args.autorun === true ||
this.args.autorun === "1";
return !shouldAutorun;
}
return this.siteSettings.ai_artifact_security !== "lax";
}
get artifactUrl() {
@@ -86,7 +101,7 @@ export default class AiArtifactComponent extends Component {
get wrapperClasses() {
return `ai-artifact__wrapper ${
this.expanded ? "ai-artifact__expanded" : ""
}`;
} ${this.seamless ? "ai-artifact__seamless" : ""}`;
}
@action
@@ -98,11 +113,38 @@ export default class AiArtifactComponent extends Component {
}
}
get heightStyle() {
if (this.args.artifactHeight) {
let height = parseInt(this.args.artifactHeight, 10);
if (isNaN(height) || height <= 0) {
height = 500; // default height if the provided value is invalid
}
if (height > 2000) {
height = 2000; // cap the height to a maximum of 2000px
}
return htmlSafe(`height: ${height}px;`);
}
}
get seamless() {
return (
this.args.seamless === "true" ||
this.args.seamless === true ||
this.args.seamless === "1"
);
}
get showFooter() {
return !this.seamless && !this.requireClickToRun;
}
<template>
{{#if this.expanded}}
{{htmlClass "ai-artifact-expanded"}}
{{/if}}
<div class={{this.wrapperClasses}}>
<div class={{this.wrapperClasses}} style={{this.heightStyle}}>
<div class="ai-artifact__panel--wrapper">
<div class="ai-artifact__panel">
<DButton
@@ -131,7 +173,7 @@ export default class AiArtifactComponent extends Component {
{{didInsert this.setDataAttributes}}
></iframe>
{{/if}}
{{#unless this.requireClickToRun}}
{{#if this.showFooter}}
<div class="ai-artifact__footer">
<DButton
class="btn-transparent btn-icon-text ai-artifact__expand-button"
@@ -140,7 +182,7 @@ export default class AiArtifactComponent extends Component {
@action={{this.toggleView}}
/>
</div>
{{/unless}}
{{/if}}
</div>
</template>
}
@@ -18,12 +18,27 @@ function initializeAiArtifacts(api) {
"data-ai-artifact-version"
);
const artifactHeight = artifactElement.getAttribute(
"data-ai-artifact-height"
);
const autorun =
artifactElement.getAttribute("data-ai-artifact-autorun") ||
artifactElement.hasAttribute("data-ai-artifact-autorun");
const seamless =
artifactElement.getAttribute("data-ai-artifact-seamless") ||
artifactElement.hasAttribute("data-ai-artifact-seamless");
const dataAttributes = {};
for (const attr of artifactElement.attributes) {
if (
attr.name.startsWith("data-") &&
attr.name !== "data-ai-artifact-id" &&
attr.name !== "data-ai-artifact-version"
attr.name !== "data-ai-artifact-version" &&
attr.name !== "data-ai-artifact-height" &&
attr.name !== "data-ai-artifact-autorun" &&
attr.name !== "data-ai-artifact-seamless"
) {
dataAttributes[attr.name] = attr.value;
}
@@ -35,6 +50,9 @@ function initializeAiArtifacts(api) {
<AiArtifact
@artifactId={{artifactId}}
@artifactVersion={{artifactVersion}}
@artifactHeight={{artifactHeight}}
@autorun={{autorun}}
@seamless={{seamless}}
@dataAttributes={{dataAttributes}}
/>
</template>
@@ -4,5 +4,8 @@ export function setup(helper) {
"div[class=ai-artifact]",
"div[data-ai-artifact-id]",
"div[data-ai-artifact-version]",
"div[data-ai-artifact-autorun]",
"div[data-ai-artifact-height]",
"div[data-ai-artifact-width]",
]);
}