Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# Changelog

## v1.0.5-beta.5 (2026-05-27)
- Added scheduled tasks for recurring agent work
- Added high-priority language support and completed missing locale keys for broader localization coverage
- Fixed MiMo Pro TTS routing so it uses chat-compatible provider behavior
- Preserved paired Feishu users across remote-control state updates
- 新增定时任务能力,支持周期性的 Agent 工作
- 新增高优先级语言支持,并补齐缺失的本地化 keys,扩大多语言覆盖
- 修复 MiMo Pro 的 TTS 路由,使其使用兼容聊天的 Provider 行为
- 修复飞书远程控制状态更新时配对用户被丢失的问题

## v1.0.5-beta.4 (2026-05-25)
- Added session tape memory to persist and compress agent conversation history more reliably
- Synced CUA driver to v0.2.0 with diagnostic tools and improved app launching
Expand Down
21 changes: 21 additions & 0 deletions docs/archives/chat-audio-tts-routing/plan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Chat Audio TTS Routing Plan

## Implementation

- Tighten `isChatAudioTtsModel` so MiMo IDs must match the known MiMo prefixes and include a standalone `tts` segment.
- Update `executeTtsPatternB` to treat `message.content` as unknown response data.
- Extract audio parts only after checking `Array.isArray(message.content)`.
- Keep `message.audio.data` as the first-preference extraction path.
- Leave the existing missing-audio error path in place for responses that contain no audio data.

## Test Strategy

- Add shared helper coverage for MiMo TTS and non-TTS model IDs.
- Extend `test/main/presenter/llmProviderPresenter/aiSdkRuntime.test.ts`.
- Cover `mimo-v2.5-pro` using normal chat streaming instead of direct TTS `fetch`.
- Cover a successful HTTP response with string `message.content` and no audio payload.
- Assert the runtime rejects with the expected missing-audio error, not `content.find is not a function`.

## Compatibility

This change is backward-compatible for actual MiMo TTS models. Non-TTS MiMo chat models stop being routed through TTS handling, while providers returning `message.audio.data` or array content audio parts keep the same behavior.
26 changes: 26 additions & 0 deletions docs/archives/chat-audio-tts-routing/spec.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Chat Audio TTS Routing

## User Story

When a MiMo chat model is selected, DeepChat should only enter chat-audio TTS handling for model IDs that are actually TTS variants. Regular MiMo chat models such as `MiMo-V2.5-Pro` should use the normal chat streaming runtime.

## Acceptance Criteria

- `mimo-v2.5-pro` and provider-prefixed variants are not classified as TTS models.
- MiMo model IDs with a `tts` segment, such as `mimo-v2.5-tts`, continue to use chat-audio TTS Pattern B.
- Chat-audio TTS responses with `choices[0].message.audio.data` continue to emit cached audio.
- Chat-audio TTS responses with array `choices[0].message.content` can still extract an audio content part.
- Chat-audio TTS responses with string `choices[0].message.content` do not throw a `TypeError`.
- If no audio payload exists, DeepChat raises the existing missing-audio error instead of a response-shape crash.

## Non-Goals

- No changes to renderer audio display behavior.
- No changes to request body construction for chat-audio TTS models.

## Constraints

- Keep the fix localized to the AI SDK runtime.
- Keep TTS model classification in shared helpers so provider and agent runtime checks agree.
- Preserve current OpenAI-compatible chat-audio behavior.
- Add focused regression coverage for the reported MiMo Pro misrouting and response shape.
8 changes: 8 additions & 0 deletions docs/archives/chat-audio-tts-routing/tasks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Chat Audio TTS Routing Tasks

- [x] Create SDD issue artifacts.
- [x] Guard chat-audio TTS content audio extraction by response shape.
- [x] Add a regression test for string `message.content`.
- [x] Tighten MiMo chat-audio TTS classification.
- [x] Add regression coverage for MiMo Pro chat routing.
- [x] Run focused test coverage and quality checks.
25 changes: 25 additions & 0 deletions docs/archives/i18n-missing-translations/plan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Plan

## Scope

