Skip to content

Add main language config#2089

Merged
yujonglee merged 1 commit intomainfrom
add-main-language
Dec 3, 2025
Merged

Add main language config#2089
yujonglee merged 1 commit intomainfrom
add-main-language

Conversation

@yujonglee
Copy link
Contributor

No description provided.

@netlify
Copy link

netlify bot commented Dec 3, 2025

Deploy Preview for hyprnote-storybook ready!

Name Link
🔨 Latest commit d20d7cf
🔍 Latest deploy log https://app.netlify.com/projects/hyprnote-storybook/deploys/692fd4f525fd890008fc946b
😎 Deploy Preview https://deploy-preview-2089--hyprnote-storybook.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@netlify
Copy link

netlify bot commented Dec 3, 2025

Deploy Preview for hyprnote ready!

Name Link
🔨 Latest commit d20d7cf
🔍 Latest deploy log https://app.netlify.com/projects/hyprnote/deploys/692fd4f50f52ea0008c61ee8
😎 Deploy Preview https://deploy-preview-2089--hyprnote.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 3, 2025

📝 Walkthrough

Walkthrough

This PR introduces language-aware system prompts by threading language preference through the task processing pipeline. It extracts language from application state, renders system prompts dynamically via template commands with language context, and passes the resulting system prompt to the chat transport for agent configuration.

Changes

Cohort / File(s) Summary
Transport Configuration
apps/desktop/src/chat/transport.ts
Added optional systemPrompt parameter to CustomChatTransport constructor and wired it into agent configuration.
Chat Session State Management
apps/desktop/src/components/chat/session.tsx
Added language state retrieval from store, dynamic system prompt rendering via templateCommands based on language, and passing the rendered prompt to transport initialization.
Settings UI
apps/desktop/src/components/settings/general/main-language.tsx
Restructured component to destructure parameters, enabled the language selector (previously disabled), and replaced static "English" option with dynamic rendering of supported languages from ISO 639-1 codes.
Task Transform Layer
apps/desktop/src/store/zustand/ai-task/task-configs/enhance-transform.ts, title-transform.ts
Extracted language preference from store and injected it into transformed task arguments alongside existing properties.
Task Type Definitions
apps/desktop/src/store/zustand/ai-task/task-configs/index.ts
Added language: string property to TaskArgsMapTransformed.enhance and TaskArgsMapTransformed.title.
Workflow System Prompt Generation
apps/desktop/src/store/zustand/ai-task/task-configs/enhance-workflow.ts, title-workflow.ts
Updated getSystemPrompt functions to accept language from args and pass it to templateCommands.render() for language-specific prompt customization.
Template System
crates/template/assets/_language.partial.jinja
Added new enforce_language macro that conditionally prepends language-enforcement directives to template output when a non-English language is specified.
System Prompt Templates
crates/template/assets/chat.system.jinja, enhance.system.jinja, title.system.jinja
Imported enforce_language macro and integrated it to inject language directives into each system prompt template.
Template Registry
crates/template/src/lib.rs
Registered _language.partial.jinja as a public template for non-debug builds.

Sequence Diagram(s)

sequenceDiagram
    participant User as User Settings
    participant Store as App Store
    participant ChatSession as Chat Session Component
    participant TemplateCmd as Template Commands
    participant Transport as Chat Transport
    participant Agent as AI Agent

    User->>Store: Select Language (e.g., "es")
    ChatSession->>Store: Read ai_language preference
    Store-->>ChatSession: Return language code
    ChatSession->>TemplateCmd: render("chat.system", { language: "es" })
    Note over TemplateCmd: enforce_language("es", "IMPORTANT: Respond in")<br/>injects language directive
    TemplateCmd-->>ChatSession: Return system prompt with<br/>language enforcement
    ChatSession->>Transport: new CustomChatTransport(registry, model, systemPrompt)
    Transport->>Agent: Configure agent with system prompt<br/>(includes language directive)
    Note over Agent: System prompt now constrains<br/>agent responses to selected language
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Template System Integration: Understand how enforce_language macro interacts with Jinja template rendering and verify language directives are correctly injected into chat, enhance, and title system prompts.
  • State Threading: Verify language dependency is correctly added to useEffect hooks and that system prompt re-renders when language changes.
  • Type Safety: Confirm TaskArgsMapTransformed type extensions properly propagate language through the transform and workflow layers.
  • Settings UI Restructuring: Review that the language selector component correctly maps supportedLanguages to ISO 639-1 display names and handles the onChange callback properly.

