2025-04-02 11:28:10 -04:00
|
|
|
@keyframes artifact-remove {
|
2025-03-12 13:25:17 -04:00
|
|
|
to {
|
2025-04-01 16:11:36 -04:00
|
|
|
height: 0;
|
|
|
|
overflow: hidden;
|
2025-03-12 13:25:17 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-04-02 11:28:10 -04:00
|
|
|
@keyframes artifact-fade {
|
2025-03-12 13:25:17 -04:00
|
|
|
to {
|
2025-04-01 16:11:36 -04:00
|
|
|
opacity: 0;
|
2025-03-12 13:25:17 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-11-19 09:22:39 +11:00
|
|
|
.ai-artifact__wrapper {
|
2025-04-01 16:11:36 -04:00
|
|
|
height: 500px;
|
|
|
|
padding-bottom: 2em;
|
|
|
|
|
2024-11-19 09:22:39 +11:00
|
|
|
iframe {
|
|
|
|
width: 100%;
|
|
|
|
height: calc(100% - 2em);
|
|
|
|
}
|
2025-04-01 16:11:36 -04:00
|
|
|
|
2025-06-12 20:04:48 +10:00
|
|
|
&.ai-artifact__seamless {
|
|
|
|
padding-bottom: 1em;
|
|
|
|
|
|
|
|
iframe {
|
|
|
|
height: 100%;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
&:not(.ai-artifact__expanded, .ai-artifact__seamless) {
|
2025-04-01 16:11:36 -04:00
|
|
|
iframe {
|
|
|
|
box-shadow: var(--shadow-card);
|
|
|
|
}
|
|
|
|
}
|
2024-11-19 09:22:39 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
.ai-artifact__click-to-run {
|
|
|
|
display: flex;
|
|
|
|
justify-content: center;
|
|
|
|
align-items: center;
|
|
|
|
height: 100%;
|
2025-04-01 16:11:36 -04:00
|
|
|
background: var(--primary-very-low);
|
2024-11-19 09:22:39 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
.ai-artifact__panel {
|
|
|
|
display: none;
|
|
|
|
}
|
|
|
|
|
|
|
|
html.ai-artifact-expanded {
|
|
|
|
overflow: hidden;
|
|
|
|
}
|
|
|
|
|
|
|
|
.ai-artifact__footer {
|
|
|
|
display: flex;
|
|
|
|
justify-content: space-between;
|
|
|
|
align-items: center;
|
2025-03-13 14:25:38 +01:00
|
|
|
|
2024-11-19 09:22:39 +11:00
|
|
|
.ai-artifact__expand-button {
|
|
|
|
margin-left: auto;
|
2025-04-01 16:11:36 -04:00
|
|
|
padding-right: 0;
|
|
|
|
|
|
|
|
.d-icon {
|
|
|
|
font-size: var(--font-down-1);
|
|
|
|
}
|
2024-11-19 09:22:39 +11:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-04-01 16:11:36 -04:00
|
|
|
.ai-artifact__panel--wrapper {
|
|
|
|
opacity: 0;
|
|
|
|
transition: opacity 0.5s ease-in-out;
|
|
|
|
}
|
|
|
|
|
2024-11-19 09:22:39 +11:00
|
|
|
.ai-artifact__expanded {
|
2025-04-01 16:11:36 -04:00
|
|
|
position: fixed;
|
|
|
|
top: 0;
|
|
|
|
left: 0;
|
|
|
|
height: 100%;
|
|
|
|
width: 100%;
|
|
|
|
z-index: z("fullscreen");
|
|
|
|
background-color: var(--secondary);
|
|
|
|
|
2024-11-19 09:22:39 +11:00
|
|
|
.ai-artifact__footer {
|
|
|
|
display: none;
|
|
|
|
}
|
|
|
|
|
|
|
|
.ai-artifact__panel--wrapper {
|
2025-04-01 16:11:36 -04:00
|
|
|
position: absolute;
|
|
|
|
top: 2em;
|
2024-12-10 05:59:19 +11:00
|
|
|
left: 2em;
|
|
|
|
right: 2em;
|
|
|
|
height: 2em;
|
2024-11-19 09:22:39 +11:00
|
|
|
z-index: 1000000;
|
2025-04-01 16:11:36 -04:00
|
|
|
display: flex;
|
|
|
|
justify-content: center;
|
|
|
|
opacity: 1;
|
2024-11-19 09:22:39 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
.ai-artifact__panel {
|
|
|
|
display: block;
|
2025-04-01 16:11:36 -04:00
|
|
|
position: absolute;
|
|
|
|
animation:
|
2025-04-02 11:28:10 -04:00
|
|
|
artifact-fade 0.75s forwards,
|
|
|
|
artifact-remove 1s forwards;
|
2025-04-01 16:11:36 -04:00
|
|
|
animation-delay: 4s;
|
|
|
|
background-color: var(--primary);
|
2024-11-19 09:22:39 +11:00
|
|
|
opacity: 0.9;
|
2025-04-01 16:11:36 -04:00
|
|
|
border-radius: var(--d-button-border-radius);
|
2024-11-19 09:22:39 +11:00
|
|
|
transform: translateY(0);
|
2025-04-01 16:11:36 -04:00
|
|
|
box-shadow: var(--shadow-card);
|
|
|
|
font-size: var(--font-up-1);
|
|
|
|
|
|
|
|
&:hover {
|
|
|
|
animation-play-state: paused;
|
|
|
|
opacity: 1;
|
|
|
|
}
|
2025-03-13 14:25:38 +01:00
|
|
|
|
2024-11-19 09:22:39 +11:00
|
|
|
button {
|
|
|
|
box-sizing: border-box;
|
2025-04-01 16:11:36 -04:00
|
|
|
justify-content: center;
|
2024-11-19 09:22:39 +11:00
|
|
|
color: var(--secondary-very-high);
|
2025-04-01 16:11:36 -04:00
|
|
|
margin: 0 auto;
|
2025-03-13 14:25:38 +01:00
|
|
|
|
2024-11-19 09:22:39 +11:00
|
|
|
&:hover {
|
|
|
|
color: var(--secondary-very-high);
|
2025-03-13 14:25:38 +01:00
|
|
|
|
2024-11-19 09:22:39 +11:00
|
|
|
.d-icon {
|
|
|
|
color: var(--secondary-high);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-12-10 05:59:19 +11:00
|
|
|
|
2024-11-19 09:22:39 +11:00
|
|
|
iframe {
|
|
|
|
position: fixed;
|
|
|
|
top: 0;
|
|
|
|
height: 100%;
|
|
|
|
max-height: 100%;
|
|
|
|
left: 0;
|
|
|
|
right: 0;
|
|
|
|
bottom: 0;
|
|
|
|
z-index: z("fullscreen");
|
|
|
|
}
|
|
|
|
}
|
FEATURE: persistent key-value storage for AI Artifacts (#1417)
Introduces a persistent, user-scoped key-value storage system for
AI Artifacts, enabling them to be stateful and interactive. This
transforms artifacts from static content into mini-applications that can
save user input, preferences, and other data.
The core components of this feature are:
1. **Model and API**:
- A new `AiArtifactKeyValue` model and corresponding database table to
store data associated with a user and an artifact.
- A new `ArtifactKeyValuesController` provides a RESTful API for
CRUD operations (`index`, `set`, `destroy`) on the key-value data.
- Permissions are enforced: users can only modify their own data but
can view public data from other users.
2. **Secure JavaScript Bridge**:
- A `postMessage` communication bridge is established between the
sandboxed artifact `iframe` and the parent Discourse window.
- A JavaScript API is exposed to the artifact as `window.discourseArtifact`
with async methods: `get(key)`, `set(key, value, options)`,
`delete(key)`, and `index(filter)`.
- The parent window handles these requests, makes authenticated calls to the
new controller, and returns the results to the iframe. This ensures
security by keeping untrusted JS isolated.
3. **AI Tool Integration**:
- The `create_artifact` tool is updated with a `requires_storage`
boolean parameter.
- If an artifact requires storage, its metadata is flagged, and the
system prompt for the code-generating AI is augmented with detailed
documentation for the new storage API.
4. **Configuration**:
- Adds hidden site settings `ai_artifact_kv_value_max_length` and
`ai_artifact_max_keys_per_user_per_artifact` for throttling.
This also includes a minor fix to use `jsonb_set` when updating
artifact metadata, ensuring other metadata fields are preserved.
2025-06-11 06:59:46 +10:00
|
|
|
|
|
|
|
.ai-share-full-topic-modal__body {
|
|
|
|
.ai-artifact-controls {
|
|
|
|
display: flex;
|
|
|
|
justify-content: space-between;
|
|
|
|
}
|
|
|
|
}
|