The scan found four real missing key paths that are referenced from renderer code:

- `mcp.errors.loadClientsFailed`
- `mcp.prompts.required`
- `promptSetting.uploadFailed`
- `settings.mcp.noServersDescription`

`searchDisclaimer` is supplied from each locale `index.ts`, and `settings.display.*` is dynamically built from existing `text-sm`, `text-base`, `text-lg`, `text-xl`, and `text-2xl` keys, so those are not changed.

## Implementation

- Add the missing keys to every locale JSON file in the matching namespace.
- Re-run the i18n type generator so `src/types/i18n.d.ts` reflects the source locale.
- Validate with format, i18n check, and lint.

## Test Strategy

- Run `pnpm run i18n:types`.
- Run `pnpm run format`.
- Run `pnpm run i18n`.
- Run `pnpm run lint`.
22 changes: 22 additions & 0 deletions docs/archives/i18n-missing-translations/spec.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Missing i18n Translations

## User Story

As a DeepChat user, I want every supported locale to provide translations for UI keys that are currently used by the app so that the interface never falls back to raw i18n key strings.

## Acceptance Criteria

- All statically used i18n keys found missing from the active locale bundles are added to every supported locale.
- `pnpm run i18n` reports no missing or invalid translations.
- The generated i18n type definitions include the restored source-locale keys.

## Non-Goals

- Do not rewrite existing translations unrelated to missing keys.
- Do not remove stale extra keys that are not currently used by the UI.
- Do not change runtime i18n loading behavior.

## Constraints

- Keep the existing locale file layout under `src/renderer/src/i18n/<locale>/`.
- Preserve interpolation placeholders such as `{count}` and `{serverName}` exactly where needed.
8 changes: 8 additions & 0 deletions docs/archives/i18n-missing-translations/tasks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Tasks

- [x] Create SDD notes for the missing translation fix.
- [x] Add `mcp.errors.loadClientsFailed` and `mcp.prompts.required` in all locales.
- [x] Add `promptSetting.uploadFailed` in all locales.
- [x] Add `settings.mcp.noServersDescription` in all locales.
- [x] Regenerate i18n types and run validation commands.
- [x] Archive the completed SDD notes.
27 changes: 27 additions & 0 deletions docs/features/high-priority-i18n-languages/plan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# High Priority i18n Languages Plan

## Scope

Implement the requested locales by following the existing static i18n bundle pattern. The source of truth for required keys is `src/renderer/src/i18n/zh-CN`, with `en-US` as a secondary reference for shorter Latin-script phrasing.

## Implementation

- Create one locale directory per target locale under `src/renderer/src/i18n/`.
- Reuse the existing locale `index.ts` import/export shape for each new locale.
- Register new locale modules in `src/renderer/src/i18n/index.ts`.
- Add language options in `src/renderer/settings/components/DisplaySettings.vue`.
- Add new locale codes to `ConfigPresenter.getSystemLanguage()`, `ChatLanguage`, and the DeepChat settings Agent tool schema.
- Extend shared context-menu and error-message translations in `src/shared/i18n.ts`.
- Keep RTL handling unchanged because all requested locales are LTR.

## Validation

- Run a structural comparison against `zh-CN` for all target locale JSON files.
- Run `pnpm run format`.
- Run `pnpm run i18n`.
- Run `pnpm run lint`.

## Risks

- The largest risk is incomplete or malformed JSON translation files. Mitigation: validate parseability and exact key parity.
- Some UI strings may become long in German, Polish, Turkish, or Vietnamese. Mitigation: prefer natural but concise desktop UI wording and use English as a length reference where appropriate.
29 changes: 29 additions & 0 deletions docs/features/high-priority-i18n-languages/spec.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# High Priority i18n Languages

## User Stories

- As a DeepChat desktop user in Spain, Germany, Turkey, Indonesia, Malaysia, Italy, Poland, or Vietnam, I can select my language in Display settings and use the app with readable local UI text.
- As a user whose system locale is one of the supported locales, DeepChat can resolve the matching app language when language is set to System.
- As an Agent Skills user, product and technical names such as DeepChat, Agent, Skills, MCP, Dify, and model/provider names remain recognizable and are not mistranslated.