Possibly related PRs

  • changed to system instructions #1296: Modifies the enhance.system template render call site to pass custom instructions, which overlaps with the language parameter integration in this PR's workflow layer.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Description check ❓ Inconclusive No pull request description was provided by the author, making it impossible to evaluate whether it relates to the changeset. Add a description explaining the purpose and scope of the language configuration feature being introduced.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Add main language config' directly relates to the main change: introducing language configuration support throughout the codebase, including new language state management, system prompts with language enforcement, and template updates.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch add-main-language

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (5)
apps/desktop/src/components/settings/general/main-language.tsx (1)

17-20: Consider using ISO_639_1_CODE for the value prop type.

The value prop is typed as string while supportedLanguages is typed as ISO_639_1_CODE[]. Using the same type for value would provide better type safety and ensure only valid language codes are passed.

 }: {
-  value: string;
-  onChange: (value: string) => void;
+  value: ISO_639_1_CODE;
+  onChange: (value: ISO_639_1_CODE) => void;
   supportedLanguages: ISO_639_1_CODE[];
 }) {
apps/desktop/src/components/chat/session.tsx (2)

167-179: Guard async systemPrompt loading to avoid stale updates / unmounted setState

The effect correctly reloads the system prompt when language changes, but it can still resolve after the language has changed again or the component has unmounted. A small guard improves robustness and avoids stale systemPrompt updates:

-  useEffect(() => {
-    templateCommands
-      .render("chat.system", { language })
-      .then((result) => {
-        if (result.status === "ok") {
-          setSystemPrompt(result.data);
-        }
-      })
-      .catch(console.error);
-  }, [language]);
+  useEffect(() => {
+    let cancelled = false;
+
+    templateCommands
+      .render("chat.system", { language })
+      .then((result) => {
+        if (!cancelled && result.status === "ok") {
+          setSystemPrompt(result.data);
+        }
+      })
+      .catch((error) => {
+        if (!cancelled) {
+          console.error(error);
+        }
+      });
+
+    return () => {
+      cancelled = true;
+    };
+  }, [language]);

This ensures older in‑flight renders don’t overwrite a newer language’s prompt and avoids calling setSystemPrompt after unmount.

Please confirm in the @hypr/plugin-template docs that render("chat.system", { language }) is side‑effect free and safe to retry, so this cancellation pattern won’t interfere with internal caching or metrics.


186-187: Transport memoization with systemPrompt is correct; consider gating on prompt readiness

Including systemPrompt in the useMemo dependency and passing it into CustomChatTransport ensures language/template changes take effect for subsequent messages, which matches the PR’s goal.

If you want to guarantee that every message in a session uses a resolved system prompt (and never falls back to undefined on first render), consider delaying transport creation until the prompt is ready, e.g.:

-    if (!model) {
+    if (!model) {
       return null;
     }
-
-    return new CustomChatTransport(registry, model, systemPrompt);
-  }, [registry, model, systemPrompt]);
+    if (!systemPrompt) {
+      return null;
+    }
+
+    return new CustomChatTransport(registry, model, systemPrompt);
+  }, [registry, model, systemPrompt]);

That’s optional and depends on whether “no system prompt until template loads” is acceptable for the first user message.

It may be worth confirming in the @ai-sdk/react docs that swapping the transport instance during a session (when systemPrompt appears) is fully supported for your useChat usage.

apps/desktop/src/store/zustand/ai-task/task-configs/title-transform.ts (1)

12-15: Language derivation for title looks good; consider de‑duplicating helper

Reading ai_language from the store with a non‑empty check and defaulting to "en" is sane and gives the template a stable language value. The same getLanguage logic exists in enhance-transform.ts; consider extracting a tiny shared helper so the behavior can’t drift between title and enhance over time (optional).

Also applies to: 22-25

crates/template/assets/_language.partial.jinja (1)

1-5: Macro logic is correct; consider language name for clarity.

The conditional logic and whitespace handling are sound. The macro correctly skips enforcement for English and empty values.

However, the output format uses language codes directly (e.g., "Generate the title in ko language."), which is grammatically awkward. Consider one of these alternatives for better readability:

  • Option 1: "Generate the title in {language_code}." (simpler)
  • Option 2: Map codes to names (e.g., "ko" → "Korean") for grammatically correct output

