diff --git a/api/controllers/common/fields.py b/api/controllers/common/fields.py index b52f41b5413..bda3b4b0421 100644 --- a/api/controllers/common/fields.py +++ b/api/controllers/common/fields.py @@ -475,6 +475,7 @@ class Parameters(BaseModel): speech_to_text: FeatureToggleObject text_to_speech: TextToSpeechObject retriever_resource: FeatureToggleObject + show_thoughts: FeatureToggleObject = Field(default_factory=lambda: {"enabled": False}) annotation_reply: FeatureToggleObject more_like_this: FeatureToggleObject user_input_form: UserInputFormList diff --git a/api/core/app/app_config/common/parameters_mapping/__init__.py b/api/core/app/app_config/common/parameters_mapping/__init__.py index 68686ceda65..a8c2e8f7a7a 100644 --- a/api/core/app/app_config/common/parameters_mapping/__init__.py +++ b/api/core/app/app_config/common/parameters_mapping/__init__.py @@ -24,6 +24,7 @@ class AppParametersDict(TypedDict): speech_to_text: FeatureToggleDict text_to_speech: FeatureToggleDict retriever_resource: FeatureToggleDict + show_thoughts: FeatureToggleDict annotation_reply: FeatureToggleDict more_like_this: FeatureToggleDict user_input_form: list[dict[str, Any]] @@ -36,7 +37,9 @@ def get_parameters_from_feature_dict( *, features_dict: Mapping[str, Any], user_input_form: list[dict[str, Any]] ) -> AppParametersDict: """ - Mapping from feature dict to webapp parameters + Map a feature mapping and input form to webapp parameters without mutating either. + + Missing or null show_thoughts is exposed as disabled for legacy configurations. """ return { "opening_statement": features_dict.get("opening_statement"), @@ -45,6 +48,7 @@ def get_parameters_from_feature_dict( "speech_to_text": features_dict.get("speech_to_text", {"enabled": False}), "text_to_speech": features_dict.get("text_to_speech", {"enabled": False}), "retriever_resource": features_dict.get("retriever_resource", {"enabled": False}), + "show_thoughts": features_dict.get("show_thoughts") or {"enabled": False}, "annotation_reply": features_dict.get("annotation_reply", {"enabled": False}), "more_like_this": features_dict.get("more_like_this", {"enabled": False}), "user_input_form": user_input_form, diff --git a/api/models/agent_config_entities.py b/api/models/agent_config_entities.py index 59c9b1daf04..c800ba94ac8 100644 --- a/api/models/agent_config_entities.py +++ b/api/models/agent_config_entities.py @@ -606,6 +606,8 @@ class AgentSoulAppFeaturesConfig(AgentFlexibleConfig): speech_to_text: AgentFeatureToggleConfig | None = None text_to_speech: AgentTextToSpeechFeatureConfig | None = None retriever_resource: AgentFeatureToggleConfig | None = None + # Missing or null preserves the default of hiding model thoughts in chat. + show_thoughts: AgentFeatureToggleConfig | None = None sensitive_word_avoidance: AgentSensitiveWordAvoidanceFeatureConfig | None = None file_upload: AgentFileUploadFeatureConfig = Field(default_factory=AgentFileUploadFeatureConfig) diff --git a/api/openapi/markdown/console-openapi.md b/api/openapi/markdown/console-openapi.md index fe98a7f7e92..c4da769ac2e 100644 --- a/api/openapi/markdown/console-openapi.md +++ b/api/openapi/markdown/console-openapi.md @@ -20753,6 +20753,7 @@ Visibility and lifecycle scope of an Agent record. | opening_statement | string | | No | | retriever_resource | [AgentFeatureToggleConfig](#agentfeaturetoggleconfig) | | No | | sensitive_word_avoidance | [AgentSensitiveWordAvoidanceFeatureConfig](#agentsensitivewordavoidancefeatureconfig) | | No | +| show_thoughts | [AgentFeatureToggleConfig](#agentfeaturetoggleconfig) | | No | | speech_to_text | [AgentFeatureToggleConfig](#agentfeaturetoggleconfig) | | No | | suggested_questions | [ string ] | | No | | suggested_questions_after_answer | [AgentSuggestedQuestionsAfterAnswerFeatureConfig](#agentsuggestedquestionsafteranswerfeatureconfig) | | No | @@ -32215,6 +32216,7 @@ Enum class for parameter type. | opening_statement | | | No | | retriever_resource | { **"enabled"**: boolean } | | Yes | | sensitive_word_avoidance | { **"enabled"**: boolean } | | Yes | +| show_thoughts | { **"enabled"**: boolean } | | No | | speech_to_text | { **"enabled"**: boolean } | | Yes | | suggested_questions | [ string ] | | Yes | | suggested_questions_after_answer | { **"enabled"**: boolean } | | Yes | diff --git a/api/openapi/markdown/service-openapi.md b/api/openapi/markdown/service-openapi.md index 0962c702afd..3241af270b2 100644 --- a/api/openapi/markdown/service-openapi.md +++ b/api/openapi/markdown/service-openapi.md @@ -7380,6 +7380,7 @@ Form input definition. | opening_statement | | | No | | retriever_resource | { **"enabled"**: boolean } | | Yes | | sensitive_word_avoidance | { **"enabled"**: boolean } | | Yes | +| show_thoughts | { **"enabled"**: boolean } | | No | | speech_to_text | { **"enabled"**: boolean } | | Yes | | suggested_questions | [ string ] | | Yes | | suggested_questions_after_answer | { **"enabled"**: boolean } | | Yes | diff --git a/api/openapi/markdown/web-openapi.md b/api/openapi/markdown/web-openapi.md index 3926fc2d228..3d35c1c8d14 100644 --- a/api/openapi/markdown/web-openapi.md +++ b/api/openapi/markdown/web-openapi.md @@ -2071,6 +2071,7 @@ Form input definition. | opening_statement | | | No | | retriever_resource | { **"enabled"**: boolean } | | Yes | | sensitive_word_avoidance | { **"enabled"**: boolean } | | Yes | +| show_thoughts | { **"enabled"**: boolean } | | No | | speech_to_text | { **"enabled"**: boolean } | | Yes | | suggested_questions | [ string ] | | Yes | | suggested_questions_after_answer | { **"enabled"**: boolean } | | Yes | diff --git a/api/tests/unit_tests/controllers/common/test_fields.py b/api/tests/unit_tests/controllers/common/test_fields.py index 1d0dd8a9462..4d62efb5ed1 100644 --- a/api/tests/unit_tests/controllers/common/test_fields.py +++ b/api/tests/unit_tests/controllers/common/test_fields.py @@ -1,5 +1,7 @@ from unittest.mock import patch +import pytest + from controllers.common.fields import Parameters, Site from core.app.app_config.common.parameters_mapping import get_parameters_from_feature_dict from models.model import IconType @@ -13,6 +15,22 @@ def test_parameters_model_round_trip() -> None: assert model.model_dump(mode="json") == parameters +@pytest.mark.parametrize("enabled", [False, True]) +def test_parameters_serializes_show_thoughts(enabled: bool) -> None: + parameters = get_parameters_from_feature_dict( + features_dict={"show_thoughts": {"enabled": enabled}}, user_input_form=[] + ) + + assert Parameters.model_validate(parameters).model_dump(mode="json")["show_thoughts"] == {"enabled": enabled} + + +def test_parameters_defaults_show_thoughts_for_legacy_payload() -> None: + parameters = dict(get_parameters_from_feature_dict(features_dict={}, user_input_form=[])) + parameters.pop("show_thoughts") + + assert Parameters.model_validate(parameters).model_dump(mode="json")["show_thoughts"] == {"enabled": False} + + def test_site_icon_url_uses_signed_url_for_image_icon() -> None: site = Site( title="Example", diff --git a/api/tests/unit_tests/controllers/console/explore/test_installed_app_admission.py b/api/tests/unit_tests/controllers/console/explore/test_installed_app_admission.py index 5381c521e52..be805616c3b 100644 --- a/api/tests/unit_tests/controllers/console/explore/test_installed_app_admission.py +++ b/api/tests/unit_tests/controllers/console/explore/test_installed_app_admission.py @@ -490,6 +490,7 @@ def test_migrated_saved_message_and_parameter_handlers_dispatch_through_full_adm "retriever_resource", "annotation_reply", "more_like_this", + "show_thoughts", "sensitive_word_avoidance", "file_upload", ) diff --git a/api/tests/unit_tests/controllers/console/explore/test_trial.py b/api/tests/unit_tests/controllers/console/explore/test_trial.py index 56937256b30..aaaf2b305e8 100644 --- a/api/tests/unit_tests/controllers/console/explore/test_trial.py +++ b/api/tests/unit_tests/controllers/console/explore/test_trial.py @@ -2490,6 +2490,7 @@ class TestTrialPreviewCases: "retriever_resource": {"enabled": False}, "annotation_reply": {"enabled": False}, "more_like_this": {"enabled": False}, + "show_thoughts": {"enabled": False}, "user_input_form": _INPUT_FORM, "sensitive_word_avoidance": {"enabled": False, "type": "", "configs": []}, "file_upload": {"enabled": False, "number_limits": 0}, diff --git a/api/tests/unit_tests/core/app/app_config/common/parameters_mapping/test___init__.py b/api/tests/unit_tests/core/app/app_config/common/parameters_mapping/test___init__.py index 9e0a550c856..3dda9f1c44c 100644 --- a/api/tests/unit_tests/core/app/app_config/common/parameters_mapping/test___init__.py +++ b/api/tests/unit_tests/core/app/app_config/common/parameters_mapping/test___init__.py @@ -21,6 +21,15 @@ type _DefaultedFeatureKey = Literal[ class TestGetParametersFromFeatureDict: """Test suite for get_parameters_from_feature_dict""" + @pytest.mark.parametrize( + ("features", "enabled"), + [({}, False), ({"show_thoughts": None}, False), ({"show_thoughts": {"enabled": True}}, True)], + ) + def test_show_thoughts_parameters(self, features: dict[str, object], enabled: bool) -> None: + result = parameters_mapping.get_parameters_from_feature_dict(features_dict=features, user_input_form=[]) + + assert result["show_thoughts"] == {"enabled": enabled} + @pytest.fixture def mock_config(self, monkeypatch: pytest.MonkeyPatch) -> None: """Override file limits on the shared typed config.""" diff --git a/api/tests/unit_tests/models/test_agent_config_entities.py b/api/tests/unit_tests/models/test_agent_config_entities.py index 172027c4a97..1bcf2456b8d 100644 --- a/api/tests/unit_tests/models/test_agent_config_entities.py +++ b/api/tests/unit_tests/models/test_agent_config_entities.py @@ -4,6 +4,7 @@ from pydantic import ValidationError from core.workflow.file_reference import build_file_reference from models.agent_config_entities import ( AgentKnowledgeSpaceConfig, + AgentSoulAppFeaturesConfig, AgentSoulConfig, AgentSoulKnowledgeConfig, AgentSoulModelSettings, @@ -16,6 +17,23 @@ from models.agent_config_entities import ( ) +@pytest.mark.parametrize("payload", [{}, {"show_thoughts": None}, {"show_thoughts": {}}]) +def test_show_thoughts_defaults_to_disabled(payload: dict[str, object]) -> None: + features = AgentSoulAppFeaturesConfig.model_validate(payload) + + assert features.show_thoughts is None or features.show_thoughts.enabled is False + + +@pytest.mark.parametrize("enabled", [False, True]) +def test_show_thoughts_round_trips_in_agent_soul(enabled: bool) -> None: + soul = AgentSoulConfig.model_validate({"app_features": {"show_thoughts": {"enabled": enabled}}}) + + restored = AgentSoulConfig.model_validate_json(soul.model_dump_json()) + + assert restored.app_features.show_thoughts is not None + assert restored.app_features.show_thoughts.enabled is enabled + + def test_agent_soul_model_settings_preserves_plugin_declared_parameters() -> None: settings = AgentSoulModelSettings.model_validate( { diff --git a/oxlint-suppressions.json b/oxlint-suppressions.json index db3e7351966..ab65a7219a0 100644 --- a/oxlint-suppressions.json +++ b/oxlint-suppressions.json @@ -1032,16 +1032,6 @@ "count": 91 } }, - "web/app/components/base/chat/chat/answer/agent-roster-response-content.tsx": { - "better-tailwindcss/enforce-logical-properties": { - "count": 2 - } - }, - "web/app/components/base/chat/chat/answer/index.tsx": { - "better-tailwindcss/enforce-logical-properties": { - "count": 7 - } - }, "web/app/components/base/chat/chat/answer/more.tsx": { "better-tailwindcss/enforce-logical-properties": { "count": 3 diff --git a/packages/contracts/generated/api/console/agent/types.gen.ts b/packages/contracts/generated/api/console/agent/types.gen.ts index e6392b23c7b..8ea0146e7fd 100644 --- a/packages/contracts/generated/api/console/agent/types.gen.ts +++ b/packages/contracts/generated/api/console/agent/types.gen.ts @@ -1581,6 +1581,7 @@ export type AgentSoulAppFeaturesConfig = { opening_statement?: string | null retriever_resource?: AgentFeatureToggleConfig | null sensitive_word_avoidance?: AgentSensitiveWordAvoidanceFeatureConfig | null + show_thoughts?: AgentFeatureToggleConfig | null speech_to_text?: AgentFeatureToggleConfig | null suggested_questions?: Array | null suggested_questions_after_answer?: AgentSuggestedQuestionsAfterAnswerFeatureConfig | null diff --git a/packages/contracts/generated/api/console/agent/zod.gen.ts b/packages/contracts/generated/api/console/agent/zod.gen.ts index f877891c087..960f6215373 100644 --- a/packages/contracts/generated/api/console/agent/zod.gen.ts +++ b/packages/contracts/generated/api/console/agent/zod.gen.ts @@ -3133,6 +3133,7 @@ export const zAgentSoulAppFeaturesConfig = z.object({ opening_statement: z.string().nullish(), retriever_resource: zAgentFeatureToggleConfig.nullish(), sensitive_word_avoidance: zAgentSensitiveWordAvoidanceFeatureConfig.nullish(), + show_thoughts: zAgentFeatureToggleConfig.nullish(), speech_to_text: zAgentFeatureToggleConfig.nullish(), suggested_questions: z.array(z.string()).nullish(), suggested_questions_after_answer: zAgentSuggestedQuestionsAfterAnswerFeatureConfig.nullish(), diff --git a/packages/contracts/generated/api/console/apps/types.gen.ts b/packages/contracts/generated/api/console/apps/types.gen.ts index a83d555d18e..5ca592e9fbe 100644 --- a/packages/contracts/generated/api/console/apps/types.gen.ts +++ b/packages/contracts/generated/api/console/apps/types.gen.ts @@ -3525,6 +3525,7 @@ export type AgentSoulAppFeaturesConfig = { opening_statement?: string | null retriever_resource?: AgentFeatureToggleConfig | null sensitive_word_avoidance?: AgentSensitiveWordAvoidanceFeatureConfig | null + show_thoughts?: AgentFeatureToggleConfig | null speech_to_text?: AgentFeatureToggleConfig | null suggested_questions?: Array | null suggested_questions_after_answer?: AgentSuggestedQuestionsAfterAnswerFeatureConfig | null diff --git a/packages/contracts/generated/api/console/apps/zod.gen.ts b/packages/contracts/generated/api/console/apps/zod.gen.ts index 1c76c5dfcfa..0582c22e175 100644 --- a/packages/contracts/generated/api/console/apps/zod.gen.ts +++ b/packages/contracts/generated/api/console/apps/zod.gen.ts @@ -6090,6 +6090,7 @@ export const zAgentSoulAppFeaturesConfig = z.object({ opening_statement: z.string().nullish(), retriever_resource: zAgentFeatureToggleConfig.nullish(), sensitive_word_avoidance: zAgentSensitiveWordAvoidanceFeatureConfig.nullish(), + show_thoughts: zAgentFeatureToggleConfig.nullish(), speech_to_text: zAgentFeatureToggleConfig.nullish(), suggested_questions: z.array(z.string()).nullish(), suggested_questions_after_answer: zAgentSuggestedQuestionsAfterAnswerFeatureConfig.nullish(), diff --git a/packages/contracts/generated/api/console/installed-apps/types.gen.ts b/packages/contracts/generated/api/console/installed-apps/types.gen.ts index c321dc5ba88..c16bf11665d 100644 --- a/packages/contracts/generated/api/console/installed-apps/types.gen.ts +++ b/packages/contracts/generated/api/console/installed-apps/types.gen.ts @@ -299,6 +299,9 @@ export type Parameters = { sensitive_word_avoidance: { enabled?: boolean } + show_thoughts?: { + enabled?: boolean + } speech_to_text: { enabled?: boolean } diff --git a/packages/contracts/generated/api/console/installed-apps/zod.gen.ts b/packages/contracts/generated/api/console/installed-apps/zod.gen.ts index 8241be8286f..0a16996c253 100644 --- a/packages/contracts/generated/api/console/installed-apps/zod.gen.ts +++ b/packages/contracts/generated/api/console/installed-apps/zod.gen.ts @@ -609,6 +609,11 @@ export const zParameters = z.object({ sensitive_word_avoidance: z.object({ enabled: z.boolean().optional(), }), + show_thoughts: z + .object({ + enabled: z.boolean().optional(), + }) + .optional(), speech_to_text: z.object({ enabled: z.boolean().optional(), }), diff --git a/packages/contracts/generated/api/console/snippets/types.gen.ts b/packages/contracts/generated/api/console/snippets/types.gen.ts index 9d8d655e070..f87e806bdc0 100644 --- a/packages/contracts/generated/api/console/snippets/types.gen.ts +++ b/packages/contracts/generated/api/console/snippets/types.gen.ts @@ -628,6 +628,7 @@ export type AgentSoulAppFeaturesConfig = { opening_statement?: string | null retriever_resource?: AgentFeatureToggleConfig | null sensitive_word_avoidance?: AgentSensitiveWordAvoidanceFeatureConfig | null + show_thoughts?: AgentFeatureToggleConfig | null speech_to_text?: AgentFeatureToggleConfig | null suggested_questions?: Array | null suggested_questions_after_answer?: AgentSuggestedQuestionsAfterAnswerFeatureConfig | null diff --git a/packages/contracts/generated/api/console/snippets/zod.gen.ts b/packages/contracts/generated/api/console/snippets/zod.gen.ts index ee89768d544..5675006946e 100644 --- a/packages/contracts/generated/api/console/snippets/zod.gen.ts +++ b/packages/contracts/generated/api/console/snippets/zod.gen.ts @@ -1546,6 +1546,7 @@ export const zAgentSoulAppFeaturesConfig = z.object({ opening_statement: z.string().nullish(), retriever_resource: zAgentFeatureToggleConfig.nullish(), sensitive_word_avoidance: zAgentSensitiveWordAvoidanceFeatureConfig.nullish(), + show_thoughts: zAgentFeatureToggleConfig.nullish(), speech_to_text: zAgentFeatureToggleConfig.nullish(), suggested_questions: z.array(z.string()).nullish(), suggested_questions_after_answer: zAgentSuggestedQuestionsAfterAnswerFeatureConfig.nullish(), diff --git a/packages/contracts/generated/api/console/trial-apps/types.gen.ts b/packages/contracts/generated/api/console/trial-apps/types.gen.ts index b6817abbafa..01b49259701 100644 --- a/packages/contracts/generated/api/console/trial-apps/types.gen.ts +++ b/packages/contracts/generated/api/console/trial-apps/types.gen.ts @@ -339,6 +339,9 @@ export type Parameters = { sensitive_word_avoidance: { enabled?: boolean } + show_thoughts?: { + enabled?: boolean + } speech_to_text: { enabled?: boolean } @@ -1007,6 +1010,7 @@ export type AgentSoulAppFeaturesConfig = { opening_statement?: string | null retriever_resource?: AgentFeatureToggleConfig | null sensitive_word_avoidance?: AgentSensitiveWordAvoidanceFeatureConfig | null + show_thoughts?: AgentFeatureToggleConfig | null speech_to_text?: AgentFeatureToggleConfig | null suggested_questions?: Array | null suggested_questions_after_answer?: AgentSuggestedQuestionsAfterAnswerFeatureConfig | null diff --git a/packages/contracts/generated/api/console/trial-apps/zod.gen.ts b/packages/contracts/generated/api/console/trial-apps/zod.gen.ts index a2b31f92370..1e72b9caf64 100644 --- a/packages/contracts/generated/api/console/trial-apps/zod.gen.ts +++ b/packages/contracts/generated/api/console/trial-apps/zod.gen.ts @@ -896,6 +896,11 @@ export const zParameters = z.object({ sensitive_word_avoidance: z.object({ enabled: z.boolean().optional(), }), + show_thoughts: z + .object({ + enabled: z.boolean().optional(), + }) + .optional(), speech_to_text: z.object({ enabled: z.boolean().optional(), }), @@ -1936,6 +1941,7 @@ export const zAgentSoulAppFeaturesConfig = z.object({ opening_statement: z.string().nullish(), retriever_resource: zAgentFeatureToggleConfig.nullish(), sensitive_word_avoidance: zAgentSensitiveWordAvoidanceFeatureConfig.nullish(), + show_thoughts: zAgentFeatureToggleConfig.nullish(), speech_to_text: zAgentFeatureToggleConfig.nullish(), suggested_questions: z.array(z.string()).nullish(), suggested_questions_after_answer: zAgentSuggestedQuestionsAfterAnswerFeatureConfig.nullish(), diff --git a/packages/contracts/generated/api/service/types.gen.ts b/packages/contracts/generated/api/service/types.gen.ts index 9ef2398212e..8ee9c8af723 100644 --- a/packages/contracts/generated/api/service/types.gen.ts +++ b/packages/contracts/generated/api/service/types.gen.ts @@ -3484,6 +3484,9 @@ export type Parameters = { sensitive_word_avoidance: { enabled?: boolean } + show_thoughts?: { + enabled?: boolean + } speech_to_text: { enabled?: boolean } diff --git a/packages/contracts/generated/api/service/zod.gen.ts b/packages/contracts/generated/api/service/zod.gen.ts index 56c183b5cae..ead033638a9 100644 --- a/packages/contracts/generated/api/service/zod.gen.ts +++ b/packages/contracts/generated/api/service/zod.gen.ts @@ -4966,6 +4966,11 @@ export const zParameters = z.object({ sensitive_word_avoidance: z.object({ enabled: z.boolean().optional(), }), + show_thoughts: z + .object({ + enabled: z.boolean().optional(), + }) + .optional(), speech_to_text: z.object({ enabled: z.boolean().optional(), }), diff --git a/packages/contracts/generated/api/web/types.gen.ts b/packages/contracts/generated/api/web/types.gen.ts index 955137a496d..fde08efc68b 100644 --- a/packages/contracts/generated/api/web/types.gen.ts +++ b/packages/contracts/generated/api/web/types.gen.ts @@ -705,6 +705,9 @@ export type Parameters = { sensitive_word_avoidance: { enabled?: boolean } + show_thoughts?: { + enabled?: boolean + } speech_to_text: { enabled?: boolean } diff --git a/packages/contracts/generated/api/web/zod.gen.ts b/packages/contracts/generated/api/web/zod.gen.ts index 295a2e72e7b..315710c0355 100644 --- a/packages/contracts/generated/api/web/zod.gen.ts +++ b/packages/contracts/generated/api/web/zod.gen.ts @@ -1458,6 +1458,11 @@ export const zParameters = z.object({ sensitive_word_avoidance: z.object({ enabled: z.boolean().optional(), }), + show_thoughts: z + .object({ + enabled: z.boolean().optional(), + }) + .optional(), speech_to_text: z.object({ enabled: z.boolean().optional(), }), diff --git a/web/app/components/base/chat/chat/answer/__tests__/agent-roster-response-content.spec.tsx b/web/app/components/base/chat/chat/answer/__tests__/agent-roster-response-content.spec.tsx index 7ea2382f9ff..1e2e3f5a801 100644 --- a/web/app/components/base/chat/chat/answer/__tests__/agent-roster-response-content.spec.tsx +++ b/web/app/components/base/chat/chat/answer/__tests__/agent-roster-response-content.spec.tsx @@ -42,6 +42,53 @@ const thinkingOnlyItem = { } satisfies ChatItem describe('AgentRosterResponseContent', () => { + it('shows trimmed plain-text thoughts in collapsed history activity only when enabled', async () => { + const user = userEvent.setup() + const thought = { + ...thinkingOnlyItem.agent_response_parts[0]!.thought, + thought: ' \nFirst\n**Second** &\n ', + } + const item: ChatItem = { + ...thinkingOnlyItem, + agent_response_parts: undefined, + agent_thoughts: [thought], + } + const { rerender } = render() + expect(screen.queryByRole('button', { name: 'Thinking' })).not.toBeInTheDocument() + + rerender() + const toggle = screen.getByRole('button', { name: 'Thinking' }) + expect(toggle).toHaveAttribute('aria-expanded', 'false') + await user.click(toggle) + const text = screen.getByText('First **Second** &') + expect(text.textContent).toBe('First\n**Second** &') + expect(text.children).toHaveLength(0) + }) + + it('collapses enabled live thoughts once they become history', async () => { + const user = userEvent.setup() + const { rerender } = render( + , + ) + expect(screen.getByText('internal thought should not render')).toBeVisible() + rerender( + , + ) + expect(screen.getByRole('button', { name: 'Thinking' })).toHaveAttribute( + 'aria-expanded', + 'false', + ) + await user.click(screen.getByRole('button', { name: 'Thinking' })) + expect(await screen.findByText('internal thought should not render')).toBeVisible() + }) + it('renders a verified receipt as a working in-answer link, but not a forged receipt', async () => { const user = userEvent.setup() const receiptId = `kfs_${'a'.repeat(32)}` diff --git a/web/app/components/base/chat/chat/answer/__tests__/index.spec.tsx b/web/app/components/base/chat/chat/answer/__tests__/index.spec.tsx index d543f3924ae..91cc4ac485a 100644 --- a/web/app/components/base/chat/chat/answer/__tests__/index.spec.tsx +++ b/web/app/components/base/chat/chat/answer/__tests__/index.spec.tsx @@ -80,6 +80,27 @@ describe('Answer Component', () => { expect(screen.getByText('streamed answer')).toHaveTextContent('streamed answer') }) + it.each([true, false])( + 'should pass the configured show thoughts setting (%s) to custom agent content', + (enabled) => { + render( + ['config']} + renderAgentContent={({ showThoughts }) =>

{`thoughts ${showThoughts}`}

} + />, + ) + + expect(screen.getByText(`thoughts ${enabled}`)).toBeInTheDocument() + }, + ) + it('should render annotation edit title', async () => { render( >> 0).toString(36) } -function hasVisibleActivity(thought: ThoughtItem) { - return !!thought.tool || !!thought.message_files?.length +function hasVisibleActivity(thought: ThoughtItem, showThoughts: boolean) { + return ( + (showThoughts && !!thought.thought?.trim()) || !!thought.tool || !!thought.message_files?.length + ) } -function getAgentActivityEntries(item: ChatItem): AgentActivityEntry[] { +function getAgentActivityEntries(item: ChatItem, showThoughts: boolean): AgentActivityEntry[] { if (item.agent_response_parts?.length) { const keyOccurrences = new Map() @@ -128,7 +131,7 @@ function getAgentActivityEntries(item: ChatItem): AgentActivityEntry[] { if (part.type === 'message') return part.content ? [{ type: 'message', content: part.content, key }] : [] - return hasVisibleActivity(part.thought) + return hasVisibleActivity(part.thought, showThoughts) ? [{ type: 'thought', thought: part.thought, key }] : [] }) @@ -142,7 +145,7 @@ function getAgentActivityEntries(item: ChatItem): AgentActivityEntry[] { const answer = thought.answer if (answer?.trim()) parts.push({ type: 'message', content: answer, key: `message-${key}` }) - if (hasVisibleActivity(thought)) + if (hasVisibleActivity(thought, showThoughts)) parts.push({ type: 'thought', thought, key: `thought-${key}` }) return parts @@ -218,7 +221,7 @@ function ToolActivityItem({ tool }: { tool: ToolActivity }) {
{hasDetails ? ( - + {content} @@ -258,15 +261,22 @@ function ToolActivityItem({ tool }: { tool: ToolActivity }) { function AgentActivityItem({ thought, responding, + showThoughts, }: { thought: ThoughtItem responding?: boolean + showThoughts: boolean }) { const locale = useLocale() const tools = getToolActivities(thought, locale, responding) return (
+ {showThoughts && !!thought.thought?.trim() && ( +
+ {thought.thought.trim()} +
+ )} {tools.map((tool) => ( ))} @@ -288,11 +298,13 @@ function AgentActivityDisclosure({ entries, responding, defaultOpen, + showThoughts, }: { item: ChatItem entries: AgentActivityEntry[] responding?: boolean defaultOpen?: boolean + showThoughts: boolean }) { const { t } = useTranslation(['agentV2']) const workingDuration = useWorkingDuration(responding) @@ -309,7 +321,7 @@ function AgentActivityDisclosure({ {thinking} {duration && ( @@ -332,7 +344,12 @@ function AgentActivityDisclosure({ content={resolveKnowledgeCitationLinks(entry.content, item.citation)} /> ) : ( - + ), )}
@@ -345,6 +362,7 @@ export function AgentRosterResponseContent({ item, responding, content, + showThoughts = false, }: AgentRosterResponseContentProps) { if (item.annotation?.logAnnotation) { return ( @@ -355,7 +373,7 @@ export function AgentRosterResponseContent({ ) } - const entries = getAgentActivityEntries(item) + const entries = getAgentActivityEntries(item, showThoughts) const hasLiveResponseParts = !!item.agent_response_parts?.length const hasThinkingStatus = entries.length === 0 && !!item.agent_response_parts?.some((part) => part.type === 'thought') @@ -381,6 +399,7 @@ export function AgentRosterResponseContent({ item={item} entries={entries} responding={responding} + showThoughts={showThoughts} defaultOpen={hasLiveResponseParts && (!!responding || entries.length > 0)} /> )} diff --git a/web/app/components/base/chat/chat/answer/index.tsx b/web/app/components/base/chat/chat/answer/index.tsx index 04c6f2f79a2..0a08120191c 100644 --- a/web/app/components/base/chat/chat/answer/index.tsx +++ b/web/app/components/base/chat/chat/answer/index.tsx @@ -42,6 +42,7 @@ type AnswerProps = { item: ChatItem responding?: boolean content?: string + showThoughts?: boolean }) => ReactNode onHumanInputFormSubmit?: (formToken: string, formData: HumanInputFormSubmitData) => Promise } @@ -143,7 +144,12 @@ const Answer: FC = ({ const contentIsEmpty = typeof content === 'string' && content.trim() === '' const agentContentNode = renderAgentContent ? ( - renderAgentContent({ item, responding, content }) + renderAgentContent({ + item, + responding, + content, + showThoughts: !!config?.show_thoughts?.enabled, + }) ) : ( ) @@ -163,21 +169,21 @@ const Answer: FC = ({
{answerIcon || } {responding && ( -
+
)}
)}
{/* Block 1: Workflow Process + Human Input Forms */} {hasHumanInputs && (
= ({ {/* Block 2: Response Content (when human inputs exist) */} {hasHumanInputs && (responding || !contentIsEmpty || hasAgentContent || hasReasoning) && ( -
-
+
+
= ({ {/* Original single block layout (when no human inputs) */} {!hasHumanInputs && (
ReactNode onHumanInputFormSubmit?: (formToken: string, formData: HumanInputFormSubmitData) => Promise getHumanInputNodeData?: (nodeID: string) => Node | undefined diff --git a/web/app/components/base/features/new-feature-panel/__tests__/index.spec.tsx b/web/app/components/base/features/new-feature-panel/__tests__/index.spec.tsx index b681b5913c2..70a72f95f19 100644 --- a/web/app/components/base/features/new-feature-panel/__tests__/index.spec.tsx +++ b/web/app/components/base/features/new-feature-panel/__tests__/index.spec.tsx @@ -124,6 +124,13 @@ describe('NewFeaturePanel', () => { } }) + it('does not offer thinking display in the shared application feature panel', () => { + renderPanel({ isChatMode: true, inWorkflow: false }) + expect( + screen.queryByRole('switch', { name: 'appDebug.feature.showThoughts.title' }), + ).not.toBeInTheDocument() + }) + describe('Chat Mode Features', () => { it('should render speech-to-text in chat mode when model is available', () => { renderPanel({ isChatMode: true }) diff --git a/web/app/components/base/features/new-feature-panel/index.tsx b/web/app/components/base/features/new-feature-panel/index.tsx index 6dcc8bad1ee..16d493f8f13 100644 --- a/web/app/components/base/features/new-feature-panel/index.tsx +++ b/web/app/components/base/features/new-feature-panel/index.tsx @@ -15,6 +15,7 @@ import { FollowUp } from '@/app/components/base/features/new-feature-panel/follo import ImageUpload from '@/app/components/base/features/new-feature-panel/image-upload' import Moderation from '@/app/components/base/features/new-feature-panel/moderation' import MoreLikeThis from '@/app/components/base/features/new-feature-panel/more-like-this' +import ShowThoughts from '@/app/components/base/features/new-feature-panel/show-thoughts' import SpeechToText from '@/app/components/base/features/new-feature-panel/speech-to-text' import TextToSpeech from '@/app/components/base/features/new-feature-panel/text-to-speech' import { @@ -33,6 +34,7 @@ type Props = Readonly<{ onClose: () => void inWorkflow?: boolean showFileUpload?: boolean + showThoughtsToggle?: boolean showModeration?: boolean showAnnotationReply?: boolean promptVariables?: PromptVariable[] @@ -51,6 +53,7 @@ const NewFeaturePanel = ({ onClose, inWorkflow = true, showFileUpload = true, + showThoughtsToggle = false, showModeration = true, showAnnotationReply = true, promptVariables, @@ -114,6 +117,9 @@ const NewFeaturePanel = ({ {showFileUpload && isChatMode && } {showFileUpload && !isChatMode && } {isChatMode && } + {isChatMode && showThoughtsToggle && ( + + )} {showModeration && (isChatMode || !inWorkflow) && ( )} diff --git a/web/app/components/base/features/new-feature-panel/show-thoughts.tsx b/web/app/components/base/features/new-feature-panel/show-thoughts.tsx new file mode 100644 index 00000000000..272d7b0b552 --- /dev/null +++ b/web/app/components/base/features/new-feature-panel/show-thoughts.tsx @@ -0,0 +1,55 @@ +import type { OnFeaturesChange } from '@/app/components/base/features/types' +import { produce } from 'immer' +import * as React from 'react' +import { useCallback } from 'react' +import { useTranslation } from 'react-i18next' +import { useFeatures, useFeaturesStore } from '@/app/components/base/features/hooks' +import FeatureCard from '@/app/components/base/features/new-feature-panel/feature-card' +import { FeatureEnum } from '@/app/components/base/features/types' + +type Props = Readonly<{ + disabled?: boolean + onChange?: OnFeaturesChange +}> + +const ShowThoughts = ({ disabled, onChange }: Props) => { + const { t } = useTranslation(['appDebug']) + const features = useFeatures((s) => s.features) + const featuresStore = useFeaturesStore() + + const handleChange = useCallback( + (type: FeatureEnum, enabled: boolean) => { + const { features, setFeatures } = featuresStore!.getState() + + const newFeatures = produce(features, (draft) => { + draft[type] = { + ...draft[type], + enabled, + } + }) + setFeatures(newFeatures) + if (onChange) onChange(newFeatures) + }, + [featuresStore, onChange], + ) + + return ( + + +
+ } + title={t(($) => $['feature.showThoughts.title'], { ns: 'appDebug' })} + value={!!features.showThoughts?.enabled} + description={t(($) => $['feature.showThoughts.description'], { ns: 'appDebug' })!} + onChange={(state) => handleChange(FeatureEnum.showThoughts, state)} + disabled={disabled} + /> + ) +} + +export default ShowThoughts diff --git a/web/app/components/base/features/store.ts b/web/app/components/base/features/store.ts index eba825bebb4..29468d78295 100644 --- a/web/app/components/base/features/store.ts +++ b/web/app/components/base/features/store.ts @@ -40,6 +40,9 @@ export const createFeaturesStore = (initProps?: Partial) => { citation: { enabled: false, }, + showThoughts: { + enabled: false, + }, moderation: { enabled: false, }, diff --git a/web/app/components/base/features/types.ts b/web/app/components/base/features/types.ts index d6747d60988..0547e912ad3 100644 --- a/web/app/components/base/features/types.ts +++ b/web/app/components/base/features/types.ts @@ -84,6 +84,7 @@ export const FeatureEnum = { text2speech: 'text2speech', speech2text: 'speech2text', citation: 'citation', + showThoughts: 'showThoughts', moderation: 'moderation', file: 'file', annotationReply: 'annotationReply', @@ -98,6 +99,7 @@ export type Features = { [FeatureEnum.text2speech]?: TextToSpeech [FeatureEnum.speech2text]?: EnabledOrDisabled [FeatureEnum.citation]?: EnabledOrDisabled + [FeatureEnum.showThoughts]?: EnabledOrDisabled [FeatureEnum.moderation]?: SensitiveWordAvoidance [FeatureEnum.file]?: FileUpload [FeatureEnum.annotationReply]?: AnnotationReplyConfig diff --git a/web/features/agent-v2/agent-detail/configure/components/preview/__tests__/chat-features-panel.spec.tsx b/web/features/agent-v2/agent-detail/configure/components/preview/__tests__/chat-features-panel.spec.tsx index 5887f8d15ac..670dba5bb70 100644 --- a/web/features/agent-v2/agent-detail/configure/components/preview/__tests__/chat-features-panel.spec.tsx +++ b/web/features/agent-v2/agent-detail/configure/components/preview/__tests__/chat-features-panel.spec.tsx @@ -58,6 +58,36 @@ function renderPanel(snapshot: AgentSoulAppFeaturesConfig, draft = snapshot, dis } describe('AgentChatFeaturesPanel', () => { + it('defaults thinking display off and saves toggles without changing citations', async () => { + const user = userEvent.setup() + const { store } = renderPanel({ retriever_resource: { enabled: true } }) + const toggle = screen.getByRole('switch', { name: 'appDebug.feature.showThoughts.title' }) + + expect(toggle).not.toBeChecked() + await user.click(toggle) + expect(toggle).toBeChecked() + expect(store.get(agentComposerAppFeaturesAtom)?.show_thoughts).toEqual({ enabled: true }) + expect(store.get(agentComposerAppFeaturesAtom)?.retriever_resource).toEqual({ enabled: true }) + await user.click(toggle) + expect(toggle).not.toBeChecked() + expect(store.get(agentComposerAppFeaturesAtom)?.show_thoughts).toEqual({ enabled: false }) + }) + + it('shows the published thinking setting read-only without changing the draft', async () => { + const user = userEvent.setup() + const { store } = renderPanel( + { show_thoughts: { enabled: true } }, + { show_thoughts: { enabled: false } }, + true, + ) + const toggle = screen.getByRole('switch', { name: 'appDebug.feature.showThoughts.title' }) + + expect(toggle).toBeChecked() + expect(toggle).toHaveAttribute('aria-disabled', 'true') + await user.click(toggle) + expect(store.get(agentComposerAppFeaturesAtom)?.show_thoughts).toEqual({ enabled: false }) + }) + it('keeps a newly saved opener enabled before the server snapshot catches up', async () => { const user = userEvent.setup({ skipHover: true }) const { updateSnapshot, store } = renderPanel({ opening_statement: '' }) diff --git a/web/features/agent-v2/agent-detail/configure/components/preview/__tests__/chat.spec.tsx b/web/features/agent-v2/agent-detail/configure/components/preview/__tests__/chat.spec.tsx index 86363b2f53d..514d9dec0f1 100644 --- a/web/features/agent-v2/agent-detail/configure/components/preview/__tests__/chat.spec.tsx +++ b/web/features/agent-v2/agent-detail/configure/components/preview/__tests__/chat.spec.tsx @@ -271,6 +271,41 @@ describe('Agent conversation history', () => { }, ) + it.each([false, true])( + 'uses the configured show thoughts setting (%s) in preview', + async (enabled) => { + messages.set('conversation-1', [ + createMessage({ + agent_thoughts: [ + { + id: 'thought-setting', + tool_labels: {}, + files: [], + message_id: 'message-0', + thought: 'Model reasoning from history', + answer: 'Public progress', + tool: '', + tool_input: '', + observation: '', + position: 1, + }, + ], + }), + ]) + renderChat({ + conversationId: 'conversation-1', + agentSoulConfig: { schema_version: 1, app_features: { show_thoughts: { enabled } } }, + }) + const toggle = await screen.findByRole('button', { + name: new RegExp(`${prefix}.answer.thinking`), + }) + expect(toggle).toHaveAttribute('aria-expanded', 'false') + await userEvent.setup().click(toggle) + if (enabled) expect(await screen.findByText('Model reasoning from history')).toBeVisible() + else expect(screen.queryByText('Model reasoning from history')).not.toBeInTheDocument() + }, + ) + it('shows historical thought answers and localized tool activity', async () => { const user = userEvent.setup() messages.set('conversation-1', [ diff --git a/web/features/agent-v2/agent-detail/configure/components/preview/chat-config.ts b/web/features/agent-v2/agent-detail/configure/components/preview/chat-config.ts index 4b0390caddb..ef794ad06c0 100644 --- a/web/features/agent-v2/agent-detail/configure/components/preview/chat-config.ts +++ b/web/features/agent-v2/agent-detail/configure/components/preview/chat-config.ts @@ -222,6 +222,7 @@ export const buildChatConfig = ({ more_like_this: { enabled: false }, text_to_speech: toEnabledConfig(appFeatures.text_to_speech) as ChatConfig['text_to_speech'], speech_to_text: toEnabledConfig(appFeatures.speech_to_text), + show_thoughts: toEnabledConfig(appFeatures.show_thoughts), retriever_resource: toEnabledConfig(appFeatures.retriever_resource), sensitive_word_avoidance: toEnabledConfig(appFeatures.sensitive_word_avoidance), annotation_reply: { diff --git a/web/features/agent-v2/agent-detail/configure/components/preview/chat-features-panel.tsx b/web/features/agent-v2/agent-detail/configure/components/preview/chat-features-panel.tsx index 86aba2d23e4..d33f9355832 100644 --- a/web/features/agent-v2/agent-detail/configure/components/preview/chat-features-panel.tsx +++ b/web/features/agent-v2/agent-detail/configure/components/preview/chat-features-panel.tsx @@ -31,6 +31,7 @@ const defaultFeatureState: Features = { text2speech: { enabled: false }, speech2text: { enabled: false }, citation: { enabled: false }, + showThoughts: { enabled: false }, moderation: { enabled: false }, file: { enabled: false, @@ -101,6 +102,7 @@ function toPanelFeatures(appFeatures?: AgentSoulAppFeaturesConfig): Features { defaultFeatureState.text2speech, speech2text: appFeatures?.speech_to_text ?? defaultFeatureState.speech2text, citation: appFeatures?.retriever_resource ?? defaultFeatureState.citation, + showThoughts: appFeatures?.show_thoughts ?? defaultFeatureState.showThoughts, moderation: (appFeatures?.sensitive_word_avoidance as Features['moderation'] | undefined) ?? defaultFeatureState.moderation, @@ -126,6 +128,7 @@ function toAppFeatures( text_to_speech: features.text2speech as AgentSoulAppFeaturesConfig['text_to_speech'], speech_to_text: features.speech2text, retriever_resource: features.citation, + show_thoughts: features.showThoughts, file_upload: toAgentFileUploadFeatureConfig(features.file), } } @@ -156,6 +159,7 @@ function AgentChatFeaturesPanelContent({ isChatMode disabled={!!disabled} inWorkflow={false} + showThoughtsToggle showModeration={false} showAnnotationReply={false} drawerClassName="bg-components-panel-bg! data-[swipe-direction=right]:top-1! data-[swipe-direction=right]:right-0! data-[swipe-direction=right]:bottom-1! data-[swipe-direction=right]:rounded-r-none!" diff --git a/web/i18n/locales/ar-TN/app-debug.json b/web/i18n/locales/ar-TN/app-debug.json index f4b5efb1114..ee0a5fa281c 100644 --- a/web/i18n/locales/ar-TN/app-debug.json +++ b/web/i18n/locales/ar-TN/app-debug.json @@ -95,6 +95,8 @@ "feature.moreLikeThis.description": "توليد نصوص متعددة في وقت واحد، ثم تحريرها ومتابعة التوليد", "feature.moreLikeThis.tip": "سيؤدي استخدام هذه الميزة إلى تكبد نفقات إضافية للرموز", "feature.moreLikeThis.title": "المزيد مثل هذا", + "feature.showThoughts.description": "اعرض محتوى تفكير النموذج في المحادثات.", + "feature.showThoughts.title": "إظهار عملية التفكير", "feature.speechToText.description": "يمكن استخدام الإدخال الصوتي في الدردشة.", "feature.speechToText.title": "تحويل الكلام إلى نص", "feature.suggestedQuestionsAfterAnswer.description": "يمكن أن يعطي إعداد اقتراح الأسئلة التالية للمستخدمين دردشة أفضل.", diff --git a/web/i18n/locales/az-AZ/app-debug.json b/web/i18n/locales/az-AZ/app-debug.json index cbb2c25c50c..4dec48cd35c 100644 --- a/web/i18n/locales/az-AZ/app-debug.json +++ b/web/i18n/locales/az-AZ/app-debug.json @@ -95,6 +95,8 @@ "feature.moreLikeThis.description": "Eyni anda bir neçə mətn yaradın, sonra redaktə edin və yaratmağa davam edin", "feature.moreLikeThis.tip": "Bu funksiyadan istifadə əlavə token sərfiyyatına səbəb olacaq", "feature.moreLikeThis.title": "Buna bənzər daha çox mətn", + "feature.showThoughts.description": "Söhbətlərdə modelin düşüncə məzmununu göstərin.", + "feature.showThoughts.title": "Düşüncə prosesini göstər", "feature.speechToText.description": "Söhbətdə səsli daxiletmədən istifadə etmək olar.", "feature.speechToText.title": "Səsin mətnə çevrilməsi", "feature.suggestedQuestionsAfterAnswer.description": "Növbəti sual təkliflərinin qurulması istifadəçilərin söhbət təcrübəsini yaxşılaşdıra bilər.", diff --git a/web/i18n/locales/de-DE/app-debug.json b/web/i18n/locales/de-DE/app-debug.json index 514c413bd56..279474982df 100644 --- a/web/i18n/locales/de-DE/app-debug.json +++ b/web/i18n/locales/de-DE/app-debug.json @@ -95,6 +95,8 @@ "feature.moreLikeThis.description": "Mehrere Texte gleichzeitig generieren und dann bearbeiten und weiter generieren", "feature.moreLikeThis.tip": "Die Verwendung dieser Funktion verursacht zusätzliche Token-Kosten", "feature.moreLikeThis.title": "Mehr davon", + "feature.showThoughts.description": "Zeigt den Gedankengang des Modells in Gesprächen an.", + "feature.showThoughts.title": "Gedankengang anzeigen", "feature.speechToText.description": "Einmal aktiviert, können Sie Spracheingabe verwenden.", "feature.speechToText.title": "Sprache zu Text", "feature.suggestedQuestionsAfterAnswer.description": "Das Einrichten von Vorschlägen für nächste Fragen kann den Chat für Benutzer verbessern.", diff --git a/web/i18n/locales/en-US/app-debug.json b/web/i18n/locales/en-US/app-debug.json index 7f96ea851dd..c9bb1e8ce0a 100644 --- a/web/i18n/locales/en-US/app-debug.json +++ b/web/i18n/locales/en-US/app-debug.json @@ -95,6 +95,8 @@ "feature.moreLikeThis.description": "Generate multiple texts at once, and then edit and continue to generate", "feature.moreLikeThis.tip": "Using this feature will incur additional tokens overhead", "feature.moreLikeThis.title": "More like this", + "feature.showThoughts.description": "Display the model’s thinking in conversations.", + "feature.showThoughts.title": "Show thinking", "feature.speechToText.description": "Voice input can be used in chat.", "feature.speechToText.title": "Speech to Text", "feature.suggestedQuestionsAfterAnswer.description": "Setting up next questions suggestion can give users a better chat.", diff --git a/web/i18n/locales/es-ES/app-debug.json b/web/i18n/locales/es-ES/app-debug.json index 4b88591415b..8feabfe1b4a 100644 --- a/web/i18n/locales/es-ES/app-debug.json +++ b/web/i18n/locales/es-ES/app-debug.json @@ -95,6 +95,8 @@ "feature.moreLikeThis.description": "Genera múltiples textos a la vez, luego edítalos y continúa generando", "feature.moreLikeThis.tip": "Usar esta función incurrirá en un costo adicional de tokens", "feature.moreLikeThis.title": "Más como esto", + "feature.showThoughts.description": "Muestra el razonamiento del modelo en las conversaciones.", + "feature.showThoughts.title": "Mostrar razonamiento", "feature.speechToText.description": "Una vez habilitado, puedes usar la entrada de voz.", "feature.speechToText.title": "Voz a Texto", "feature.suggestedQuestionsAfterAnswer.description": "Configurar sugerencias de próximas preguntas puede proporcionar una mejor conversación.", diff --git a/web/i18n/locales/fa-IR/app-debug.json b/web/i18n/locales/fa-IR/app-debug.json index 551a5a8c698..9ded769c4fa 100644 --- a/web/i18n/locales/fa-IR/app-debug.json +++ b/web/i18n/locales/fa-IR/app-debug.json @@ -95,6 +95,8 @@ "feature.moreLikeThis.description": "تولید چندین متن به طور همزمان، و سپس ویرایش و ادامه تولید", "feature.moreLikeThis.tip": "استفاده از این ویژگی هزینه‌های اضافی توکن‌ها را به همراه دارد", "feature.moreLikeThis.title": "بیشتر از این", + "feature.showThoughts.description": "محتوای تفکر مدل را در گفتگوها نمایش دهید.", + "feature.showThoughts.title": "نمایش روند تفکر", "feature.speechToText.description": "پس از فعال شدن، می‌توانید از ورودی صوتی استفاده کنید.", "feature.speechToText.title": "تبدیل گفتار به متن", "feature.suggestedQuestionsAfterAnswer.description": "تنظیم پیشنهاد سوالات بعدی می‌تواند به کاربران یک چت بهتر ارائه دهد.", diff --git a/web/i18n/locales/fr-FR/app-debug.json b/web/i18n/locales/fr-FR/app-debug.json index 0edcc46d657..31f34c47248 100644 --- a/web/i18n/locales/fr-FR/app-debug.json +++ b/web/i18n/locales/fr-FR/app-debug.json @@ -95,6 +95,8 @@ "feature.moreLikeThis.description": "Générez plusieurs textes à la fois, puis modifiez et continuez à générer", "feature.moreLikeThis.tip": "L'utilisation de cette fonctionnalité entraînera un surcoût de tokens supplémentaires", "feature.moreLikeThis.title": "Plus comme ça", + "feature.showThoughts.description": "Affichez le raisonnement du modèle dans les conversations.", + "feature.showThoughts.title": "Afficher le raisonnement", "feature.speechToText.description": "Une fois activé, vous pouvez utiliser l'entrée vocale.", "feature.speechToText.title": "Discours en Texte", "feature.suggestedQuestionsAfterAnswer.description": "La configuration de la suggestion des prochaines questions peut offrir aux utilisateurs une meilleure discussion.", diff --git a/web/i18n/locales/hi-IN/app-debug.json b/web/i18n/locales/hi-IN/app-debug.json index 44b04721835..98f66d49662 100644 --- a/web/i18n/locales/hi-IN/app-debug.json +++ b/web/i18n/locales/hi-IN/app-debug.json @@ -95,6 +95,8 @@ "feature.moreLikeThis.description": "एक बार में कई पाठ उत्पन्न करें, और फिर संपादित करें और जारी रखें", "feature.moreLikeThis.tip": "इस सुविधा का उपयोग करने से अतिरिक्त टोकन खर्च होगा", "feature.moreLikeThis.title": "ऐसा और", + "feature.showThoughts.description": "बातचीत में मॉडल की सोचने की प्रक्रिया दिखाएँ।", + "feature.showThoughts.title": "सोचने की प्रक्रिया दिखाएँ", "feature.speechToText.description": "सक्रिय होने पर, आप वॉयस इनपुट का उपयोग कर सकते हैं।", "feature.speechToText.title": "वाक् से पाठ", "feature.suggestedQuestionsAfterAnswer.description": "अगले प्रश्न सुझाव सेट करना उपयोगकर्ताओं को बेहतर चैट दे सकता है।", diff --git a/web/i18n/locales/id-ID/app-debug.json b/web/i18n/locales/id-ID/app-debug.json index 01bb54e082a..1bd797b621b 100644 --- a/web/i18n/locales/id-ID/app-debug.json +++ b/web/i18n/locales/id-ID/app-debug.json @@ -95,6 +95,8 @@ "feature.moreLikeThis.description": "Buat beberapa teks sekaligus, lalu edit dan lanjutkan membuat", "feature.moreLikeThis.tip": "Menggunakan fitur ini akan dikenakan overhead token tambahan", "feature.moreLikeThis.title": "Lebih seperti ini", + "feature.showThoughts.description": "Tampilkan isi pemikiran model dalam percakapan.", + "feature.showThoughts.title": "Tampilkan proses berpikir", "feature.speechToText.description": "Input suara dapat digunakan dalam obrolan.", "feature.speechToText.title": "Ucapan ke Teks", "feature.suggestedQuestionsAfterAnswer.description": "Menyiapkan saran pertanyaan berikutnya dapat memberi pengguna obrolan yang lebih baik.", diff --git a/web/i18n/locales/it-IT/app-debug.json b/web/i18n/locales/it-IT/app-debug.json index 5763f7a7dab..cdb39954853 100644 --- a/web/i18n/locales/it-IT/app-debug.json +++ b/web/i18n/locales/it-IT/app-debug.json @@ -95,6 +95,8 @@ "feature.moreLikeThis.description": "Genera più testi contemporaneamente, poi modifica e continua a generare", "feature.moreLikeThis.tip": "L'utilizzo di questa funzione comporterà un costo aggiuntivo di token", "feature.moreLikeThis.title": "Altri simili", + "feature.showThoughts.description": "Mostra il ragionamento del modello nelle conversazioni.", + "feature.showThoughts.title": "Mostra ragionamento", "feature.speechToText.description": "Una volta abilitato, puoi usare l'input vocale.", "feature.speechToText.title": "Da voce a testo", "feature.suggestedQuestionsAfterAnswer.description": "Impostare suggerimenti per le prossime domande può offrire agli utenti una chat migliore.", diff --git a/web/i18n/locales/ja-JP/app-debug.json b/web/i18n/locales/ja-JP/app-debug.json index df378ec0b4f..ee2cc19ec3f 100644 --- a/web/i18n/locales/ja-JP/app-debug.json +++ b/web/i18n/locales/ja-JP/app-debug.json @@ -95,6 +95,8 @@ "feature.moreLikeThis.description": "一度に複数のテキストを生成し、編集して生成を続ける", "feature.moreLikeThis.tip": "この機能を使用すると、追加のトークンオーバーヘッドが発生します", "feature.moreLikeThis.title": "これに似たもの", + "feature.showThoughts.description": "会話中にモデルの思考内容を表示します。", + "feature.showThoughts.title": "思考過程を表示", "feature.speechToText.description": "有効にすると、音声入力を使用できます。", "feature.speechToText.title": "音声からテキストへ", "feature.suggestedQuestionsAfterAnswer.description": "次の質問の提案を設定すると、ユーザーにより良いチャットが提供されます。", diff --git a/web/i18n/locales/ko-KR/app-debug.json b/web/i18n/locales/ko-KR/app-debug.json index 2e36f888fce..1ca3032cac1 100644 --- a/web/i18n/locales/ko-KR/app-debug.json +++ b/web/i18n/locales/ko-KR/app-debug.json @@ -95,6 +95,8 @@ "feature.moreLikeThis.description": "여러 텍스트를 한 번에 생성하고 편집하여 계속해서 생성합니다.", "feature.moreLikeThis.tip": "이 기능을 사용하면 추가적인 토큰 오버헤드가 발생합니다", "feature.moreLikeThis.title": "유사한 항목", + "feature.showThoughts.description": "대화에서 모델의 사고 내용을 표시합니다.", + "feature.showThoughts.title": "사고 과정 표시", "feature.speechToText.description": "활성화하면 음성 입력을 사용할 수 있습니다.", "feature.speechToText.title": "음성에서 텍스트로", "feature.suggestedQuestionsAfterAnswer.description": "다음 질문 제안을 설정하면 사용자에게 더 나은 채팅이 제공됩니다.", diff --git a/web/i18n/locales/lo-LA/app-debug.json b/web/i18n/locales/lo-LA/app-debug.json index 7fd1625aa36..59cafb0748f 100644 --- a/web/i18n/locales/lo-LA/app-debug.json +++ b/web/i18n/locales/lo-LA/app-debug.json @@ -95,6 +95,8 @@ "feature.moreLikeThis.description": "ສ້າງຫຼາຍຂໍ້ຄວາມພ້ອມກັນ, ຈາກນັ້ນແກ້ໄຂ ແລະ ສ້າງຕໍ່", "feature.moreLikeThis.tip": "ການໃຊ້ຄຸນສົມບັດນີ້ຈະມີຄ່າໃຊ້ຈ່າຍ tokens ເພີ່ມເຕີມ", "feature.moreLikeThis.title": "ຂໍ້ຄວາມທີ່ຄ້າຍຄືກັນນີ້", + "feature.showThoughts.description": "ສະແດງເນື້ອຫາການຄິດຂອງໂມເດລໃນການສົນທະນາ.", + "feature.showThoughts.title": "ສະແດງຂະບວນການຄິດ", "feature.speechToText.description": "ສາມາດໃຊ້ການປ້ອນຂໍ້ມູນດ້ວຍສຽງໃນການສົນທະນາໄດ້.", "feature.speechToText.title": "ປ່ຽນສຽງເປັນຂໍ້ຄວາມ", "feature.suggestedQuestionsAfterAnswer.description": "ການຕັ້ງຄ່າຄຳຖາມແນະນຳຖັດໄປຈະຊ່ວຍໃຫ້ຜູ້ໃຊ້ມີການສົນທະນາທີ່ດີຂຶ້ນ.", diff --git a/web/i18n/locales/nl-NL/app-debug.json b/web/i18n/locales/nl-NL/app-debug.json index bb60ac0cc21..b69d966696b 100644 --- a/web/i18n/locales/nl-NL/app-debug.json +++ b/web/i18n/locales/nl-NL/app-debug.json @@ -95,6 +95,8 @@ "feature.moreLikeThis.description": "Generate multiple texts at once, and then edit and continue to generate", "feature.moreLikeThis.tip": "Using this feature will incur additional tokens overhead", "feature.moreLikeThis.title": "More like this", + "feature.showThoughts.description": "Toon het denkproces van het model in gesprekken.", + "feature.showThoughts.title": "Denkproces tonen", "feature.speechToText.description": "Voice input can be used in chat.", "feature.speechToText.title": "Speech to Text", "feature.suggestedQuestionsAfterAnswer.description": "Setting up next questions suggestion can give users a better chat.", diff --git a/web/i18n/locales/pl-PL/app-debug.json b/web/i18n/locales/pl-PL/app-debug.json index 488f3785912..5209f994da5 100644 --- a/web/i18n/locales/pl-PL/app-debug.json +++ b/web/i18n/locales/pl-PL/app-debug.json @@ -95,6 +95,8 @@ "feature.moreLikeThis.description": "Generuj wiele tekstów na raz, a następnie edytuj i kontynuuj generowanie", "feature.moreLikeThis.tip": "Korzystanie z tej funkcji spowoduje dodatkowe zużycie tokenów", "feature.moreLikeThis.title": "Więcej takich jak ten", + "feature.showThoughts.description": "Wyświetlaj tok rozumowania modelu w rozmowach.", + "feature.showThoughts.title": "Pokaż tok rozumowania", "feature.speechToText.description": "Po włączeniu można używać wprowadzania głosowego.", "feature.speechToText.title": "Mowa na tekst", "feature.suggestedQuestionsAfterAnswer.description": "Ustawienie kolejnych pytań może poprawić czat.", diff --git a/web/i18n/locales/pt-BR/app-debug.json b/web/i18n/locales/pt-BR/app-debug.json index 535816ac53c..3aad12a09fe 100644 --- a/web/i18n/locales/pt-BR/app-debug.json +++ b/web/i18n/locales/pt-BR/app-debug.json @@ -95,6 +95,8 @@ "feature.moreLikeThis.description": "Gere vários textos de uma vez e, em seguida, edite e continue a gerar", "feature.moreLikeThis.tip": "Usar esse recurso incorrerá em sobrecarga adicional de tokens", "feature.moreLikeThis.title": "Mais como isso", + "feature.showThoughts.description": "Exiba o raciocínio do modelo nas conversas.", + "feature.showThoughts.title": "Mostrar raciocínio", "feature.speechToText.description": "Uma vez ativado, você pode usar entrada de voz.", "feature.speechToText.title": "Fala para Texto", "feature.suggestedQuestionsAfterAnswer.description": "Configurar sugestões de próximas perguntas pode proporcionar um melhor chat aos usuários.", diff --git a/web/i18n/locales/ro-RO/app-debug.json b/web/i18n/locales/ro-RO/app-debug.json index 312cf1c5b90..0acbe38f2bc 100644 --- a/web/i18n/locales/ro-RO/app-debug.json +++ b/web/i18n/locales/ro-RO/app-debug.json @@ -95,6 +95,8 @@ "feature.moreLikeThis.description": "Generați mai multe texte o dată, apoi editați și continuați să generați", "feature.moreLikeThis.tip": "Utilizarea acestei funcții va genera un consum suplimentar de jetoane", "feature.moreLikeThis.title": "Mai multe ca aceasta", + "feature.showThoughts.description": "Afișează raționamentul modelului în conversații.", + "feature.showThoughts.title": "Afișează raționamentul", "feature.speechToText.description": "După activare, puteți utiliza intrarea vocală.", "feature.speechToText.title": "Voce la text", "feature.suggestedQuestionsAfterAnswer.description": "Setarea sugestiilor pentru întrebările următoare poate oferi utilizatorilor o conversație mai bună.", diff --git a/web/i18n/locales/ru-RU/app-debug.json b/web/i18n/locales/ru-RU/app-debug.json index f536b8ec84e..c9077c52ee1 100644 --- a/web/i18n/locales/ru-RU/app-debug.json +++ b/web/i18n/locales/ru-RU/app-debug.json @@ -95,6 +95,8 @@ "feature.moreLikeThis.description": "Сгенерируйте несколько текстов одновременно, а затем отредактируйте и продолжайте генерировать", "feature.moreLikeThis.tip": "Использование этой функции приведет к дополнительным расходам токенов", "feature.moreLikeThis.title": "Больше похожего", + "feature.showThoughts.description": "Показывать рассуждения модели в диалогах.", + "feature.showThoughts.title": "Показывать рассуждения", "feature.speechToText.description": "После включения вы можете использовать голосовой ввод.", "feature.speechToText.title": "Преобразование речи в текст", "feature.suggestedQuestionsAfterAnswer.description": "Настройка предложения следующих вопросов может улучшить чат для пользователей.", diff --git a/web/i18n/locales/sl-SI/app-debug.json b/web/i18n/locales/sl-SI/app-debug.json index 7ed7ce9278e..9237ebcb843 100644 --- a/web/i18n/locales/sl-SI/app-debug.json +++ b/web/i18n/locales/sl-SI/app-debug.json @@ -95,6 +95,8 @@ "feature.moreLikeThis.description": "Ustvari več besedil naenkrat, nato pa jih urejaj in nadaljuj z ustvarjanjem.", "feature.moreLikeThis.tip": "Uporaba te funkcije povzroča dodatno porabo žetonov.", "feature.moreLikeThis.title": "Več takšnih", + "feature.showThoughts.description": "Prikaži razmišljanje modela v pogovorih.", + "feature.showThoughts.title": "Prikaži razmišljanje", "feature.speechToText.description": "Ko je omogočeno, lahko uporabljaš glasovni vnos.", "feature.speechToText.title": "Govor v besedilo", "feature.suggestedQuestionsAfterAnswer.description": "Nastavitev predlogov za naslednja vprašanja lahko uporabnikom izboljša klepet.", diff --git a/web/i18n/locales/th-TH/app-debug.json b/web/i18n/locales/th-TH/app-debug.json index 93e8f241ccc..63f0c4ba887 100644 --- a/web/i18n/locales/th-TH/app-debug.json +++ b/web/i18n/locales/th-TH/app-debug.json @@ -95,6 +95,8 @@ "feature.moreLikeThis.description": "สร้างข้อความหลายข้อความพร้อมกัน จากนั้นแก้ไขและสร้างต่อไป", "feature.moreLikeThis.tip": "การใช้คุณสมบัตินี้จะมีค่าใช้จ่ายโทเค็นเพิ่มเติม", "feature.moreLikeThis.title": "เพิ่มเติมเช่นนี้", + "feature.showThoughts.description": "แสดงเนื้อหาการคิดของโมเดลในการสนทนา", + "feature.showThoughts.title": "แสดงกระบวนการคิด", "feature.speechToText.description": "สามารถใช้การป้อนข้อมูลด้วยเสียงในการแชทได้", "feature.speechToText.title": "คําพูดเป็นข้อความ", "feature.suggestedQuestionsAfterAnswer.description": "การตั้งค่าคําแนะนําคําถามถัดไปจะช่วยให้ผู้ใช้แชทได้ดีขึ้น", diff --git a/web/i18n/locales/tr-TR/app-debug.json b/web/i18n/locales/tr-TR/app-debug.json index 75ef8d576f9..6875744b0ef 100644 --- a/web/i18n/locales/tr-TR/app-debug.json +++ b/web/i18n/locales/tr-TR/app-debug.json @@ -95,6 +95,8 @@ "feature.moreLikeThis.description": "Birden fazla metni bir kerede üretin, ardından düzenleyin ve üretmeye devam edin", "feature.moreLikeThis.tip": "Bu özelliği kullanmak ek token maliyetine yol açacaktır", "feature.moreLikeThis.title": "Bunun gibi daha fazlası", + "feature.showThoughts.description": "Sohbetlerde modelin düşünme içeriğini gösterir.", + "feature.showThoughts.title": "Düşünme sürecini göster", "feature.speechToText.description": "Etkinleştirildiğinde, sesli giriş kullanabilirsiniz.", "feature.speechToText.title": "Sesten Metne", "feature.suggestedQuestionsAfterAnswer.description": "Sonraki soru önerilerini ayarlamak, kullanıcılara daha iyi bir sohbet deneyimi sunabilir.", diff --git a/web/i18n/locales/uk-UA/app-debug.json b/web/i18n/locales/uk-UA/app-debug.json index c7bb1c8a774..9b792e0f873 100644 --- a/web/i18n/locales/uk-UA/app-debug.json +++ b/web/i18n/locales/uk-UA/app-debug.json @@ -95,6 +95,8 @@ "feature.moreLikeThis.description": "Згенерувати кілька текстів одночасно, а потім редагувати та продовжити генерацію", "feature.moreLikeThis.tip": "Використання цієї функції призведе до додаткових витрат токенів", "feature.moreLikeThis.title": "Більше такого", + "feature.showThoughts.description": "Показувати міркування моделі в розмовах.", + "feature.showThoughts.title": "Показувати міркування", "feature.speechToText.description": "Після увімкнення ви можете використовувати голосовий ввід.", "feature.speechToText.title": "Мовлення в текст", "feature.suggestedQuestionsAfterAnswer.description": "Налаштування пропозицій наступних запитань може надати користувачам кращий чат.", diff --git a/web/i18n/locales/vi-VN/app-debug.json b/web/i18n/locales/vi-VN/app-debug.json index 117e63a74cf..c061ad59267 100644 --- a/web/i18n/locales/vi-VN/app-debug.json +++ b/web/i18n/locales/vi-VN/app-debug.json @@ -95,6 +95,8 @@ "feature.moreLikeThis.description": "Tạo nhiều văn bản cùng một lúc, sau đó chỉnh sửa và tiếp tục tạo ra.", "feature.moreLikeThis.tip": "Sử dụng tính năng này sẽ tiêu tốn thêm token.", "feature.moreLikeThis.title": "Thêm tương tự", + "feature.showThoughts.description": "Hiển thị nội dung suy nghĩ của mô hình trong cuộc trò chuyện.", + "feature.showThoughts.title": "Hiển thị quá trình suy nghĩ", "feature.speechToText.description": "Khi được bật, bạn có thể sử dụng đầu vào bằng giọng nói.", "feature.speechToText.title": "Chuyển đổi giọng nói thành văn bản", "feature.suggestedQuestionsAfterAnswer.description": "Thiết lập đề xuất câu hỏi tiếp theo có thể tạo ra cuộc trò chuyện tốt hơn cho người dùng.", diff --git a/web/i18n/locales/zh-Hans/app-debug.json b/web/i18n/locales/zh-Hans/app-debug.json index a7e00b4cf5a..cf342c49235 100644 --- a/web/i18n/locales/zh-Hans/app-debug.json +++ b/web/i18n/locales/zh-Hans/app-debug.json @@ -95,6 +95,8 @@ "feature.moreLikeThis.description": "一次生成多条文本,可在此基础上编辑并继续生成", "feature.moreLikeThis.tip": "使用此功能将会额外消耗 tokens", "feature.moreLikeThis.title": "更多类似的", + "feature.showThoughts.description": "在对话中展示模型的思考内容。", + "feature.showThoughts.title": "显示思考过程", "feature.speechToText.description": "您可以使用语音输入。", "feature.speechToText.title": "语音转文字", "feature.suggestedQuestionsAfterAnswer.description": "设置下一步问题建议可以让用户更好的对话。", diff --git a/web/i18n/locales/zh-Hant/app-debug.json b/web/i18n/locales/zh-Hant/app-debug.json index 59589bc998e..f311f47b6b9 100644 --- a/web/i18n/locales/zh-Hant/app-debug.json +++ b/web/i18n/locales/zh-Hant/app-debug.json @@ -95,6 +95,8 @@ "feature.moreLikeThis.description": "一次生成多條文字,可在此基礎上編輯並繼續生成", "feature.moreLikeThis.tip": "使用此功能將會額外消耗 tokens", "feature.moreLikeThis.title": "更多類似的", + "feature.showThoughts.description": "在對話中展示模型的思考內容。", + "feature.showThoughts.title": "顯示思考過程", "feature.speechToText.description": "啟用後,您可以使用語音輸入。", "feature.speechToText.title": "語音轉文字", "feature.suggestedQuestionsAfterAnswer.description": "設定下一步問題建議可以讓使用者更好的對話。", diff --git a/web/i18n/resources.generated.d.ts b/web/i18n/resources.generated.d.ts index 92960643c7f..dcd48c7b964 100644 --- a/web/i18n/resources.generated.d.ts +++ b/web/i18n/resources.generated.d.ts @@ -1091,6 +1091,8 @@ export default interface Resources { 'feature.moreLikeThis.description': 'Generate multiple texts at once, and then edit and continue to generate' 'feature.moreLikeThis.tip': 'Using this feature will incur additional tokens overhead' 'feature.moreLikeThis.title': 'More like this' + 'feature.showThoughts.description': 'Display the model’s thinking in conversations.' + 'feature.showThoughts.title': 'Show thinking' 'feature.speechToText.description': 'Voice input can be used in chat.' 'feature.speechToText.title': 'Speech to Text' 'feature.suggestedQuestionsAfterAnswer.description': 'Setting up next questions suggestion can give users a better chat.' diff --git a/web/types/app.ts b/web/types/app.ts index acb0da14371..6516377924a 100644 --- a/web/types/app.ts +++ b/web/types/app.ts @@ -261,6 +261,9 @@ export type ModelConfig = { language?: string autoPlay?: TtsAutoPlay } + show_thoughts?: { + enabled: boolean + } retriever_resource: { enabled: boolean }