## Acceptance Criteria

- Add full renderer i18n bundles for `es-ES`, `de-DE`, `tr-TR`, `id-ID`, `ms-MY`, `it-IT`, `pl-PL`, and `vi-VN`.
- Each new locale has the same JSON files and key structure as `zh-CN`.
- New locales are registered in renderer, settings renderer, floating renderer, language selector options, system-locale matching, shared chat settings types, and DeepChat settings Agent tool language schema.
- Shared native menu and error-label translations support the new locales where the shared i18n helper is used.
- Translation wording follows the Chinese source meaning, with English used as length/reference for Latin-script languages.
- Product and domain terms stay untranslated where requested: DeepChat, Agent, Skills, MCP, Dify, model/provider brand names, API, JSON, URL, token, prompt, and similar technical identifiers.
- `pnpm run format`, `pnpm run i18n`, and `pnpm run lint` pass.

## Non-Goals

- No UI layout redesign.
- No new runtime language-loading architecture.
- No locale-specific date, number, or plural-rule behavior beyond existing vue-i18n support unless needed by validation.

## Constraints

- Preserve existing keys, placeholders, interpolation variables, markdown, and JSON syntax.
- Keep translations clear for desktop application users; avoid jargon-heavy or literal machine-style phrasing.
- Resolve implementation without `[NEEDS CLARIFICATION]` markers.
8 changes: 8 additions & 0 deletions docs/features/high-priority-i18n-languages/tasks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# High Priority i18n Languages Tasks

- [x] Create SDD artifacts for the i18n expansion.
- [x] Add translated locale bundles for `es-ES`, `de-DE`, `tr-TR`, `id-ID`, `ms-MY`, `it-IT`, `pl-PL`, and `vi-VN`.
- [x] Register all new locales in renderer and main-process language support.
- [x] Extend shared menu/error translations for the new locale codes.
- [x] Validate locale key parity and JSON parseability.
- [x] Run `pnpm run format`, `pnpm run i18n`, and `pnpm run lint`.
63 changes: 63 additions & 0 deletions docs/features/scheduled-tasks/plan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Implementation Plan

## Architecture

- **Shared types** (`src/shared/scheduledTasks.ts`) define the `Trigger`,
`Action`, `ScheduledTask`, and `ScheduledTasksSettings` shapes.
- **Route contracts** (`src/shared/contracts/routes/scheduledTasks.routes.ts`)
expose `scheduledTasks.{list,upsert,delete,toggle,fireNow}` via Zod
schemas, mirroring `onboarding.routes.ts`.
- **Persistence** is handled in `ConfigPresenter` (`get/setScheduledTasks`)
with a `normalizeScheduledTasksConfig` pass identical in pattern to
`normalizeHooksNotificationsConfig`.
- **Scheduling** lives in a new `ScheduledTasksService`
(`src/main/presenter/scheduledTasks/index.ts`). One `setTimeout` per
armed task, chained at most 12h at a time. Public surface:
- `start()` — read tasks, run startup pass (one-shot backfill, arm next
slot for recurring), called from the existing lifecycle init flow.
- `stop()` — clear all armed timers (called on app shutdown).
- `list()` / `upsert(task)` / `delete(id)` / `toggle(id, enabled)` /
`fireNow(id)` — back the IPC routes and rearm timers on mutation.
- `computeNextFireAt(task, after)` — pure function, exported for tests.
- **Action dispatch** is a small helper inside the service: switch on
`task.action.kind`, then call `notificationPresenter` and/or
`eventBus.sendToRenderer(DEEPLINK_EVENTS.START, ...)` and/or
`sessionService.createSession(...)`.

## Wiring