Since LLMs can likely understand language codes in context, this is optional.

Optional: Alternative with cleaner formatting
 {% macro enforce_language(language_code, prefix, suffix="language.") -%}
 {% if language_code and language_code != "en" -%}
-{{ prefix }} {{ language_code }} {{ suffix }}
+{{ prefix }} {{ language_code }}.
 {% endif -%}
 {%- endmacro %}

This produces: "Generate the title in ko." which reads more naturally.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9f2f8b4 and d20d7cf.

📒 Files selected for processing (13)
  • apps/desktop/src/chat/transport.ts (2 hunks)
  • apps/desktop/src/components/chat/session.tsx (2 hunks)
  • apps/desktop/src/components/settings/general/main-language.tsx (2 hunks)
  • apps/desktop/src/store/zustand/ai-task/task-configs/enhance-transform.ts (1 hunks)
  • apps/desktop/src/store/zustand/ai-task/task-configs/enhance-workflow.ts (1 hunks)
  • apps/desktop/src/store/zustand/ai-task/task-configs/index.ts (2 hunks)
  • apps/desktop/src/store/zustand/ai-task/task-configs/title-transform.ts (1 hunks)
  • apps/desktop/src/store/zustand/ai-task/task-configs/title-workflow.ts (1 hunks)
  • crates/template/assets/_language.partial.jinja (1 hunks)
  • crates/template/assets/chat.system.jinja (1 hunks)
  • crates/template/assets/enhance.system.jinja (1 hunks)
  • crates/template/assets/title.system.jinja (1 hunks)
  • crates/template/src/lib.rs (2 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.ts: Agent implementations should use TypeScript and follow the established architectural patterns defined in the agent framework
Agent communication should use defined message protocols and interfaces

Files:

  • apps/desktop/src/store/zustand/ai-task/task-configs/index.ts
  • apps/desktop/src/store/zustand/ai-task/task-configs/enhance-workflow.ts
  • apps/desktop/src/chat/transport.ts
  • apps/desktop/src/store/zustand/ai-task/task-configs/title-transform.ts
  • apps/desktop/src/store/zustand/ai-task/task-configs/enhance-transform.ts
  • apps/desktop/src/store/zustand/ai-task/task-configs/title-workflow.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Avoid creating a bunch of types/interfaces if they are not shared. Especially for function props, just inline them instead.
Never do manual state management for form/mutation. Use useForm (from tanstack-form) and useQuery/useMutation (from tanstack-query) instead for 99% of cases. Avoid patterns like setError.
If there are many classNames with conditional logic, use cn (import from @hypr/utils). It is similar to clsx. Always pass an array and split by logical grouping.
Use motion/react instead of framer-motion.

Files:

  • apps/desktop/src/store/zustand/ai-task/task-configs/index.ts
  • apps/desktop/src/store/zustand/ai-task/task-configs/enhance-workflow.ts
  • apps/desktop/src/chat/transport.ts
  • apps/desktop/src/store/zustand/ai-task/task-configs/title-transform.ts
  • apps/desktop/src/store/zustand/ai-task/task-configs/enhance-transform.ts
  • apps/desktop/src/components/chat/session.tsx
  • apps/desktop/src/components/settings/general/main-language.tsx
  • apps/desktop/src/store/zustand/ai-task/task-configs/title-workflow.ts
🧬 Code graph analysis (4)
apps/desktop/src/store/zustand/ai-task/task-configs/enhance-transform.ts (1)
crates/whisper-local/src/model/mod.rs (1)
  • language (26-28)
apps/desktop/src/components/chat/session.tsx (2)
crates/whisper-local/src/model/mod.rs (1)
  • language (26-28)
apps/desktop/src/chat/transport.ts (1)
  • CustomChatTransport (12-60)
apps/desktop/src/components/settings/general/main-language.tsx (1)
extensions/shared/types/hypr-extension.d.ts (5)
  • Select (397-397)
  • SelectTrigger (409-409)
  • SelectValue (410-410)
  • SelectContent (398-398)
  • SelectItem (400-400)
apps/desktop/src/store/zustand/ai-task/task-configs/title-workflow.ts (1)
apps/desktop/src/store/zustand/ai-task/task-configs/index.ts (1)
  • TaskArgsMapTransformed (20-56)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: Redirect rules - hyprnote
  • GitHub Check: Header rules - hyprnote
  • GitHub Check: Pages changed - hyprnote
  • GitHub Check: fmt
  • GitHub Check: desktop_ci (linux, depot-ubuntu-22.04-8)
  • GitHub Check: desktop_ci (macos, depot-macos-14)
  • GitHub Check: desktop_ci (linux, depot-ubuntu-24.04-8)
🔇 Additional comments (12)
apps/desktop/src/components/settings/general/main-language.tsx (1)

30-41: LGTM!

The Select implementation correctly binds value/onChange and dynamically generates options from supportedLanguages. The key usage with code is appropriate for unique ISO 639-1 codes.

apps/desktop/src/chat/transport.ts (2)

13-17: Constructor extension for systemPrompt looks good

Adding the optional systemPrompt parameter and storing it on the instance is straightforward and keeps existing two‑argument call sites valid. No issues here.


24-27: Wiring systemPrompt into Agent.system matches the PR intent

Forwarding the stored systemPrompt into the Agent’s system field is the right place to inject the template‑driven system prompt; behavior should remain unchanged when systemPrompt is undefined.

If you haven’t already, please double‑check the Experimental_Agent options in the ai SDK docs to confirm system is nullable/optional and behaves as expected with undefined.

apps/desktop/src/components/chat/session.tsx (1)

3-5: New imports align with usage

Bringing in useState and templateCommands cleanly matches the new useTransport logic below; import structure stays consistent with the rest of the file.

If you’re upgrading or pinning @hypr/plugin-template, please confirm that commands.render is still the recommended API name in the current version.

apps/desktop/src/store/zustand/ai-task/task-configs/enhance-workflow.ts (1)

70-74: Language-aware system prompt wiring for enhance looks correct

getSystemPrompt now threads args.language into enhance.system, matching TaskArgsMapTransformed["enhance"] and the new language-enforcing template; no issues spotted.

crates/template/src/lib.rs (1)

77-78: Embedded _language.partial registration matches existing template pattern

Defining LANGUAGE_PARTIAL_TPL and registering it as "_language.partial" in the non‑debug environment mirrors how other templates are embedded, so the new partial will be available in release builds as expected.

Also applies to: 99-135

apps/desktop/src/store/zustand/ai-task/task-configs/title-workflow.ts (1)

55-65: Title system prompt now correctly uses task language

Using args.language when rendering title.system (and returning result.data) aligns the workflow with the new language-aware templates; the change is consistent with the transformed args shape.

apps/desktop/src/store/zustand/ai-task/task-configs/index.ts (1)

20-55: Transformed task args now properly carry language for enhance and title

Adding language: string to both enhance and title in TaskArgsMapTransformed matches the updated transform/workflow logic and supports the language-aware templates; the type surface looks coherent.

crates/template/assets/enhance.system.jinja (1)

1-7: Language enforcement hook in enhance.system aligns with workflow changes

Using enforce_language(language, "IMPORTANT: Generate all content in") matches the new getSystemPrompt payload (which now includes language) and cleanly centralizes language instructions in the shared partial.

apps/desktop/src/store/zustand/ai-task/task-configs/enhance-transform.ts (1)

49-64: Enhance transform now reliably provides language for downstream templates

Injecting language = getLanguage(store) into the transformed enhance args, with ai_language lookup and "en" fallback, ensures enhance.system always receives a usable language value; the implementation is straightforward and consistent with the title transform.

Also applies to: 71-74

crates/template/assets/chat.system.jinja (1)

1-7: No action required—language is already being passed to the template context.

The single chat.system render call site in apps/desktop/src/components/chat/session.tsx already passes language explicitly: .render("chat.system", { language }). The language value is obtained with a fallback default of "en", ensuring it is never undefined.

crates/template/assets/title.system.jinja (1)

1-4: The language variable is correctly passed to the template context in the rendering call at apps/desktop/src/store/zustand/ai-task/task-configs/title-workflow.ts:56-57, where templateCommands.render("title.system", { language: args.language }) provides the required parameter. No action needed.

@yujonglee yujonglee merged commit 11f2c9b into main Dec 3, 2025
16 checks passed
@yujonglee yujonglee deleted the add-main-language branch December 3, 2025 06:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant