|
| 1 | +# Plan: Control Settings via Chat |
| 2 | + |
| 3 | +## Key Decision: Skill-Based Context Control |
| 4 | + |
| 5 | +This feature MUST be described and delivered as a DeepChat skill so that additional instructions/context are only injected when the user actually requests to change DeepChat settings. |
| 6 | + |
| 7 | +- Skill Name (suggested): `deepchat-settings` |
| 8 | +- Activation: Activated via `skill_control` **ONLY** when the user request involves DeepChat settings/preferences. |
| 9 | +- Deactivation: Call `skill_control` after completing the setting change to keep context lean. |
| 10 | + |
| 11 | +## Tool Injection Control (No Skill, No Tools) |
| 12 | + |
| 13 | +Configuration-related tools MUST NOT appear in the LLM tool list (and MUST NOT be mentioned in the system prompt) unless the `deepchat-settings` skill is active. |
| 14 | + |
| 15 | +Implementation intent: |
| 16 | + |
| 17 | +- Define dedicated tools (MCP-format function definitions): |
| 18 | + - `deepchat_settings_toggle` |
| 19 | + - `deepchat_settings_set_language` |
| 20 | + - `deepchat_settings_set_theme` |
| 21 | + - `deepchat_settings_set_font_size` |
| 22 | + - `deepchat_settings_open` |
| 23 | +- **DO NOT** expose them through MCP server/tool list UI (avoid being auto-enabled into `enabledMcpTools`). |
| 24 | +- Only inject these tool definitions when: |
| 25 | + - `deepchat-settings` is enabled for the current conversation, AND |
| 26 | + - The skill's pre-metadata `allowedTools` includes the tool name. |
| 27 | + |
| 28 | +This requires conversation-scoped tool definition construction: |
| 29 | + |
| 30 | +- Extend tool definition construction context to include `conversationId`. |
| 31 | +- Retrieve `skillsAllowedTools` for that conversation (via `SkillPresenter.getActiveSkillsAllowedTools`). |
| 32 | +- Only conditionally append `deepchat_settings_*` tool definitions when allowed. |
| 33 | + |
| 34 | +## Step 1: Safe Settings Application API (Main Process) |
| 35 | + |
| 36 | +### Entry Point |
| 37 | + |
| 38 | +Implement a narrow, validated application surface in the main process (presenter method or agent tool handler) for: |
| 39 | + |
| 40 | +- Accepting `unknown` input and validating it (Zod-style, similar to `AgentFileSystemHandler`). |
| 41 | +- Using an allowlist of setting IDs. |
| 42 | +- Applying changes by calling existing `ConfigPresenter` methods so existing event broadcasts remain correct. |
| 43 | +- Returning structured results to render confirmation/error messages. |
| 44 | + |
| 45 | +### Allowlisted Settings and Mapping |
| 46 | + |
| 47 | +Toggle settings: |
| 48 | + |
| 49 | +- `soundEnabled` -> `ConfigPresenter.setSoundEnabled(boolean)` (broadcasts: `CONFIG_EVENTS.SOUND_ENABLED_CHANGED`) |
| 50 | +- `copyWithCotEnabled` -> `ConfigPresenter.setCopyWithCotEnabled(boolean)` (broadcasts: `CONFIG_EVENTS.COPY_WITH_COT_CHANGED`) |
| 51 | + |
| 52 | +Enum settings: |
| 53 | + |
| 54 | +- `language` -> `ConfigPresenter.setLanguage(locale)` (broadcasts: `CONFIG_EVENTS.LANGUAGE_CHANGED`) |
| 55 | +- `theme` -> `ConfigPresenter.setTheme('dark' | 'light' | 'system')` (broadcasts: `CONFIG_EVENTS.THEME_CHANGED`) |
| 56 | +- `fontSizeLevel` -> `ConfigPresenter.setSetting('fontSizeLevel', level)` (broadcasts `CONFIG_EVENTS.FONT_SIZE_CHANGED` via special case) |
| 57 | + |
| 58 | +### Validation Rules |
| 59 | + |
| 60 | +- Strict allowlist; reject unknown IDs. |
| 61 | +- No implicit type conversion in Step 1. |
| 62 | +- Validation per setting: |
| 63 | + - Booleans: must be boolean type |
| 64 | + - Enum values: must match allowed set |
| 65 | + - `fontSizeLevel`: must be integer within supported range (source of truth TBD; may align with `uiSettingsStore` constants) |
| 66 | + - `language`: must be one of supported locales (reuse support list from config) |
| 67 | + |
| 68 | +### Defense in Depth: Require Skill Activity |
| 69 | + |
| 70 | +Even with controlled tool injection, maintain runtime checks: |
| 71 | + |
| 72 | +- If `deepchat-settings` is **NOT** enabled for the conversation, reject application and return error telling the model/user to activate it. |
| 73 | +- This ensures settings don't accidentally change due to unrelated agent behavior. |
| 74 | + |
| 75 | +## Step 2: Skill Definition (Natural Language Behavior) |
| 76 | + |
| 77 | +### Built-in Skill Artifact |
| 78 | + |
| 79 | +Add `resources/skills/deepchat-settings/SKILL.md`: |
| 80 | + |
| 81 | +- Pre-metadata `description` MUST explicitly state: |
| 82 | + - This is ONLY for changing DeepChat application settings. |
| 83 | + - Activate ONLY when user requests setting changes (settings/preferences/theme/language/font/sound/copy COT). |
| 84 | + - Do NOT activate for OS settings or programming/code settings. |
| 85 | +- Body MUST define: |
| 86 | + - Supported settings (allowlist) and canonical values. |
| 87 | + - How to ask clarifying questions when ambiguous. |
| 88 | + - When to refuse and instead open settings. |
| 89 | + - Always deactivate after completing setting tasks. |
| 90 | + |
| 91 | +### Disallowed Settings -> Open Settings |
| 92 | + |
| 93 | +For requests involving MCP configuration, prompts, providers, API keys, etc.: |
| 94 | + |
| 95 | +- Do NOT apply via tools. |
| 96 | +- Provide precise instructions telling user where to change them. |
| 97 | +- Open settings window and navigate to relevant section if possible. |
| 98 | + |
| 99 | +Implementation options for opening/navigating settings: |
| 100 | + |
| 101 | +- Use `presenter.windowPresenter.createSettingsWindow()`. |
| 102 | +- Optionally `executeJavaScript` to set localStorage navigation hint that UI can read. |
| 103 | +- Or add dedicated IPC channel from main process -> settings renderer to navigate to tab/section. |
| 104 | + |
| 105 | +## Data Model |
| 106 | + |
| 107 | +Introduce shared request/response types (for Step 1 entry point + tools): |
| 108 | + |
| 109 | +- `ChatSettingId` (union of allowlisted IDs) |
| 110 | +- `ApplyChatSettingRequest` (discriminated union `{ id, value }`) |
| 111 | +- `ApplyChatSettingResult` |
| 112 | + - `{ ok: true; id; value; previousValue?; appliedAt }` |
| 113 | + - `{ ok: false; errorCode; message; details? }` |
| 114 | + |
| 115 | +## Testing Strategy |
| 116 | + |
| 117 | +- Main process (Vitest): |
| 118 | + - Allowlist + validation (reject invalid values, no writes) |
| 119 | + - Each supported setting maps to correct `ConfigPresenter` method |
| 120 | + - Skill requirement enforcement works (tool rejects when skill inactive) |
| 121 | +- Renderer/UI (if any navigation hints added): |
| 122 | + - Settings page navigation handler tests (optional) |
0 commit comments