Compare commits
27
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5b012a15b8 | ||
|
|
051ac3ea49 | ||
|
|
d993b02975 | ||
|
|
39653aed22 | ||
|
|
6781ecd02e | ||
|
|
e264572597 | ||
|
|
70b0db2871 | ||
|
|
2d6ec5e1e6 | ||
|
|
cead887480 | ||
|
|
adc92e1e75 | ||
|
|
0ce17a122f | ||
|
|
cf220c530c | ||
|
|
61ef1932fa | ||
|
|
11e90f5f3f | ||
|
|
b817810d46 | ||
|
|
55dab9c68a | ||
|
|
c29183fc2d | ||
|
|
d72ad84f8f | ||
|
|
e207eba1a4 | ||
|
|
53905f65ac | ||
|
|
ef260be7cf | ||
|
|
0c69bb85ce | ||
|
|
af18603b21 | ||
|
|
7db2589cc4 | ||
|
|
2fb691cba8 | ||
|
|
de0625571b | ||
|
|
296aa24df1 |
@@ -124,6 +124,10 @@ module DiscourseAi
|
||||
raise Discourse::InvalidParameters.new(:custom_prompt) if params[:custom_prompt].blank?
|
||||
end
|
||||
|
||||
# to stream we must have an appropriate client_id
|
||||
# otherwise we may end up streaming the data to the wrong client
|
||||
raise Discourse::InvalidParameters.new(:client_id) if params[:client_id].blank?
|
||||
|
||||
if location == "composer"
|
||||
Jobs.enqueue(
|
||||
:stream_composer_helper,
|
||||
@@ -132,6 +136,7 @@ module DiscourseAi
|
||||
prompt: prompt.name,
|
||||
custom_prompt: params[:custom_prompt],
|
||||
force_default_locale: params[:force_default_locale] || false,
|
||||
client_id: params[:client_id],
|
||||
)
|
||||
else
|
||||
post_id = get_post_param!
|
||||
@@ -146,6 +151,7 @@ module DiscourseAi
|
||||
text: text,
|
||||
prompt: prompt.name,
|
||||
custom_prompt: params[:custom_prompt],
|
||||
client_id: params[:client_id],
|
||||
)
|
||||
end
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ module Jobs
|
||||
return unless args[:prompt]
|
||||
return unless user = User.find_by(id: args[:user_id])
|
||||
return unless args[:text]
|
||||
return unless args[:client_id]
|
||||
|
||||
prompt = CompletionPrompt.enabled_by_name(args[:prompt])
|
||||
|
||||
@@ -21,6 +22,7 @@ module Jobs
|
||||
user,
|
||||
"/discourse-ai/ai-helper/stream_composer_suggestion",
|
||||
force_default_locale: args[:force_default_locale],
|
||||
client_id: args[:client_id],
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -242,6 +242,7 @@ export default class AiPostHelperMenu extends Component {
|
||||
text: this.args.data.selectedText,
|
||||
post_id: this.args.data.quoteState.postId,
|
||||
custom_prompt: this.customPromptValue,
|
||||
client_id: this.messageBus.clientId,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -12,18 +12,21 @@ import concatClass from "discourse/helpers/concat-class";
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
import { popupAjaxError } from "discourse/lib/ajax-error";
|
||||
import { bind } from "discourse/lib/decorators";
|
||||
import { escapeExpression } from "discourse/lib/utilities";
|
||||
import { i18n } from "discourse-i18n";
|
||||
import DiffStreamer from "../../lib/diff-streamer";
|
||||
import SmoothStreamer from "../../lib/smooth-streamer";
|
||||
import AiIndicatorWave from "../ai-indicator-wave";
|
||||
|
||||
const CHANNEL = "/discourse-ai/ai-helper/stream_composer_suggestion";
|
||||
|
||||
export default class ModalDiffModal extends Component {
|
||||
@service currentUser;
|
||||
@service messageBus;
|
||||
|
||||
@tracked loading = false;
|
||||
@tracked finalResult = "";
|
||||
@tracked showcasedDiff = "";
|
||||
@tracked escapedSelectedText = escapeExpression(this.args.model.selectedText);
|
||||
@tracked diffStreamer = new DiffStreamer(this.args.model.selectedText);
|
||||
@tracked suggestion = "";
|
||||
@tracked
|
||||
@@ -31,13 +34,28 @@ export default class ModalDiffModal extends Component {
|
||||
() => this.suggestion,
|
||||
(newValue) => (this.suggestion = newValue)
|
||||
);
|
||||
@tracked isStreaming = false;
|
||||
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
this.suggestChanges();
|
||||
}
|
||||
|
||||
get diffResult() {
|
||||
if (this.diffStreamer.diff?.length > 0) {
|
||||
return this.diffStreamer.diff;
|
||||
}
|
||||
|
||||
// Prevents flash by showing the
|
||||
// original text when the diff is empty
|
||||
return this.escapedSelectedText;
|
||||
}
|
||||
|
||||
get isStreaming() {
|
||||
// diffStreamer stops Streaming when it is finished with a chunk, looking at isDone is safe
|
||||
// it starts off not done
|
||||
return !this.diffStreamer.isDone || this.smoothStreamer.isStreaming;
|
||||
}
|
||||
|
||||
get primaryBtnLabel() {
|
||||
return this.loading
|
||||
? i18n("discourse_ai.ai_helper.context_menu.loading")
|
||||
@@ -50,35 +68,24 @@ export default class ModalDiffModal extends Component {
|
||||
|
||||
@bind
|
||||
subscribe() {
|
||||
const channel = "/discourse-ai/ai-helper/stream_composer_suggestion";
|
||||
this.messageBus.subscribe(channel, this.updateResult);
|
||||
this.messageBus.subscribe(CHANNEL, this.updateResult);
|
||||
}
|
||||
|
||||
@bind
|
||||
unsubscribe() {
|
||||
const channel = "/discourse-ai/ai-helper/stream_composer_suggestion";
|
||||
this.messageBus.subscribe(channel, this.updateResult);
|
||||
cleanup() {
|
||||
// stop all callbacks so it does not end up streaming pointlessly
|
||||
this.smoothStreamer.resetStreaming();
|
||||
this.diffStreamer.reset();
|
||||
this.messageBus.unsubscribe(CHANNEL, this.updateResult);
|
||||
}
|
||||
|
||||
@action
|
||||
async updateResult(result) {
|
||||
// TODO(@keegan)
|
||||
// Temporarily we are removing the animation using the diff streamer
|
||||
// and simply showing the diff streamed without a proper animation
|
||||
// while we figure things out
|
||||
// so that things are not too janky in the meantime.
|
||||
updateResult(result) {
|
||||
this.loading = false;
|
||||
this.isStreaming = true;
|
||||
|
||||
if (result.done) {
|
||||
this.finalResult = result.result;
|
||||
}
|
||||
|
||||
this.showcasedDiff = result.diff;
|
||||
|
||||
if (result.done) {
|
||||
this.loading = false;
|
||||
this.isStreaming = false;
|
||||
}
|
||||
|
||||
if (this.args.model.showResultAsDiff) {
|
||||
@@ -103,6 +110,7 @@ export default class ModalDiffModal extends Component {
|
||||
text: this.args.model.selectedText,
|
||||
custom_prompt: this.args.model.customPromptValue,
|
||||
force_default_locale: true,
|
||||
client_id: this.messageBus.clientId,
|
||||
},
|
||||
});
|
||||
} catch (e) {
|
||||
@@ -125,6 +133,7 @@ export default class ModalDiffModal extends Component {
|
||||
this.finalResult?.length > 0
|
||||
? this.finalResult
|
||||
: this.diffStreamer.suggestion;
|
||||
|
||||
if (this.args.model.showResultAsDiff && finalResult) {
|
||||
this.args.model.toolbarEvent.replaceText(
|
||||
this.args.model.selectedText,
|
||||
@@ -140,10 +149,14 @@ export default class ModalDiffModal extends Component {
|
||||
@closeModal={{@closeModal}}
|
||||
>
|
||||
<:body>
|
||||
<div {{didInsert this.subscribe}} {{willDestroy this.unsubscribe}}>
|
||||
<div
|
||||
{{didInsert this.subscribe}}
|
||||
{{willDestroy this.cleanup}}
|
||||
class="text-preview"
|
||||
>
|
||||
{{#if this.loading}}
|
||||
<div class="composer-ai-helper-modal__loading">
|
||||
<CookText @rawText={{@model.selectedText}} />
|
||||
{{~@model.selectedText~}}
|
||||
</div>
|
||||
{{else}}
|
||||
<div
|
||||
@@ -152,10 +165,11 @@ export default class ModalDiffModal extends Component {
|
||||
"streamable-content"
|
||||
(if this.isStreaming "streaming")
|
||||
(if @model.showResultAsDiff "inline-diff")
|
||||
(if this.diffStreamer.isThinking "thinking")
|
||||
}}
|
||||
>
|
||||
{{#if @model.showResultAsDiff}}
|
||||
{{htmlSafe this.showcasedDiff}}
|
||||
{{~#if @model.showResultAsDiff~}}
|
||||
<span class="diff-inner">{{htmlSafe this.diffResult}}</span>
|
||||
{{else}}
|
||||
{{#if this.smoothStreamer.isStreaming}}
|
||||
<CookText
|
||||
|
||||
+9
-3
@@ -19,7 +19,6 @@ export default class AiPostHelperTrigger extends Component {
|
||||
@tracked menuState = this.MENU_STATES.triggers;
|
||||
@tracked showMainButtons = true;
|
||||
@tracked showAiButtons = true;
|
||||
@tracked originalPostHTML = null;
|
||||
@tracked postHighlighted = false;
|
||||
@tracked currentMenu = this.menu.getByIdentifier(
|
||||
"post-text-selection-toolbar"
|
||||
@@ -45,7 +44,6 @@ export default class AiPostHelperTrigger extends Component {
|
||||
return;
|
||||
}
|
||||
|
||||
this.originalPostHTML = postElement.innerHTML;
|
||||
this.selectedText = this.args.outletArgs.data.quoteState.buffer;
|
||||
|
||||
const selection = window.getSelection();
|
||||
@@ -121,7 +119,15 @@ export default class AiPostHelperTrigger extends Component {
|
||||
return;
|
||||
}
|
||||
|
||||
postElement.innerHTML = this.originalPostHTML;
|
||||
const highlightedSpans = postElement.querySelectorAll(
|
||||
"span.ai-helper-highlighted-selection"
|
||||
);
|
||||
|
||||
highlightedSpans.forEach((span) => {
|
||||
const textNode = document.createTextNode(span.textContent);
|
||||
span.parentNode.replaceChild(textNode, span);
|
||||
});
|
||||
|
||||
this.postHighlighted = false;
|
||||
}
|
||||
|
||||
|
||||
+16
-10
@@ -7,6 +7,10 @@ import AiSummaryModal from "../../components/modal/ai-summary-modal";
|
||||
export default class AiSummaryTrigger extends Component {
|
||||
@service modal;
|
||||
|
||||
get isAiConversation() {
|
||||
return this.args.outletArgs.topic.is_bot_pm;
|
||||
}
|
||||
|
||||
@action
|
||||
openAiSummaryModal() {
|
||||
this.modal.show(AiSummaryModal, {
|
||||
@@ -18,15 +22,17 @@ export default class AiSummaryTrigger extends Component {
|
||||
}
|
||||
|
||||
<template>
|
||||
{{#if @outletArgs.topic.summarizable}}
|
||||
<section class="topic-map__additional-contents toggle-summary">
|
||||
<DButton
|
||||
@label="summary.buttons.generate"
|
||||
@icon="discourse-sparkles"
|
||||
@action={{this.openAiSummaryModal}}
|
||||
class="btn-default ai-summarization-button"
|
||||
/>
|
||||
</section>
|
||||
{{/if}}
|
||||
{{#unless this.isAiConversation}}
|
||||
{{#if @outletArgs.topic.summarizable}}
|
||||
<section class="topic-map__additional-contents toggle-summary">
|
||||
<DButton
|
||||
@label="summary.buttons.generate"
|
||||
@icon="discourse-sparkles"
|
||||
@action={{this.openAiSummaryModal}}
|
||||
class="btn-default ai-summarization-button"
|
||||
/>
|
||||
</section>
|
||||
{{/if}}
|
||||
{{/unless}}
|
||||
</template>
|
||||
}
|
||||
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
import Component from "@glimmer/component";
|
||||
import { action } from "@ember/object";
|
||||
import { service } from "@ember/service";
|
||||
import { or } from "truth-helpers";
|
||||
import DButton from "discourse/components/d-button";
|
||||
import Participant from "discourse/components/header/topic/participant";
|
||||
import AddPmParticipants from "discourse/components/modal/add-pm-participants";
|
||||
|
||||
export default class AiConversationInvite extends Component {
|
||||
static shouldRender(args) {
|
||||
return args.topic.is_bot_pm;
|
||||
}
|
||||
|
||||
@service site;
|
||||
@service modal;
|
||||
@service header;
|
||||
@service sidebarState;
|
||||
|
||||
get participants() {
|
||||
const participants = [
|
||||
...(this.header.topicInfo.details?.allowed_users ?? []),
|
||||
...(this.header.topicInfo.details?.allowed_groups ?? []),
|
||||
];
|
||||
return participants;
|
||||
}
|
||||
|
||||
@action
|
||||
showInvite() {
|
||||
this.modal.show(AddPmParticipants, {
|
||||
model: {
|
||||
title: "discourse_ai.ai_bot.invite_ai_conversation.title",
|
||||
inviteModel: this.args.outletArgs.topic,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
<template>
|
||||
<div class="ai-conversation__participants">
|
||||
<DButton
|
||||
@icon="user-plus"
|
||||
@label="discourse_ai.ai_bot.invite_ai_conversation.button"
|
||||
@action={{this.showInvite}}
|
||||
class="btn-default ai-conversations__invite-button"
|
||||
/>
|
||||
{{#each this.participants as |participant|}}
|
||||
<Participant
|
||||
@user={{participant}}
|
||||
@type={{if participant.username "user" "group"}}
|
||||
@username={{or participant.username participant.name}}
|
||||
@avatarSize="medium"
|
||||
/>
|
||||
{{/each}}
|
||||
</div>
|
||||
</template>
|
||||
}
|
||||
@@ -12,13 +12,15 @@ export default class PostUpdater extends StreamUpdater {
|
||||
|
||||
constructor(postStream, postId) {
|
||||
super();
|
||||
|
||||
this.postStream = postStream;
|
||||
this.postId = postId;
|
||||
this.post = postStream.findLoadedPost(postId);
|
||||
const topicId = postStream.topic.id;
|
||||
|
||||
if (this.post) {
|
||||
this.postElement = document.querySelector(
|
||||
`#post_${this.post.post_number}`
|
||||
`.topic-area[data-topic-id="${topicId}"] #post_${this.post.post_number}`
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -57,6 +59,10 @@ export default class PostUpdater extends StreamUpdater {
|
||||
}
|
||||
|
||||
async setCooked(value) {
|
||||
if (!this.postElement) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.post.set("cooked", value);
|
||||
|
||||
(await loadMorphlex()).morphInner(
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -42,8 +42,7 @@ export default class AiConversationsSidebarManager extends Service {
|
||||
if (this.sidebarState.isForcingSidebar && !isAdminSidebarActive) {
|
||||
this.sidebarState.setPanel(MAIN_PANEL); // Return to main sidebar panel
|
||||
this.sidebarState.isForcingSidebar = false;
|
||||
this.appEvents.trigger("discourse-ai:stop-forcing-conversations-sidebar");
|
||||
}
|
||||
|
||||
this.appEvents.trigger("discourse-ai:stop-forcing-conversations-sidebar");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ function initializeAiHelperTrigger(api) {
|
||||
icon: "discourse-sparkles",
|
||||
title: "discourse_ai.ai_helper.context_menu.trigger",
|
||||
preventFocus: true,
|
||||
hideShortcutInTitle: true,
|
||||
shortcut: "ALT+P",
|
||||
shortcutAction: (toolbarEvent) => {
|
||||
if (toolbarEvent.getText().length === 0) {
|
||||
|
||||
@@ -83,14 +83,48 @@ article.streaming .cooked {
|
||||
@keyframes mark-blink {
|
||||
0%,
|
||||
100% {
|
||||
border-color: var(--highlight-high);
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
50% {
|
||||
border-color: transparent;
|
||||
border-color: var(--highlight-high);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fade-in-highlight {
|
||||
from {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
mark.highlight {
|
||||
background-color: var(--highlight-high);
|
||||
animation: fade-in-highlight 0.5s ease-in-out forwards;
|
||||
}
|
||||
|
||||
.composer-ai-helper-modal__suggestion.thinking mark.highlight {
|
||||
animation: mark-blink 1s step-start 0s infinite;
|
||||
animation-name: mark-blink;
|
||||
}
|
||||
|
||||
.composer-ai-helper-modal__loading {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
.composer-ai-helper-modal__suggestion.inline-diff {
|
||||
white-space: pre-wrap;
|
||||
|
||||
del:last-child {
|
||||
text-decoration: none;
|
||||
background-color: transparent;
|
||||
color: var(--primary-low-mid);
|
||||
}
|
||||
|
||||
.diff-inner {
|
||||
display: inline;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,25 +39,22 @@ body.has-ai-conversations-sidebar {
|
||||
.sidebar-section-link.date-heading {
|
||||
pointer-events: none;
|
||||
cursor: default;
|
||||
color: var(--primary-medium);
|
||||
opacity: 0.8;
|
||||
font-weight: 700;
|
||||
color: var(--d-sidebar-header-color);
|
||||
margin-top: 1em;
|
||||
font-size: var(--font-down-2);
|
||||
font-weight: bold;
|
||||
font-size: var(--font-down-2-rem);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05rem;
|
||||
}
|
||||
|
||||
.sidebar-section-link {
|
||||
height: unset;
|
||||
padding-block: 0.65em;
|
||||
font-size: var(--font-down-1);
|
||||
letter-spacing: 0.35px;
|
||||
border-radius: 0 var(--border-radius) var(--border-radius) 0;
|
||||
|
||||
.sidebar-section-link-content-text {
|
||||
white-space: normal;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-line-clamp: 1;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
@@ -78,7 +75,6 @@ body.has-ai-conversations-sidebar {
|
||||
.private-message-glyph-wrapper,
|
||||
.topic-header-participants,
|
||||
.topic-above-footer-buttons-outlet,
|
||||
.topic-map,
|
||||
#topic-footer-buttons .topic-footer-main-buttons details {
|
||||
display: none;
|
||||
}
|
||||
@@ -455,4 +451,82 @@ body.has-ai-conversations-sidebar {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.topic-map {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
padding-block: 0.5em;
|
||||
|
||||
.topic-map__views-trigger,
|
||||
.topic-map__likes-trigger,
|
||||
.summarization-button,
|
||||
&__private-message-map,
|
||||
.topic-map__users-list {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&.--bottom {
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
section {
|
||||
background: transparent;
|
||||
border-block: 1px solid var(--primary-low);
|
||||
}
|
||||
|
||||
&__contents {
|
||||
padding: 0.5em 1.25em;
|
||||
|
||||
@include viewport.from(sm) {
|
||||
padding: 0.5em 0.5em 0.5em 1.9em;
|
||||
}
|
||||
}
|
||||
|
||||
&__stats {
|
||||
height: 100%;
|
||||
flex-wrap: nowrap;
|
||||
gap: 1em;
|
||||
}
|
||||
|
||||
.ai-conversation__participants {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.5em 0.25em;
|
||||
align-items: center;
|
||||
|
||||
.avatar {
|
||||
width: 2em;
|
||||
height: 2em;
|
||||
}
|
||||
|
||||
.trigger-group-card {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border: 1px solid var(--primary-low);
|
||||
border-radius: var(--d-button-border-radius);
|
||||
padding: 0.25em 0.5em;
|
||||
font-size: var(--font-down-1);
|
||||
|
||||
span {
|
||||
position: relative;
|
||||
top: -1px;
|
||||
}
|
||||
|
||||
.d-icon {
|
||||
position: relative;
|
||||
top: 1px;
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--primary-medium);
|
||||
}
|
||||
}
|
||||
|
||||
.btn {
|
||||
font-size: var(--font-down-1);
|
||||
margin-right: 0.5em;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
@use "lib/viewport";
|
||||
|
||||
.composer-ai-helper-modal {
|
||||
.text-preview,
|
||||
.inline-diff {
|
||||
font-family: var(--d-font-family--monospace);
|
||||
font-variant-ligatures: none;
|
||||
|
||||
ins {
|
||||
background-color: var(--success-low);
|
||||
text-decoration: none;
|
||||
@@ -176,7 +181,7 @@
|
||||
|
||||
@keyframes dot-falling {
|
||||
0% {
|
||||
box-shadow: 9999px -15px 0 0 rgba(152, 128, 255, 0);
|
||||
box-shadow: 9999px -15px 0 0 rgb(152, 128, 255, 0);
|
||||
}
|
||||
|
||||
25%,
|
||||
@@ -186,13 +191,13 @@
|
||||
}
|
||||
|
||||
100% {
|
||||
box-shadow: 9999px 15px 0 0 rgba(152, 128, 255, 0);
|
||||
box-shadow: 9999px 15px 0 0 rgb(152, 128, 255, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes dot-falling-before {
|
||||
0% {
|
||||
box-shadow: 9984px -15px 0 0 rgba(152, 128, 255, 0);
|
||||
box-shadow: 9984px -15px 0 0 rgb(152, 128, 255, 0);
|
||||
}
|
||||
|
||||
25%,
|
||||
@@ -202,13 +207,13 @@
|
||||
}
|
||||
|
||||
100% {
|
||||
box-shadow: 9984px 15px 0 0 rgba(152, 128, 255, 0);
|
||||
box-shadow: 9984px 15px 0 0 rgb(152, 128, 255, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes dot-falling-after {
|
||||
0% {
|
||||
box-shadow: 10014px -15px 0 0 rgba(152, 128, 255, 0);
|
||||
box-shadow: 10014px -15px 0 0 rgb(152, 128, 255, 0);
|
||||
}
|
||||
|
||||
25%,
|
||||
@@ -218,7 +223,7 @@
|
||||
}
|
||||
|
||||
100% {
|
||||
box-shadow: 10014px 15px 0 0 rgba(152, 128, 255, 0);
|
||||
box-shadow: 10014px 15px 0 0 rgb(152, 128, 255, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -229,19 +234,6 @@
|
||||
input:focus {
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
input {
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.category-chooser,
|
||||
.mini-tag-chooser {
|
||||
.select-kit-header {
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
}
|
||||
|
||||
#edit-title {
|
||||
@@ -636,7 +628,7 @@
|
||||
height: 7em;
|
||||
min-width: var(--ai-caption-popup-min-width);
|
||||
|
||||
@include breakpoint(tablet) {
|
||||
@include viewport.until(md) {
|
||||
width: 100%;
|
||||
max-width: unset;
|
||||
min-width: unset;
|
||||
|
||||
@@ -603,6 +603,8 @@ ar:
|
||||
share_ai_conversation:
|
||||
name: "مشاركة محادثة الذكاء الاصطناعي"
|
||||
title: "مشاركة هذه المحادثة بشكلٍ علني"
|
||||
invite_ai_conversation:
|
||||
button: "دعوة"
|
||||
ai_label: "الذكاء الاصطناعي"
|
||||
ai_title: "المحادثة مع الذكاء الاصطناعي"
|
||||
share_modal:
|
||||
|
||||
@@ -134,6 +134,8 @@ bg:
|
||||
request: "Заявка"
|
||||
next_log: "Напред"
|
||||
previous_log: "Предишни"
|
||||
invite_ai_conversation:
|
||||
button: "Покана"
|
||||
share_modal:
|
||||
copy: "Копирай"
|
||||
conversations:
|
||||
|
||||
@@ -128,6 +128,8 @@ bs_BA:
|
||||
response: "Odgovor"
|
||||
next_log: "Iduće"
|
||||
previous_log: "Previous"
|
||||
invite_ai_conversation:
|
||||
button: "Invite"
|
||||
share_modal:
|
||||
copy: "Copy"
|
||||
conversations:
|
||||
|
||||
@@ -133,6 +133,8 @@ ca:
|
||||
response: "Reacció"
|
||||
next_log: "Següent"
|
||||
previous_log: "Previ"
|
||||
invite_ai_conversation:
|
||||
button: "Convida"
|
||||
share_modal:
|
||||
copy: "Còpia"
|
||||
conversations:
|
||||
|
||||
@@ -211,24 +211,69 @@ cs:
|
||||
ai_artifact:
|
||||
collapse_view_label: "Ukončení celé obrazovky (ESC nebo tlačítko Zpět)"
|
||||
ai_bot:
|
||||
pm_warning: "Zprávy chatbotů s umělou inteligencí jsou pravidelně monitorovány moderátory."
|
||||
cancel_streaming: "Zastavit odpověď"
|
||||
default_pm_prefix: "[Nepojmenovaná SZ od AI bota]"
|
||||
shortcut_title: "Začněte SZ s AI botem"
|
||||
share: "Kopírovat konverzaci s AI"
|
||||
conversation_shared: "Konverzace zkopírována"
|
||||
debug_ai: "Zobrazit nezpracovaný požadavek a odpověď umělé inteligence"
|
||||
sidebar_empty: "Zde se zobrazí historie konverzace s botem."
|
||||
debug_ai_modal:
|
||||
title: "Zobrazit interakci s umělou inteligencí"
|
||||
copy_request: "Kopírovat požadavek"
|
||||
copy_response: "Kopírovat odpověď"
|
||||
request_tokens: "Tokeny požadavku:"
|
||||
response_tokens: "Tokeny odpovědi:"
|
||||
request: "Požadavek"
|
||||
response: "Odpověď"
|
||||
next_log: "Další"
|
||||
previous_log: "Předchozí"
|
||||
share_full_topic_modal:
|
||||
title: "Veřejně sdílet konverzaci"
|
||||
share: "Sdílet a kopírovat odkaz"
|
||||
update: "Aktualizovat a zkopírovat odkaz"
|
||||
delete: "Odstranit sdílení"
|
||||
share_ai_conversation:
|
||||
name: "Sdílet konverzaci s AI"
|
||||
title: "Sdílejte veřejně tuto konverzaci s umělou inteligencí"
|
||||
invite_ai_conversation:
|
||||
button: "Pozvat"
|
||||
title: "Pozvat do konverzace s AI"
|
||||
ai_title: "Konverzace s AI"
|
||||
share_modal:
|
||||
title: "Kopírovat konverzaci s AI"
|
||||
copy: "Kopírovat"
|
||||
context: "Interakce ke sdílení:"
|
||||
share_tip: "Můžete také sdílet celou konverzaci."
|
||||
bot_names:
|
||||
fake: "Falešný testovací bot"
|
||||
claude-3-opus: "Claude 3 Opus"
|
||||
claude-3-sonnet: "Claude 3 Sonet"
|
||||
claude-3-haiku: "Haiku Claude 3"
|
||||
cohere-command-r-plus: "Cohere Command R Plus"
|
||||
gpt-4: "GPT-4"
|
||||
gpt-4-turbo: "GPT-4 Turbo"
|
||||
gpt-4o: "GPT-4 Omni"
|
||||
gpt-3:
|
||||
5-turbo: "GPT-3.5"
|
||||
claude-2: "Claude 2"
|
||||
gemini-1:
|
||||
5-pro: "Gemini"
|
||||
mixtral-8x7B-Instruct-V0:
|
||||
"1": "Mixtral-8x7B V0.1"
|
||||
conversations:
|
||||
header: "S čím mohu pomoci?"
|
||||
submit: "Odeslat otázku"
|
||||
disclaimer: "Generativní umělá inteligence může dělat chyby. Ověřte si důležité informace."
|
||||
placeholder: "Zeptejte se..."
|
||||
new: "Nová otázka"
|
||||
min_input_length_message:
|
||||
one: "Zpráva musí mít 1 nebo více znaků"
|
||||
few: "Zpráva musí mít %{count} nebo více znaků"
|
||||
many: "Zpráva musí mít %{count} nebo více znaků"
|
||||
other: "Zpráva musí mít %{count} nebo více znaků"
|
||||
messages_sidebar_title: "Konverzace"
|
||||
today: "Dnes"
|
||||
last_7_days: "Posledních 7 dní"
|
||||
last_30_days: "Posledních 30 dní"
|
||||
|
||||
@@ -147,6 +147,8 @@ da:
|
||||
response: "Svar"
|
||||
next_log: "Næste"
|
||||
previous_log: "Forrige"
|
||||
invite_ai_conversation:
|
||||
button: "Invitér"
|
||||
share_modal:
|
||||
copy: "Kopier"
|
||||
conversations:
|
||||
|
||||
@@ -320,9 +320,20 @@ de:
|
||||
rag_conversation_chunks_help: "Die Anzahl der Chunks, die für die RAG-Modell-Suche verwendet werden. Erhöhen, um die Menge des Kontexts zu steigern, den die KI verwenden kann."
|
||||
persona_description: "Personas sind eine leistungsstarke Funktion, mit der du das Verhalten der KI-Engine in deinem Discourse-Forum anpassen kannst. Sie fungieren als „Systemnachricht“, welche die Antworten und Interaktionen der KI steuert und dazu beiträgt, ein persönlicheres und ansprechenderes Erlebnis für Benutzer zu schaffen."
|
||||
response_format:
|
||||
title: "JSON-Antwortformat"
|
||||
no_format: "Kein JSON-Format angegeben"
|
||||
open_modal: "Bearbeiten"
|
||||
modal:
|
||||
root_title: "Antwortstruktur"
|
||||
key_title: "Schlüssel"
|
||||
examples:
|
||||
title: Beispiele
|
||||
examples_help: Simuliere frühere Interaktionen mit dem LLM und erde es, um bessere Ergebnisse zu erzielen.
|
||||
new: Neues Beispiel
|
||||
remove: Beispiel löschen
|
||||
collapsable_title: "Beispiel #%{number}"
|
||||
user: "Nachricht des Benutzers"
|
||||
model: "Antwort des Modells"
|
||||
list:
|
||||
enabled: "KI-Bot?"
|
||||
ai_bot:
|
||||
@@ -513,7 +524,9 @@ de:
|
||||
provider_quantizations: "Reihenfolge der Provider-Quantisierungen (kommagetrennte Liste, z. B.: fp16,fp8)"
|
||||
disable_streaming: "Streaming-Vervollständigung deaktivieren (Streaming-Anfragen in Nicht-Streaming-Anfragen umwandeln)"
|
||||
reasoning_effort: "Argumentationsaufwand (gilt nur für Argumentationsmodelle)"
|
||||
enable_reasoning: "Argumentation aktivieren (gilt nur für Sonnet 3.7)"
|
||||
enable_reasoning: "Argumentation aktivieren (nur für Argumentationsmodelle anwendbar)"
|
||||
enable_thinking: "Denken aktivieren (nur bei entsprechenden Modellen, z.B.: Flash 2.5)"
|
||||
thinking_tokens: "Anzahl der zum Denken verwendeten Token"
|
||||
reasoning_tokens: "Anzahl der für die Argumentation verwendeten Token"
|
||||
disable_temperature: "Temperatur deaktivieren (einige Denkmodelle unterstützen keine Temperatur)"
|
||||
disable_top_p: "Top P deaktivieren (einige Denkmodelle unterstützen Top P nicht)"
|
||||
@@ -654,6 +667,7 @@ de:
|
||||
share: "KI-Unterhaltung kopieren"
|
||||
conversation_shared: "Unterhaltung kopiert"
|
||||
debug_ai: "Rohdaten der KI-Anfrage und -Antwort anzeigen"
|
||||
sidebar_empty: "Der Verlauf der Bot-Konversation wird hier angezeigt."
|
||||
debug_ai_modal:
|
||||
title: "KI-Interaktion ansehen"
|
||||
copy_request: "Anfrage kopieren"
|
||||
@@ -672,6 +686,9 @@ de:
|
||||
share_ai_conversation:
|
||||
name: "KI-Unterhaltung teilen"
|
||||
title: "Diese KI-Unterhaltung öffentlich teilen"
|
||||
invite_ai_conversation:
|
||||
button: "Einladen"
|
||||
title: "Zur KI-Konversation einladen"
|
||||
ai_label: "KI"
|
||||
ai_title: "Unterhaltung mit KI"
|
||||
share_modal:
|
||||
@@ -701,6 +718,9 @@ de:
|
||||
disclaimer: "Generative KI kann Fehler machen. Überprüfe wichtige Informationen."
|
||||
placeholder: "Stell eine Frage ..."
|
||||
new: "Neue Frage"
|
||||
min_input_length_message:
|
||||
one: "Nachricht muss mindestens 1 Zeichen lang sein"
|
||||
other: "Nachricht muss mindestens %{count} Zeichen lang sein"
|
||||
messages_sidebar_title: "Unterhaltungen"
|
||||
today: "Heute"
|
||||
last_7_days: "Letzte 7 Tage"
|
||||
|
||||
@@ -142,6 +142,8 @@ el:
|
||||
response: "Απάντηση"
|
||||
next_log: "Επόμενο"
|
||||
previous_log: "Προηγούμενο"
|
||||
invite_ai_conversation:
|
||||
button: "Πρόσκληση"
|
||||
share_modal:
|
||||
copy: "Αντιγραφή"
|
||||
conversations:
|
||||
|
||||
@@ -540,7 +540,7 @@ en:
|
||||
provider_quantizations: "Order of provider quantizations (comma delimited list eg: fp16,fp8)"
|
||||
disable_streaming: "Disable streaming completions (convert streaming to non streaming requests)"
|
||||
reasoning_effort: "Reasoning effort (only applicable to reasoning models)"
|
||||
enable_reasoning: "Enable reasoning (only applicable to Sonnet 3.7)"
|
||||
enable_reasoning: "Enable reasoning (only applicable to reasoning models)"
|
||||
enable_thinking: "Enable thinking (only on applicable models eg: flash 2.5)"
|
||||
thinking_tokens: "Number of tokens used for thinking"
|
||||
reasoning_tokens: "Number of tokens used for reasoning"
|
||||
@@ -712,6 +712,10 @@ en:
|
||||
name: "Share AI conversation"
|
||||
title: "Share this AI conversation publicly"
|
||||
|
||||
invite_ai_conversation:
|
||||
button: "Invite"
|
||||
title: "Invite to AI conversation"
|
||||
|
||||
ai_label: "AI"
|
||||
ai_title: "Conversation with AI"
|
||||
|
||||
|
||||
@@ -591,6 +591,8 @@ es:
|
||||
share_ai_conversation:
|
||||
name: "Compartir conversación de IA"
|
||||
title: "Compartir esta conversación de IA públicamente"
|
||||
invite_ai_conversation:
|
||||
button: "Invitar"
|
||||
ai_label: "IA"
|
||||
ai_title: "Conversación con IA"
|
||||
share_modal:
|
||||
|
||||
@@ -130,6 +130,8 @@ et:
|
||||
response: "Vastus"
|
||||
next_log: "Järgmine"
|
||||
previous_log: "Eelmine"
|
||||
invite_ai_conversation:
|
||||
button: "Kutsu"
|
||||
share_modal:
|
||||
copy: "Kopeeri"
|
||||
conversations:
|
||||
|
||||
@@ -187,6 +187,8 @@ fa_IR:
|
||||
response: "پاسخ"
|
||||
next_log: "بعدی"
|
||||
previous_log: "پیشین"
|
||||
invite_ai_conversation:
|
||||
button: "دعوت"
|
||||
ai_label: "هوش مصنوعی"
|
||||
share_modal:
|
||||
copy: "کپی"
|
||||
|
||||
@@ -591,6 +591,8 @@ fi:
|
||||
share_ai_conversation:
|
||||
name: "Jaa tekoälykeskustelu"
|
||||
title: "Jaa tämä tekoälykeskustelu julkisesti"
|
||||
invite_ai_conversation:
|
||||
button: "Kutsu"
|
||||
ai_label: "Tekoäly"
|
||||
ai_title: "Keskustelu tekoälyn kanssa"
|
||||
share_modal:
|
||||
|
||||
@@ -591,6 +591,8 @@ fr:
|
||||
share_ai_conversation:
|
||||
name: "Partager une conversation IA"
|
||||
title: "Partager publiquement cette conversation avec l'IA"
|
||||
invite_ai_conversation:
|
||||
button: "Inviter"
|
||||
ai_label: "IA"
|
||||
ai_title: "Conversation avec l'IA"
|
||||
share_modal:
|
||||
|
||||
@@ -140,6 +140,8 @@ gl:
|
||||
response: "Resposta"
|
||||
next_log: "Seguinte"
|
||||
previous_log: "Anterior"
|
||||
invite_ai_conversation:
|
||||
button: "Convidar"
|
||||
share_modal:
|
||||
copy: "Copiar"
|
||||
conversations:
|
||||
|
||||
@@ -309,6 +309,13 @@ he:
|
||||
modal:
|
||||
root_title: "מבנה תגובה"
|
||||
key_title: "מפתח"
|
||||
examples:
|
||||
title: דוגמאות
|
||||
new: דוגמה חדשה
|
||||
remove: מחיקת דוגמה
|
||||
collapsable_title: "דוגמה מס׳ %{number}"
|
||||
user: "הודעת משתמש"
|
||||
model: "תגובת המודל"
|
||||
list:
|
||||
enabled: "בוט בינה מלאכותית?"
|
||||
ai_bot:
|
||||
@@ -490,7 +497,8 @@ he:
|
||||
disable_native_tools: "השבתת תמיכה בבלי מובנה (להשתמש בכלים מבוססי XML)"
|
||||
provider_order: "סדר ספקים (רשימה מופרדת בפסיקים)"
|
||||
provider_quantizations: "סדר כימות הספקים (רשימה מופרדת בפסיקים, למשל: fp16,fp8)"
|
||||
enable_reasoning: "הפעלת נימוק (תקף רק על Sonnet 3.7)"
|
||||
reasoning_effort: "מאמץ נימוק (תקף רק על מודלים של נימוק)"
|
||||
enable_thinking: "הפעלת חשיבה (רק במודלים תקפים לדוגמה: flash 2.5)"
|
||||
reasoning_tokens: "כמות אסימונים המשמשים לנימוק"
|
||||
related_topics:
|
||||
title: "נושאים קשורים"
|
||||
@@ -624,6 +632,7 @@ he:
|
||||
share: "העתקת דיון עם בינה מלאכותית"
|
||||
conversation_shared: "הדיון הועתק"
|
||||
debug_ai: "הצגת בקשה ותגובה גולמיות לבינה המלאכותית"
|
||||
sidebar_empty: "היסטוריית השיחה עם הבוט תופיע כאן."
|
||||
debug_ai_modal:
|
||||
title: "הצגת התכתובת מול הבינה המלאכותית"
|
||||
copy_request: "העתקת הבקשה"
|
||||
@@ -642,6 +651,9 @@ he:
|
||||
share_ai_conversation:
|
||||
name: "שיתוף דיון עם בינה מלאכותית"
|
||||
title: "שיתוף שיחת בינה מלאכותית באופן ציבורי"
|
||||
invite_ai_conversation:
|
||||
button: "להזמין"
|
||||
title: "הזמנה לשיחה עם בינה מלאכותית"
|
||||
ai_label: "בינה מלאכותית"
|
||||
ai_title: "דיון עם בינה מלאכותית"
|
||||
share_modal:
|
||||
@@ -668,6 +680,7 @@ he:
|
||||
conversations:
|
||||
header: "איך אפשר לעזור?"
|
||||
submit: "הגשת שאלה"
|
||||
disclaimer: "בינה מלאכותית מחוללת עלולה לשגות. כדאי לאמת פרטים חשובים."
|
||||
placeholder: "הגשת שאלה…"
|
||||
new: "שאלה חדשה"
|
||||
messages_sidebar_title: "שיחות"
|
||||
@@ -714,6 +727,7 @@ he:
|
||||
discobot_discoveries:
|
||||
regular_results: "נושאים"
|
||||
tell_me_more: "אשמח לדעת עוד…"
|
||||
continue_convo: "המשך בשיחה…"
|
||||
collapse: "צמצום"
|
||||
tooltip:
|
||||
header: "חיפוש מופעל בינה מלאכותית"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user