- `Presenter` constructor (`src/main/presenter/index.ts`) instantiates
`ScheduledTasksService` next to `hooksNotifications`, passing it
`configPresenter`, `notificationPresenter`, `windowPresenter`, and a
thunk that resolves `sessionService` lazily (the route runtime owns
sessionService, so the service exposes a setter the route runtime calls
during bootstrap).
- `src/main/routes/index.ts` wires the five new route cases against
`runtime.scheduledTasksService` and, in the same place that constructs
the runtime, sets the service's session-service reference so auto-send
has somewhere to call.
- Lifecycle `after-start` hook invokes `scheduledTasksService.start()`
after the other presenters have come up; the existing `beforeQuit` hook
calls `stop()`.

## UI

- Settings navigation adds `settings-scheduled-tasks` (group `tools`,
position 5.6, icon `lucide:clock-9`).
- `ScheduledTasksSettings.vue` mirrors `NotificationsHooksSettings.vue`:
ScrollArea + header + "新建任务" button + bordered cards per task.
- A renderer client `ScheduledTasksClient.ts` matches the
`OnboardingClient` shape.
- i18n keys go in every locale under `routes.settings-scheduled-tasks` and
`settings.scheduledTasks.*` so `pnpm run i18n` stays green.

## Validation

- `pnpm run format`
- `pnpm run i18n`
- `pnpm run lint`
- `pnpm run typecheck`
- Unit tests in `test/main/presenter/scheduledTasks.test.ts` cover
`computeNextFireAt` (daily wrap, weekly across the week, one-shot past
with/without `lastFiredAt`) and `normalizeScheduledTasksConfig`
(drops malformed entries, deduplicates ids, preserves valid ones).
59 changes: 59 additions & 0 deletions docs/features/scheduled-tasks/spec.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Scheduled Tasks

## Problem

