From 1be5a0a355fe889cd60ba43ae2c593065f003ffa Mon Sep 17 00:00:00 2001 From: sychic <47618543+Sychic@users.noreply.github.com> Date: Tue, 25 Aug 2026 15:42:47 -0400 Subject: [PATCH 1/5] feat(labrinth): separate out ai functionality into its own disclosure --- ...0825120000_ai-functionality-disclosure.sql | 24 +++++++++++++++++++ apps/labrinth/src/models/v3/disclosures.rs | 4 +++- 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 apps/labrinth/migrations/20260825120000_ai-functionality-disclosure.sql diff --git a/apps/labrinth/migrations/20260825120000_ai-functionality-disclosure.sql b/apps/labrinth/migrations/20260825120000_ai-functionality-disclosure.sql new file mode 100644 index 0000000000..6347d0c4bb --- /dev/null +++ b/apps/labrinth/migrations/20260825120000_ai-functionality-disclosure.sql @@ -0,0 +1,24 @@ +INSERT INTO project_disclosures (project_id, type, metadata, updated_at, updated_by, set_by_moderator, deleted_at, lock_status) +SELECT + project_id, + 'ai_functionality', + '{"note":null}'::jsonb, + now(), + 0, + set_by_moderator, + deleted_at, + lock_status +FROM project_disclosures +WHERE type = 'ai_content' + AND metadata -> 'uses' ? 'functionality' +ON CONFLICT (project_id, type) DO NOTHING; + +DELETE FROM project_disclosures +WHERE type = 'ai_content' + AND metadata -> 'uses' ? 'functionality' + AND jsonb_array_length(metadata -> 'uses') = 1; + +UPDATE project_disclosures +SET metadata = jsonb_set(metadata, '{uses}', (metadata -> 'uses') - 'functionality') +WHERE type = 'ai_content' + AND metadata -> 'uses' ? 'functionality'; diff --git a/apps/labrinth/src/models/v3/disclosures.rs b/apps/labrinth/src/models/v3/disclosures.rs index 2c7e7b2a45..48da86e906 100644 --- a/apps/labrinth/src/models/v3/disclosures.rs +++ b/apps/labrinth/src/models/v3/disclosures.rs @@ -18,6 +18,9 @@ pub enum ProjectDisclosure { note: Option, uses: BTreeSet, }, + AiFunctionality { + note: Option, + }, Advertisements { note: Option, }, @@ -161,7 +164,6 @@ pub enum AiUsages { Code, Assets, Text, - Functionality, } #[derive(Debug, Clone, Serialize, Deserialize, ToSchema, IntoStaticStr)] From 3ed7ed1bf9e38729ce7cebcbe3677f9789a6de7f Mon Sep 17 00:00:00 2001 From: sychic <47618543+Sychic@users.noreply.github.com> Date: Tue, 25 Aug 2026 21:45:22 -0400 Subject: [PATCH 2/5] chore: increase stack size --- .github/workflows/labrinth-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/labrinth-build.yml b/.github/workflows/labrinth-build.yml index 950a1337bd..dd19280d2d 100644 --- a/.github/workflows/labrinth-build.yml +++ b/.github/workflows/labrinth-build.yml @@ -86,7 +86,7 @@ jobs: GIT_HASH: ${{ github.sha }} SCCACHE_CACHE_SIZE: ${{ needs.skip-if-clean.outputs.internal == 'true' && '20G' || '' }} RUSTC_WRAPPER: ${{ needs.skip-if-clean.outputs.internal == 'true' && 'sccache' || '' }} - RUST_MIN_STACK: '16777216' + RUST_MIN_STACK: '268435456' steps: - name: Check out code uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 From e79d9250471e041646787bf11774c5a4500cbb76 Mon Sep 17 00:00:00 2001 From: Prospector <6166773+Prospector@users.noreply.github.com> Date: Mon, 24 Aug 2026 23:49:32 -0700 Subject: [PATCH 3/5] frontend: migrate genai functionality disclosure --- .../disclosures/AiDisclosureCard.vue | 7 +- .../AiFunctionalityDisclosureCard.vue | 68 +++++++++++++++++++ .../ui/project-settings/disclosures/form.ts | 8 ++- .../ui/project-settings/disclosures/index.ts | 1 + .../ui/project-settings/disclosures/types.ts | 1 + apps/frontend/src/locales/en-US/index.json | 11 ++- .../[type]/[project]/settings/disclosures.vue | 9 +++ .../api-client/src/modules/labrinth/types.ts | 6 +- packages/assets/generated-icons.ts | 2 + packages/assets/icons/brain-circuit.svg | 27 ++++++++ .../project/ProjectSidebarDetails.vue | 23 +++++-- packages/ui/src/locales/de-CH/index.json | 6 -- packages/ui/src/locales/de-DE/index.json | 6 -- packages/ui/src/locales/en-US/index.json | 12 ++-- packages/ui/src/locales/es-419/index.json | 6 -- packages/ui/src/locales/es-ES/index.json | 6 -- packages/ui/src/locales/hu-HU/index.json | 6 -- packages/ui/src/locales/it-IT/index.json | 6 -- packages/ui/src/locales/ko-KR/index.json | 6 -- packages/ui/src/locales/pl-PL/index.json | 6 -- packages/ui/src/locales/pt-BR/index.json | 7 -- packages/ui/src/locales/ru-RU/index.json | 6 -- packages/ui/src/locales/sv-SE/index.json | 6 -- packages/ui/src/locales/tr-TR/index.json | 6 -- packages/ui/src/locales/uk-UA/index.json | 6 -- packages/ui/src/locales/zh-CN/index.json | 6 -- packages/ui/src/locales/zh-TW/index.json | 6 -- packages/ui/src/utils/common-messages.ts | 4 -- packages/ui/src/utils/disclosures.ts | 3 +- packages/ui/src/utils/search.ts | 9 +++ 30 files changed, 168 insertions(+), 114 deletions(-) create mode 100644 apps/frontend/src/components/ui/project-settings/disclosures/AiFunctionalityDisclosureCard.vue create mode 100644 packages/assets/icons/brain-circuit.svg diff --git a/apps/frontend/src/components/ui/project-settings/disclosures/AiDisclosureCard.vue b/apps/frontend/src/components/ui/project-settings/disclosures/AiDisclosureCard.vue index e0280d303b..b1883fb6ce 100644 --- a/apps/frontend/src/components/ui/project-settings/disclosures/AiDisclosureCard.vue +++ b/apps/frontend/src/components/ui/project-settings/disclosures/AiDisclosureCard.vue @@ -25,7 +25,7 @@ const emit = defineEmits<{ const { formatMessage } = useVIntl() -const AI_USES: AiUsage[] = ['code', 'assets', 'text', 'functionality'] +const AI_USES: AiUsage[] = ['code', 'assets', 'text'] const messages = defineMessages({ title: { @@ -35,9 +35,8 @@ const messages = defineMessages({ description: { id: 'project.settings.disclosures.ai.description', defaultMessage: `You must enable this if this project contains a substantial amount of AI-generated code, any - assets that are substantially AI-generated, the project's functionality relies on the use of - generative AI, or if any element of your project's page such as description or publishing - relies on generative AI.`, + assets that are substantially AI-generated, or if any element of your project's page such as + description or publishing relies on generative AI.`, }, contentRules: { id: 'project.settings.disclosures.ai.content-rules', diff --git a/apps/frontend/src/components/ui/project-settings/disclosures/AiFunctionalityDisclosureCard.vue b/apps/frontend/src/components/ui/project-settings/disclosures/AiFunctionalityDisclosureCard.vue new file mode 100644 index 0000000000..0df3a680ee --- /dev/null +++ b/apps/frontend/src/components/ui/project-settings/disclosures/AiFunctionalityDisclosureCard.vue @@ -0,0 +1,68 @@ + + + diff --git a/apps/frontend/src/components/ui/project-settings/disclosures/form.ts b/apps/frontend/src/components/ui/project-settings/disclosures/form.ts index d6cedf831a..5e1ba8e419 100644 --- a/apps/frontend/src/components/ui/project-settings/disclosures/form.ts +++ b/apps/frontend/src/components/ui/project-settings/disclosures/form.ts @@ -22,7 +22,7 @@ function findDisclosure( return disclosures.find((disclosure): disclosure is DisclosureOf => disclosure.type === type) } -type NoteDisclosureType = 'advertisements' | 'epilepsy_triggers' | 'archived' +type NoteDisclosureType = 'ai_functionality' | 'advertisements' | 'epilepsy_triggers' | 'archived' function createNoteModel( disclosures: ProjectDisclosureData[], @@ -66,6 +66,7 @@ export function disclosuresToForm(disclosures: ProjectDisclosureData[]): Disclos uses: ai ? [...(ai.uses ?? [])] : [], note: ai?.note ?? '', }, + aiFunctionality: createNoteModel(disclosures, 'ai_functionality'), advertising: createNoteModel(disclosures, 'advertisements'), paidFeatures: { enabled: isActiveDisclosure(paidFeatures), @@ -110,6 +111,8 @@ export function formToDisclosure( uses: [...form.ai.uses], note: form.ai.note.trim() || null, } + case 'ai_functionality': + return { type: 'ai_functionality', note: form.aiFunctionality.note.trim() || null } case 'advertisements': return { type: 'advertisements', note: form.advertising.note.trim() || null } case 'paid_features': @@ -151,6 +154,9 @@ export function formToDisclosures(form: DisclosureFormState): ProjectDisclosure[ if (form.ai.enabled) { set.push(formToDisclosure(form, 'ai_content')) } + if (form.aiFunctionality.enabled) { + set.push(formToDisclosure(form, 'ai_functionality')) + } if (form.advertising.enabled) { set.push(formToDisclosure(form, 'advertisements')) } diff --git a/apps/frontend/src/components/ui/project-settings/disclosures/index.ts b/apps/frontend/src/components/ui/project-settings/disclosures/index.ts index 085bf22204..3c49f28e9a 100644 --- a/apps/frontend/src/components/ui/project-settings/disclosures/index.ts +++ b/apps/frontend/src/components/ui/project-settings/disclosures/index.ts @@ -1,5 +1,6 @@ export { default as AdvertisingDisclosureCard } from './AdvertisingDisclosureCard.vue' export { default as AiDisclosureCard } from './AiDisclosureCard.vue' +export { default as AiFunctionalityDisclosureCard } from './AiFunctionalityDisclosureCard.vue' export { default as ArchivedDisclosureCard } from './ArchivedDisclosureCard.vue' export { default as DerivativeDisclosureCard } from './DerivativeDisclosureCard.vue' export { default as DisclosureToggleCard } from './DisclosureToggleCard.vue' diff --git a/apps/frontend/src/components/ui/project-settings/disclosures/types.ts b/apps/frontend/src/components/ui/project-settings/disclosures/types.ts index 6983314a98..acf811d467 100644 --- a/apps/frontend/src/components/ui/project-settings/disclosures/types.ts +++ b/apps/frontend/src/components/ui/project-settings/disclosures/types.ts @@ -44,6 +44,7 @@ export type DerivativeDisclosure = { export type DisclosureFormState = { ai: AiDisclosure + aiFunctionality: NoteDisclosure advertising: NoteDisclosure paidFeatures: PaidFeaturesDisclosure telemetry: TelemetryDisclosure diff --git a/apps/frontend/src/locales/en-US/index.json b/apps/frontend/src/locales/en-US/index.json index 38ef534d84..6cdc1f79de 100644 --- a/apps/frontend/src/locales/en-US/index.json +++ b/apps/frontend/src/locales/en-US/index.json @@ -3839,11 +3839,20 @@ "project.settings.disclosures.advertising.title": { "message": "Contains advertisements" }, + "project.settings.disclosures.ai-functionality.description": { + "message": "Placeholder description." + }, + "project.settings.disclosures.ai-functionality.note-placeholder": { + "message": "e.g. This project includes an in-game assistant powered by a generative AI API." + }, + "project.settings.disclosures.ai-functionality.title": { + "message": "Contains generative AI functionality" + }, "project.settings.disclosures.ai.content-rules": { "message": "Please refer to Section 6 of Modrinth's Content Rules for more information." }, "project.settings.disclosures.ai.description": { - "message": "You must enable this if this project contains a substantial amount of AI-generated code, any\n\t\t\t\tassets that are substantially AI-generated, the project's functionality relies on the use of\n\t\t\t\tgenerative AI, or if any element of your project's page such as description or publishing\n\t\t\t\trelies on generative AI." + "message": "You must enable this if this project contains a substantial amount of AI-generated code, any\n\t\t\t\tassets that are substantially AI-generated, or if any element of your project's page such as\n\t\t\t\tdescription or publishing relies on generative AI." }, "project.settings.disclosures.ai.note-placeholder": { "message": "e.g. The Chinese and Arabic translations are AI-generated." diff --git a/apps/frontend/src/pages/[type]/[project]/settings/disclosures.vue b/apps/frontend/src/pages/[type]/[project]/settings/disclosures.vue index 0d79f28ca8..dd9bc55b39 100644 --- a/apps/frontend/src/pages/[type]/[project]/settings/disclosures.vue +++ b/apps/frontend/src/pages/[type]/[project]/settings/disclosures.vue @@ -22,6 +22,7 @@ import { computed, watch } from 'vue' import { AdvertisingDisclosureCard, AiDisclosureCard, + AiFunctionalityDisclosureCard, ArchivedDisclosureCard, DerivativeDisclosureCard, type DisclosureFormIssue, @@ -293,6 +294,14 @@ const { confirmLeaveModal } = usePageLeaveSafety(hasChanges) (status: DisclosureLockStatus) => setDisclosureLockStatus('ai_content', status) " /> + + + + + + + + + + + + + + + + diff --git a/packages/ui/src/components/project/ProjectSidebarDetails.vue b/packages/ui/src/components/project/ProjectSidebarDetails.vue index 8be4b125e9..99399cfb12 100644 --- a/packages/ui/src/components/project/ProjectSidebarDetails.vue +++ b/packages/ui/src/components/project/ProjectSidebarDetails.vue @@ -38,6 +38,17 @@ +
+