Closes [#1567](https://github.com/ThinkInAIXYZ/deepchat/issues/1567).

Users want to schedule "reminders" and "planned tasks" inside DeepChat —
either a plain notification ("drink water at 4pm every day") or a scheduled
chat prompt ("every morning at 9 ask the deepchat agent for today's plan").
No equivalent feature exists today; the only time-aware paths are
`hooksNotifications` (event-driven, not time-driven) and the deeplink
"start" flow (which has `autoSend` security-disabled, so it can only
prefill a chat draft).

## User Story

As a DeepChat user, I want to create a scheduled task with a trigger time
(once at a specific datetime, daily, or weekly on a chosen day) and an
action (raise a system notification, prefill a new chat thread with a
preset prompt, or auto-send a preset prompt to a chosen agent/model). I
want my tasks to persist across app restarts; one-shot tasks that I missed
because the app was closed should still fire on next launch.

## Acceptance Criteria

- A "定时任务" entry exists in Settings → Tools (between Notifications &
Hooks and Plugins). It lists, creates, edits, toggles, deletes, and
manually fires user-defined scheduled tasks.
- Each task has:
- A name and an enabled toggle.
- A trigger of one of three kinds: `once` (a specific datetime),
`daily` (hour + minute), or `weekly` (day-of-week + hour + minute).
- An action of one of two kinds: `notify` (title + body for the system
notification) or `prompt` (notification title + chat message + optional
agent / provider / model / system prompt + `autoSend` toggle).
- When a task fires:
- `notify`: a system notification appears via `notificationPresenter`,
subject to the existing `notificationsEnabled` config.
- `prompt` with `autoSend = false`: a system notification appears and the
main window's new-thread page receives the deeplink-start payload,
prefilling the chat input.
- `prompt` with `autoSend = true`: `sessionService.createSession` is
invoked directly using the configured agent/provider/model, so the LLM
actually responds without user interaction. A notification is raised
when the session is created.
- One-shot tasks whose `firesAt` was in the past at launch and that have no
`lastFiredAt` recorded are fired once on startup (backfill). Recurring
tasks are not backfilled — they simply jump to the next slot.
- Task records survive app restart (persisted through `ConfigPresenter`'s
ElectronStore as the `scheduledTasks` key).

## Non-goals

- Cron-expression input. Daily / weekly / once is sufficient for the
feature ask; a future iteration may add `cron` and `interval` trigger
kinds.
- Per-task timezone handling. Triggers use the OS's local time.
- Letting the LLM schedule tasks via an MCP tool. Possible follow-up.
- Calendar / iCal export.
16 changes: 16 additions & 0 deletions docs/features/scheduled-tasks/tasks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Tasks

- [x] Add SDD artifacts.
- [x] Define shared types (`src/shared/scheduledTasks.ts`) and route contracts.
- [x] Implement `ScheduledTasksService` (presenter + `computeNextFireAt` + action dispatch).
- [x] Wire `ConfigPresenter` persistence (`scheduledTasks` key) with normalize-on-read.
- [x] Register routes in `src/main/routes/index.ts` and instantiate in `Presenter` constructor.
- [x] Hook lifecycle: start on `after-start`, stop on `beforeQuit`.
- [x] Add renderer client `src/renderer/api/ScheduledTasksClient.ts`.
- [x] Add settings navigation entry and dynamic route component.
- [x] Implement `ScheduledTasksSettings.vue` (CRUD, mirror NotificationsHooks layout).
- [x] Add i18n keys across all locales.
- [x] Unit tests for `computeNextFireAt` and `normalizeScheduledTasksConfig`.
- [x] Add service tests for notification firing, one-shot disable, and prompt auto-send dispatch.
- [x] Run `pnpm run format`, `pnpm run i18n`, `pnpm run lint`, `pnpm run typecheck`.
- [x] Address PR review comments without changing scheduled-task behavior.
23 changes: 23 additions & 0 deletions docs/issues/feishu-pairing-save-race/plan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Plan

## Implementation Approach
- Inspect `RemoteControlPresenter.saveFeishuSettings` and binding store ownership of Feishu paired users.
- Update Feishu settings save to persist editable settings while preserving `config.pairedUserOpenIds`.
- Keep runtime rebuild behavior unchanged after saving credentials or enabled state.

## Affected Interfaces
- `saveFeishuSettings(input: FeishuRemoteSettings)` behavior changes to ignore `input.pairedUserOpenIds` for persistence.
- Returned settings remain `FeishuRemoteSettings` and include the current paired users from storage.

## Data Flow
- Frontend sends normalized Feishu settings, possibly from stale form state.
- Main process updates editable Feishu config fields.
- Existing `pairedUserOpenIds` is copied from the current config, so pairing state created by command handling is preserved.

## Compatibility
- No IPC or renderer contract changes.
- Old frontend payloads with `pairedUserOpenIds` continue to be accepted but cannot mutate authorization state.

## Test Strategy
- Add a main presenter unit test that seeds a paired Feishu user, saves settings with `pairedUserOpenIds: []`, and expects the paired user to remain.
- Run focused remote control presenter tests, then required format/i18n/lint commands if feasible.
21 changes: 21 additions & 0 deletions docs/issues/feishu-pairing-save-race/spec.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Feishu Pairing Save Race

## User Need
Feishu/Lark Remote Control users who complete `/pair <code>` must stay authorized after the settings page auto-saves stale form state.

## Goal
Prevent general Feishu settings saves from overwriting the runtime-managed `pairedUserOpenIds` list.

## Acceptance Criteria
- Saving Feishu settings preserves the existing paired user open IDs when the input contains an older or empty list.
- Pair/unpair operations remain the only path that changes Feishu paired users.
- Existing Feishu settings fields such as brand, credentials, enabled state, default agent, and workdir still save normally.
- Regression coverage verifies stale frontend settings cannot erase a paired Feishu user.

## Constraints
- Keep public settings shape compatible with the current renderer and IPC contracts.
- Avoid broad changes to unrelated remote channels unless a matching save-race path is confirmed in code.

## Non-Goals
- Redesign remote settings state management.
- Remove `pairedUserOpenIds` from shared types in this fix.
6 changes: 6 additions & 0 deletions docs/issues/feishu-pairing-save-race/tasks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Tasks

- [x] Capture issue requirements and SDD artifacts.
- [x] Change Feishu settings save to preserve paired users.
- [x] Add regression test for stale Feishu settings save.
- [x] Run formatting, i18n generation, lint, and focused tests.
Loading
Loading