Skip to content

Comments

feat(plugin-sdk): add setInput and clearInput methods to BoxSDK#222

Merged
TalexDreamSoul merged 27 commits intomasterfrom
fix/2.4.7-251201
Dec 6, 2025
Merged

feat(plugin-sdk): add setInput and clearInput methods to BoxSDK#222
TalexDreamSoul merged 27 commits intomasterfrom
fix/2.4.7-251201

Conversation

@TalexDreamSoul
Copy link
Contributor

@TalexDreamSoul TalexDreamSoul commented Dec 2, 2025

Summary by CodeRabbit

  • New Features

    • Filterable, paginated clipboard search API; setInput/clearInput added to Box SDK; keyboard event forwarding to plugin UIs.
  • Improvements

    • CoreBox recognizes shortcut-triggered opens and enables shortcut-specific autofill; improved search relevance with tokenization and scoring; Arrow key list wrapping for small lists; ESC prioritizes clearing/teardown before hiding; safer external link handling with user prompt.
  • Documentation

    • Added docs for keyboard API and updated Box SDK input/channel guidance.

✏️ Tip: You can customize this high-level summary in your review settings.

This commit introduces new functionality to the Plugin SDK, allowing plugins to programmatically control the content of the CoreBox input field.

New BoxSDK methods:
- `plugin.box.setInput(value)`: Sets the input field to a specified string.
- `plugin.box.clearInput()`: Clears the input field.

These are implemented via new main process channel listeners: `core-box:set-input` and `core-box:clear-input`.

Additionally, this commit includes several significant refactorings and fixes:

- refactor(channel): Plugin lifecycle channel events are renamed for clarity (e.g., `@lifecycle:ac` is now `plugin:lifecycle:active`).
- refactor(renderer): Introduced a new `useClipboardChannel` composable to centralize clipboard-related channel listeners, preventing potential memory leaks and improving code organization.
- fix(core-box): The theme change mechanism for plugin UI views has been modified. Instead of broadcasting real-time updates, the theme is now sent once when the UI view is attached to prevent channel timeout errors.
- refactor(plugin-sdk): Implemented an `ensureRendererChannel` utility to make SDK hooks more robust against initialization race conditions.
Standardizes the method for obtaining the IPC send function across BoxSDK and DivisionBoxSDK. This change ensures the correct 'this' context is bound and provides a more explicit error message when a send function is unavailable.

Additionally, related IPC handlers in the core application have been simplified and cleaned up for consistency and readability.
Introduces the `useUrlProcessor` hook to manage custom URL schemes at application startup.

This enables the application to handle deep links and external protocol invocations, allowing for better integration with other services.
In the `WindowManager`, the `this` context was lost within the `Promise` and `setTimeout` callbacks of the `send` method for plugin channels. This could lead to runtime errors when accessing instance properties like `pendingMap`.

This commit resolves the issue by capturing the `this` instance in a local variable before the async operations, ensuring the correct context is maintained throughout the promise lifecycle.

Additionally, the `createBoxSDK` function was refactored to use a strongly-typed `ITouchClientChannel`, improving type safety and simplifying implementation.
…support

The IPC communication layer has been updated to fix incorrect channel type registration and improve support for asynchronous operations in handlers.

- Core-box IPC channels intended for plugin use are now correctly registered with the `PLUGIN` type instead of `MAIN`.
- The renderer-side channel implementation now properly awaits promises returned by handlers before sending a reply. This prevents race conditions where a response was sent before an asynchronous task was finished.
- The `sendToMain` call in the main process has been updated to match the revised channel API.
This enhances the clipboard history module by introducing comprehensive search, filtering, and sorting capabilities, making it easier for users and plugins to find specific items.

The `clipboard:get-history` endpoint now supports filtering by:
- Keyword (fuzzy search in content)
- Date range (startTime, endTime)
- Item type ('text', 'image', 'files')
- Favorite status
- Source application

The plugin SDK (`@talex-touch/utils`) is updated with a new `searchHistory` method in `useClipboardHistory` to expose this functionality to plugins.

BREAKING CHANGE: The data structure for the `onCoreBoxInputChange` hook has been changed from `{ query: string }` to `{ query: { inputs: any[], text: string } }` to provide richer context about the input state.
This commit refactors the input change communication pipeline to fix several critical bugs and improve system robustness. A new centralized `InputTransport` layer is introduced in both the main and renderer processes to standardize how input changes are broadcast.

Key fixes include:
- **Escape Key Logic:** The exit sequence on 'Escape' press is corrected to clear file/clipboard attachments before deactivating a provider's UI view. This prevents the view from closing while data is still attached.
- **Keyboard Event Capture:** The global `keydown` listener now uses the event capture phase, fixing a bug where hotkeys would not fire if the search input element had focus.
- **Plugin Communication:** Plugins now reliably receive events with the full query object, including when the input is cleared. The IPC channel is renamed to `core-box:input-change` for consistency.
This commit introduces several enhancements to the core box functionality to improve user experience and search accuracy.

- **Search Relevance:** The sorting algorithm now considers the `source.id` of features during a search. This significantly improves relevance, allowing English keywords (e.g., "clipboard") to match features whose display titles might be in other languages (e.g., "剪贴板历史").

- **Keyboard Navigation:** Arrow key navigation now cycles through the results list. When the user reaches the end of the list and presses `ArrowDown`, the focus wraps around to the first item, and vice versa for `ArrowUp`. This behavior is enabled for lists with 20 or fewer items to maintain UI performance.

- **Refactor:** The IPC transport layer between the main and renderer processes for core box inputs has been refactored for better structure and maintainability.
This commit introduces a more sophisticated search mechanism for plugin features to enhance discoverability and relevance.

Previously, search relied on basic substring matching against feature titles and source IDs. This change implements a token-based system to provide more intelligent results.

- Adds support for a `keywords` field in plugin feature definitions.
- Generates `searchTokens` (including keywords, Pinyin, and initials) for each feature upon registration.
- Updates the `tuff-sorter` to prioritize matches against these new tokens, significantly improving the ranking of relevant results for non-exact or Pinyin-based queries.
Previously, the CoreBox would attempt to autofill content from the clipboard every time it was shown. This could lead to unwanted behavior when opening the box via methods other than the global shortcut, such as clicking the tray icon.

This change introduces a mechanism to differentiate the trigger source. The autofill feature is now only activated when the CoreBox is explicitly opened with a keyboard shortcut.

This is achieved by:
- Passing a `triggeredByShortcut` flag through the show logic in the main process.
- Sending a `core-box:shortcut-triggered` IPC event to the renderer.
- Conditionally calling the autofill function in the renderer based on this event.
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 2, 2025

Warning

Rate limit exceeded

@TalexDreamSoul has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 12 minutes and 36 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between f162b43 and eb94d5f.

📒 Files selected for processing (16)
  • apps/core-app/src/main/modules/box-tool/core-box/ipc.ts (6 hunks)
  • apps/core-app/src/main/modules/box-tool/search-engine/sort/tuff-sorter.ts (4 hunks)
  • apps/core-app/src/main/modules/plugin/adapters/plugin-features-adapter.ts (14 hunks)
  • apps/core-app/src/main/modules/plugin/widget/processors/vue-processor.ts (1 hunks)
  • apps/core-app/src/main/modules/plugin/widget/widget-compiler.ts (1 hunks)
  • apps/core-app/src/main/modules/plugin/widget/widget-manager.ts (4 hunks)
  • apps/core-app/src/main/modules/plugin/widget/widget-processor.ts (1 hunks)
  • apps/core-app/src/renderer/src/components/plugin/layout/PluginItem.vue (1 hunks)
  • apps/core-app/src/renderer/src/env.d.ts (1 hunks)
  • apps/core-app/src/renderer/src/modules/box/adapter/transport/core-box-transport.ts (1 hunks)
  • apps/core-app/src/renderer/src/modules/box/adapter/transport/input-transport.ts (1 hunks)
  • apps/core-app/src/renderer/src/modules/channel/channel-core.ts (8 hunks)
  • apps/core-app/src/renderer/src/modules/hooks/useUrlProcessor.ts (1 hunks)
  • apps/core-app/src/renderer/src/modules/plugin/widget-registry.ts (3 hunks)
  • apps/docs/dev/api/keyboard.en.md (1 hunks)
  • plugins/touch-translation/widgets/TestWidget.vue (1 hunks)

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Adds CoreBox input/key transports and renderer transport factories, tracks shortcut-origin metadata, enhances plugin feature search tokens and sorter scoring, moves many channel interactions to typed renderer-safe channels, adds paginated clipboard search, and introduces widget processors and sandboxing for plugin widgets.

Changes

Cohort / File(s) Summary
CoreBox transports (main & renderer)
apps/core-app/src/main/modules/box-tool/core-box/input-transport.ts, apps/core-app/src/main/modules/box-tool/core-box/key-transport.ts, apps/core-app/src/main/modules/box-tool/core-box/transport/core-box-transport.ts, apps/core-app/src/renderer/src/modules/box/adapter/transport/input-transport.ts, apps/core-app/src/renderer/src/modules/box/adapter/transport/key-transport.ts, apps/core-app/src/renderer/src/modules/box/adapter/transport/core-box-transport.ts
Add main-side singleton transports and renderer-side transport factories for debounced/immediate core-box:input-change and key events; provide channel-like abstractions, registration helpers, and UI-state querying.
CoreBox manager/window/ipc & key forwarding
apps/core-app/src/main/modules/box-tool/core-box/manager.ts, apps/core-app/src/main/modules/box-tool/core-box/window.ts, apps/core-app/src/main/modules/box-tool/core-box/ipc.ts, apps/core-app/src/main/modules/box-tool/core-box/index.ts
Extend trigger APIs to accept TriggerOptions (triggeredByShortcut), forward shortcut metadata to UI, add helper to send input value to renderer, switch many core-box handlers to PLUGIN channels, and notify renderer on UI-mode exit.
Renderer hooks: input, search, keyboard, visibility, clipboard
apps/core-app/src/renderer/src/modules/box/adapter/hooks/useSearch.ts, useKeyboard.ts, useVisibility.ts, useClipboard.ts, useClipboardChannel.ts, index.ts, useChannel.ts
Introduce renderer-side input transport usage and broadcasting points, capture-phase keyboard listener with key-forwarding rules (including ESC reorder), track shortcut-triggered flag, centralize clipboard channel via useClipboardChannel (returns cleanup), and adjust channel reply typing.
Plugin SDK & channel safety (renderer helpers + Box SDK)
packages/utils/plugin/sdk/channel.ts, packages/utils/plugin/sdk/box-sdk.ts, packages/utils/plugin/sdk/feature-sdk.ts, packages/utils/plugin/sdk/hooks/*, packages/utils/plugin/sdk/division-box.ts, packages/utils/plugin/sdk/clipboard.ts, packages/utils/plugin/sdk/types.ts, packages/utils/plugin/sdk/README.md, packages/utils/plugin/sdk/enum/bridge-event.ts
Add ensureRendererChannel/useChannel helpers, replace direct window.$channel usage, add BoxSDK.setInput/clearInput, extend FeatureSDK with forwarded key events and onKeyEvent, add clipboard search types and APIs, and add bridge/core-box key-event enum.
Plugin core: features, adapters, lifecycle, API channel
apps/core-app/src/main/modules/plugin/plugin-feature.ts, apps/core-app/src/main/modules/plugin/adapters/feature-search-tokens.ts, apps/core-app/src/main/modules/plugin/adapters/plugin-features-adapter.ts, apps/core-app/src/main/modules/plugin/plugin-module.ts, apps/core-app/src/main/modules/plugin/plugin.ts
Add keywords/searchTokens on PluginFeature, implement buildFeatureSearchTokens (including pinyin tokens), persist searchTokens, add PluginFeaturesAdapter.handleActiveFeatureInput to route active-feature input to plugins, standardize lifecycle event names, and expose a boxChannel in plugin API.
Search engine / sorter
apps/core-app/src/main/modules/box-tool/search-engine/sort/tuff-sorter.ts, apps/core-app/src/main/modules/box-tool/search-engine/query-completion-service.ts
Add internal calculateMatchScore using normalized keys and tokens/sourceId boosts; normalize incoming query text; formatting and minor inline refactors in completion service.
Clipboard backend & renderer integration
apps/core-app/src/main/modules/clipboard.ts, apps/core-app/src/renderer/src/modules/box/adapter/hooks/useClipboard.ts, apps/core-app/src/renderer/src/modules/box/adapter/hooks/useClipboardChannel.ts, packages/utils/plugin/sdk/clipboard.ts, packages/utils/plugin/sdk/types.ts
Replace fixed-limit clipboard history with filterable, paginated clipboard:get-history; add renderer-side centralized clipboard channel hook, synchronous/async getters, apply-to-active-app helper, and SDK searchHistory wrapper/types.
Widget processing & sandboxing
apps/core-app/src/main/modules/plugin/widget/widget-processor.ts, apps/core-app/src/main/modules/plugin/widget/processors/vue-processor.ts, apps/core-app/src/main/modules/plugin/widget/widget-compiler.ts, apps/core-app/src/renderer/src/modules/plugin/widget-registry.ts, packages/utils/plugin/widget.ts
Introduce widget processor registry and CompiledWidget contract, add Vue SFC widget processor, switch compilation to processor-based flow, add legacy compatibility wrapper, and sandbox evaluateWidgetComponent with allowed dependencies; add optional widget dependencies payload.
Renderer CoreBox component lifecycle & cleanup
apps/core-app/src/renderer/src/views/box/CoreBox.vue
Remove old search watch emitting input-changed; consume new cleanup functions from useClipboard/useVisibility and call them on unmount; register UI-mode-exited listener to deactivate providers.
Channel/core behavior and touch channel updates
apps/core-app/src/main/core/channel-core.ts, apps/core-app/src/renderer/src/modules/channel/channel-core.ts
Minor formatting and single-line adjustments; renderer TouchChannel now handles promise-returning listeners (awaits results and replies with DataCode success/error) and TouchChannel registers IPC listener in constructor.
Miscellaneous: UI, storage, ocr, tray, icons, logs, packages
apps/core-app/src/main/modules/ocr/ocr-service.ts, apps/core-app/src/main/modules/download/concurrency-adjuster.ts, apps/core-app/src/main/utils/plugin-injection.ts, apps/core-app/src/renderer/src/components/base/TuffIcon.vue, apps/core-app/src/renderer/src/components/plugin/layout/PluginItem.vue, apps/core-app/src/renderer/src/modules/storage/prompt-library.ts, apps/core-app/src/renderer/src/modules/storage/division-box-storage.ts, apps/core-app/src/renderer/src/modules/division-box/store/division-box.ts, apps/core-app/src/renderer/src/modules/hooks/usePromptManager.ts, various package.json bumps, docs and new files`
Route clipboard-meta updates to plugin UI, reduce logging verbosity, remove a CSS border-radius, change TuffIcon colorful behavior, add debug log in PluginItem, add prompt-library and division-box storages, update prompt manager to use storage-backed prompts, simplify tray icon resolution, add docs for keyboard channels, and bump package versions.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Areas to focus review on:
    • CoreBox IPC/channel shifts (MAIN→PLUGIN) and sendInputValueToRenderer correctness.
    • Transport implementations and debounce behavior for input/key paths (main ↔ renderer).
    • PluginFeaturesAdapter.handleActiveFeatureInput and buildFeatureSearchTokens (pinyin generation and token deduplication).
    • Clipboard:get-history filtering/pagination (bounds, totals).
    • Widget processor sandboxing and dependency allowlist behavior.
    • Renderer hook lifecycle cleanup and keyboard-forwarding edge cases (ESC ordering, capture-phase listener).

Possibly related PRs

Poem

🐰
I hopped through channels, soft and fleet,
Debounced my paws so inputs meet,
Tokens and shortcuts in tidy rows,
Widgets sandboxed where safe wind blows,
Plugins hum — the box now grows! 🥕

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 47.76% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive The title accurately describes a major feature addition: new setInput and clearInput methods to BoxSDK. However, the changeset is substantially larger than just this SDK feature—it includes extensive CoreBox infrastructure improvements, input transport systems, keyboard event handling, clipboard refactoring, widget processing, and multiple renderer-side updates across many modules. Consider whether the title should reflect the broader scope of changes (e.g., 'feat: enhance CoreBox input handling and plugin SDK' or similar) to better represent all the infrastructure work, or clarify if this PR should be narrower in scope.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

The CoreBox will now only auto-fill content from the clipboard when it is activated via a keyboard shortcut. This prevents unwanted autopasting when opening the box through other means, providing a more predictable user experience.

This is implemented by passing a `triggeredByShortcut` flag from the main process shortcut handlers down to the renderer. The renderer uses this signal to conditionally trigger the auto-fill logic upon becoming visible.

Additionally, this commit includes:
- A refactor of the plugin Box SDK channel to ensure proper event listener cleanup.
- A minor style adjustment removing the border-radius from injected plugin views.
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

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: 10

Note

Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
apps/core-app/src/main/modules/download/concurrency-adjuster.ts (1)

116-123: Replace console.debug with the project's structured logger

console.debug on line 122 violates the ESLint no-console rule (only warn/error allowed) and the main-process guideline to use log4js-based structured logging. Use globalThis.logger, which is already configured in the main process:

  updateConcurrency(newConcurrency: number): void {
    const oldConcurrency = this.currentConcurrency
    this.currentConcurrency = Math.max(1, Math.min(10, newConcurrency))

    this.addToHistory(this.currentConcurrency)

-   console.debug(`Concurrency adjusted from ${oldConcurrency} to ${this.currentConcurrency}`)
+   globalThis.logger.debug(`Concurrency adjusted from ${oldConcurrency} to ${this.currentConcurrency}`)
  }
apps/core-app/src/main/modules/box-tool/core-box/ipc.ts (1)

180-193: Missing null check for coreBoxWindow.

Unlike core-box:hide-input (line 162-166) which validates coreBoxWindow before use, core-box:show-input uses the non-null assertion coreBoxWindow!.window without validation. This could cause a runtime exception if the window is unavailable.

     this.touchApp.channel.regChannel(ChannelType.PLUGIN, 'core-box:show-input', ({ reply }) => {
       const coreBoxWindow = getCoreBoxWindow()
+      if (!coreBoxWindow || coreBoxWindow.window.isDestroyed()) {
+        reply(DataCode.ERROR, { error: 'CoreBox window not available' })
+        return
+      }

       this.touchApp.channel
-        .sendTo(coreBoxWindow!.window, ChannelType.MAIN, 'core-box:set-input-visibility', {
+        .sendTo(coreBoxWindow.window, ChannelType.MAIN, 'core-box:set-input-visibility', {
           visible: true
         })
apps/core-app/src/main/modules/plugin/plugin-module.ts (1)

301-305: Main process lifecycle events incompatible with SDK hook listeners—breaks plugin lifecycle integration

The lifecycle event names sent from main process (plugin:lifecycle:inactive, plugin:lifecycle:active, plugin:lifecycle:crashed) do not match what the SDK hook system listens for. The SDK registers listeners for @lifecycle:in, @lifecycle:ac, @lifecycle:cr (from LifecycleHooks enum in packages/utils/plugin/sdk/hooks/life-cycle.ts:28). Plugins using onPluginActive(), onPluginInactive(), onPluginEnable(), onPluginDisable(), and onCrash() hooks will not receive these lifecycle events.

Either update the main process to send @lifecycle:ac/@lifecycle:in/@lifecycle:cr events on the PLUGIN channel, or update the SDK to listen for the new plugin:lifecycle:* event names.

🟡 Minor comments (12)
apps/core-app/src/renderer/src/modules/hooks/application-hooks.ts-23-25 (1)

23-25: ESLint: style/brace-style violations.

Closing curly braces should not appear on the same line as subsequent blocks (} else {). The project's linting rules require each brace on its own line.

-      } else {
+      }
+      else {

Apply similar fixes at lines 126 and 128.

Also applies to: 126-130

apps/core-app/src/renderer/src/modules/hooks/application-hooks.ts-17-18 (1)

17-18: Regex uses unused capturing groups and violates operator linebreak rule.

The regex defines 4 capturing groups that are never used. Use non-capturing groups (?:...) instead. Additionally, the = operator should be placed at the beginning of the line per style/operator-linebreak.

-      const regex =
-        /(^https:\/\/localhost)|(^http:\/\/localhost)|(^http:\/\/127\.0\.0\.1)|(^https:\/\/127\.0\.0\.1)/
+      const regex
+        = /(?:^https:\/\/localhost)|(?:^http:\/\/localhost)|(?:^http:\/\/127\.0\.0\.1)|(?:^https:\/\/127\.0\.0\.1)/

Or simplify further:

const regex = /^https?:\/\/(?:localhost|127\.0\.0\.1)/
apps/core-app/src/renderer/src/modules/hooks/application-hooks.ts-11-11 (1)

11-11: ESLint: antfu/if-newline violations detected.

The linter requires a newline after if statements before the return/body. These single-line if statements violate the project's style rules.

Apply this pattern to fix (example for line 11):

-      if (target.getAttribute('ignoreSafeCheck') === 'true') return
+      if (target.getAttribute('ignoreSafeCheck') === 'true')
+        return

Similar fixes needed for lines 15, 81, and 122.

Also applies to: 15-15, 81-81, 122-122

apps/core-app/src/renderer/src/modules/hooks/application-hooks.ts-121-121 (1)

121-121: ESLint: Missing semicolon in type annotation.

The linter expects a semicolon delimiter in the type annotation per style/member-delimiter-style.

-    ({ data }: { data?: { type: string; data: string } }) => {
+    ({ data }: { data?: { type: string; data: string }; }) => {
apps/core-app/src/renderer/src/modules/box/adapter/hooks/useChannel.ts-7-7 (1)

7-7: Remove debug console.log statement.

This violates the ESLint rule and coding guidelines. As per coding guidelines, use log4js for structured logging if this information is needed for debugging.

Apply this diff to remove the debug statement:

-  console.log('useChannel', boxOptions)
-
apps/core-app/src/renderer/src/modules/box/adapter/hooks/index.ts-4-4 (1)

4-4: New clipboard channel exports are fine; sort names to satisfy ESLint

The re‑exports look correct. To satisfy the perfectionist/sort-named-exports rule, you can reorder the names:

-export { useClipboardChannel, CLIPBOARD_CHANNELS, type ClipboardChannelHandlers, type ClipboardMetaUpdate } from './useClipboardChannel'
+export {
+  CLIPBOARD_CHANNELS,
+  useClipboardChannel,
+  type ClipboardChannelHandlers,
+  type ClipboardMetaUpdate,
+} from './useClipboardChannel'
packages/utils/plugin/sdk/division-box.ts-14-15 (1)

14-15: Channel selection helper is fine; fix operator‑linebreak to satisfy ESLint

The send wrapper correctly prefers sendToMain and falls back to send, with a clear error if neither is available. useDivisionBox using ensureRendererChannel is also consistent with the new SDK pattern.

To address the style/operator-linebreak warning on Line 184, you can rewrite the declaration as:

-  const send: (eventName: string, payload?: any) => Promise<any> =
-    typeof channel?.sendToMain === 'function'
+  const send: (eventName: string, payload?: any) => Promise<any>
+    = typeof channel?.sendToMain === 'function'
       ? channel.sendToMain.bind(channel)
       : typeof channel?.send === 'function'
         ? channel.send.bind(channel)
         : (() => {
             throw new Error('[DivisionBox SDK] Channel send function not available')
           })()

This should keep behavior identical while satisfying the lint rule.

Also applies to: 184-191, 196-207, 221-245, 263-265

apps/core-app/src/main/modules/box-tool/core-box/transport/core-box-transport.ts-17-25 (1)

17-25: Missing unregister mechanism may cause memory leaks.

The register method calls regChannel but discards the returned unregister function. Per the coding guidelines, regChannel returns () => void to unregister the channel. Without exposing this, handlers cannot be cleaned up when no longer needed.

-  public register<TPayload>(
+  public register<TPayload>(
     channelType: ChannelType,
     event: string,
     handler: Handler<TPayload>
-  ): void {
-    this.touchApp.channel.regChannel(channelType, event, ({ data }) => {
+  ): () => void {
+    return this.touchApp.channel.regChannel(channelType, event, ({ data }) => {
       handler(data as TPayload)
     })
   }

Committable suggestion skipped: line range outside the PR's diff.

apps/core-app/src/main/modules/box-tool/search-engine/sort/tuff-sorter.ts-148-162 (1)

148-162: Replace console.log with the project's logger.

ESLint reports that only console.warn and console.error are allowed. Since this is debug-level logging, use the project's createLogger utility instead, consistent with other modules in this codebase.

+import { createLogger } from '../../../utils/logger'
+
+const log = createLogger('TuffSorter')
+
 // In calculateSortScore function:
-  if (item.kind === 'feature' && searchKey) {
-    console.log('[TuffSorter]', {
-      title: item.render.basic?.title,
-      ...
-    })
-  }
+  if (item.kind === 'feature' && searchKey) {
+    log.debug('Feature item scoring', {
+      meta: {
+        title: item.render.basic?.title,
+        kind: item.kind,
+        searchKey,
+        sourceId: item.source?.id,
+        weight,
+        matchScore,
+        recency,
+        frequency,
+        finalScore,
+      }
+    })
+  }

Committable suggestion skipped: line range outside the PR's diff.

apps/core-app/src/main/modules/box-tool/search-engine/query-completion-service.ts-39-39 (1)

39-39: Fix ESLint style violations in this file.

ESLint reports 27 style errors in this file (all auto-fixable):

  • antfu/if-newline: Newline required after if statements (lines 39, 98, 152, 158, 168)
  • style/operator-linebreak: Operators should be at line start (lines 59, 84, 85, 188, 189)
  • style/brace-style: Closing braces misplaced (lines 70, 91, 144, 195, 219)
  • style/comma-dangle: Missing trailing commas (lines 27, 53, 67, 78, 89, 113, 136, 141, 173, 193, 215)
  • style/arrow-parens: Unnecessary parentheses in arrow function (line 160)

Run:

npx eslint --fix apps/core-app/src/main/modules/box-tool/search-engine/query-completion-service.ts
packages/utils/plugin/sdk/hooks/bridge.ts-68-68 (1)

68-68: Breaking change in onCoreBoxInputChange type signature.

The type parameter changed from { query: string } to { query: { inputs: Array<any>, text: string } }. This is a breaking change for existing plugin consumers.

Consider:

  1. Adding migration notes in the PR description or changelog
  2. Using a more specific type for inputs instead of Array<any> (e.g., TuffQueryInput[] from @talex-touch/utils)
-export const onCoreBoxInputChange = createBridgeHook<{ query: { inputs: Array<any>, text: string } }>(BridgeEventForCoreBox.CORE_BOX_INPUT_CHANGE)
+export const onCoreBoxInputChange = createBridgeHook<{ query: TuffQuery }>(BridgeEventForCoreBox.CORE_BOX_INPUT_CHANGE)

This would require importing TuffQuery from @talex-touch/utils and would provide better type safety. Based on learnings, plugins should use TuffInputType enum values when handling clipboard data.

Committable suggestion skipped: line range outside the PR's diff.

apps/core-app/src/renderer/src/modules/box/adapter/hooks/useSearch.ts-17-17 (1)

17-17: Add cleanup mechanism for the input transport's debounce timer.

The inputTransport instance created at module scope holds a debounced timer via useDebounceFn. When the composable is destroyed or called multiple times in different components, pending timers can accumulate without being cleared, causing memory leaks and potential race conditions.

Wrap the transport cleanup in an onUnmounted hook:

onUnmounted(() => {
  // Clear any pending debounced invocations
  inputTransport.broadcast.cancel?.()
})

Or consider moving the transport creation inside onMounted to ensure proper lifecycle management.

🧹 Nitpick comments (29)
apps/core-app/src/renderer/src/modules/box/adapter/hooks/useChannel.ts (1)

4-4: Reorder imports to follow ESLint convention.

External package imports should precede relative parent imports.

Apply this diff to fix the import order:

 import type { Ref } from 'vue'
 import { touchChannel } from '~/modules/channel/channel-core'
-import { BoxMode } from '../types'
 import { DataCode } from '@talex-touch/utils'
+import { BoxMode } from '../types'
apps/core-app/src/main/modules/download/concurrency-adjuster.ts (1)

44-45: Optionally centralize concurrency bounds into a shared constant

The min/max concurrency bounds (1 and 10) are duplicated in multiple places (Lines 44–45, 118–119, 215–216). Not a bug, but extracting them to named constants would reduce drift risk and clarify intent:

 export class ConcurrencyAdjuster {
+  private static readonly MIN_CONCURRENCY = 1
+  private static readonly MAX_CONCURRENCY = 10
@@
-    return Math.max(1, Math.min(10, recommendedConcurrency))
+    return Math.max(
+      ConcurrencyAdjuster.MIN_CONCURRENCY,
+      Math.min(ConcurrencyAdjuster.MAX_CONCURRENCY, recommendedConcurrency),
+    )
@@
-    this.currentConcurrency = Math.max(1, Math.min(10, newConcurrency))
+    this.currentConcurrency = Math.max(
+      ConcurrencyAdjuster.MIN_CONCURRENCY,
+      Math.min(ConcurrencyAdjuster.MAX_CONCURRENCY, newConcurrency),
+    )
@@
-    this.config.concurrency.maxConcurrent = Math.max(1, Math.min(10, maxConcurrency))
+    this.config.concurrency.maxConcurrent = Math.max(
+      ConcurrencyAdjuster.MIN_CONCURRENCY,
+      Math.min(ConcurrencyAdjuster.MAX_CONCURRENCY, maxConcurrency),
+    )

Purely a readability/maintainability improvement; fine to defer if out of scope for this PR.

Also applies to: 118-119, 215-216

apps/core-app/src/main/modules/ocr/ocr-service.ts (1)

990-990: Remove extra blank line.

Per ESLint: more than 1 blank line not allowed.

     }
   }
-

 
   private async upsertConfig(key: string, value: unknown): Promise<void> {
apps/core-app/src/main/modules/box-tool/core-box/ipc.ts (2)

8-8: Import ordering issue.

Per ESLint, "./input-transport" should come before "./manager" alphabetically.

 import searchEngineCore from '../search-engine/search-core'
+import { coreBoxInputTransport } from './input-transport'
 import { coreBoxManager } from './manager'
-import { coreBoxInputTransport } from './input-transport'
 import { getCoreBoxWindow, windowManager } from './window'

208-208: Brace style formatting.

Per ESLint, closing curly braces should not appear on the same line as subsequent blocks. This applies to lines 208, 222, 235, and 246.

-        } catch (error: any) {
+        }
+        catch (error: any) {
apps/core-app/src/main/modules/clipboard.ts (2)

963-976: Add null guards for this.db in IPC handlers.

The set-favorite and delete-item handlers use this.db! without first checking if this.db exists. While get-history handler (line 880) correctly guards against null, these handlers do not, which could cause runtime errors if called before initialization.

       touchChannel.regChannel(type, 'clipboard:set-favorite', async ({ data, reply }) => {
+        if (!this.db) {
+          reply(DataCode.ERROR, null)
+          return
+        }
         const { id, isFavorite } = data ?? {}
-        await this.db!.update(clipboardHistory)
-          .set({ isFavorite })
-          .where(eq(clipboardHistory.id, id))
+        await this.db.update(clipboardHistory)
+          .set({ isFavorite })
+          .where(eq(clipboardHistory.id, id))
         reply(DataCode.SUCCESS, null)
       })

       touchChannel.regChannel(type, 'clipboard:delete-item', async ({ data, reply }) => {
+        if (!this.db) {
+          reply(DataCode.ERROR, null)
+          return
+        }
         const { id } = data ?? {}
-        await this.db!.delete(clipboardHistory).where(eq(clipboardHistory.id, id))
+        await this.db.delete(clipboardHistory).where(eq(clipboardHistory.id, id))
         this.memoryCache = this.memoryCache.filter((item) => item.id !== id)
         reply(DataCode.SUCCESS, null)
       })

978-983: Add null guard for this.db in clear-history handler.

Same issue as above - this.db! is used without a null check.

       touchChannel.regChannel(type, 'clipboard:clear-history', async ({ reply }) => {
+        if (!this.db) {
+          reply(DataCode.ERROR, null)
+          return
+        }
         const oneHourAgo = new Date(Date.now() - CACHE_MAX_AGE_MS)
-        await this.db!.delete(clipboardHistory).where(gt(clipboardHistory.timestamp, oneHourAgo))
+        await this.db.delete(clipboardHistory).where(gt(clipboardHistory.timestamp, oneHourAgo))
         this.memoryCache = []
         reply(DataCode.SUCCESS, null)
       })
apps/core-app/src/main/modules/plugin/plugin-feature.ts (1)

81-82: Optionally wire searchTokens through the constructor

You’ve added searchTokens?: string[] on the class but don’t assign it from options. If any caller ever passes precomputed tokens, they’ll be dropped.

Consider also copying it in the constructor:

  constructor(pluginPath: string, options: IPluginFeature, dev: IPluginDev) {
    this.id = options.id
    this.name = options.name
    this.desc = options.desc
    this.icon = new TuffIconImpl(pluginPath, options.icon.type, options.icon.value)
    this.keywords = options.keywords
+   this.searchTokens = options.searchTokens
    this.push = options.push
    this.platform = options.platform

Leaving searchTokens out of toJSONObject() still makes sense if it’s meant to remain internal.

Also applies to: 88-89, 95-96, 118-124

apps/core-app/src/renderer/src/modules/box/adapter/hooks/useKeyboard.ts (1)

60-77: Keyboard navigation and ESC sequencing changes look correct; watch brace‑style lint

The updated ArrowUp/ArrowDown logic correctly wraps focus only for small result sets (≤20), while preserving the previous clamp behavior for larger lists. The new ESC flow (attachments → activations → input → exit) matches the comment and should avoid leaving clipboard/file attachments behind when dismissing providers.

Using a capture‑phase keydown listener with a matching removal call is also appropriate to ensure CoreBox receives keyboard events even when the input has focus.

If your ESLint config enforces a specific brace-style, you may need to reformat the else branches (e.g., Lines 64 and 74) to avoid style warnings, but that’s purely cosmetic.

Also applies to: 122-168, 208-222

apps/core-app/src/main/modules/box-tool/core-box/transport/core-box-transport.ts (1)

3-3: Use import type for type-only imports.

The TouchApp import is only used as a type annotation, not as a value. As per coding guidelines and the ESLint hint, use import type for consistency.

-import { TouchApp } from '../../../../core/touch-app'
+import type { TouchApp } from '../../../../core/touch-app'
apps/core-app/src/main/modules/box-tool/core-box/input-transport.ts (2)

5-6: Fix import order.

ESLint reports that ./transport/core-box-transport should come before ./window. Reorder imports for consistency with the project's import sorting rules.

 import { createLogger } from '../../../utils/logger'
 import pluginFeaturesAdapter from '../../plugin/adapters/plugin-features-adapter'
-import { windowManager } from './window'
 import { coreBoxTransport } from './transport/core-box-transport'
+import { windowManager } from './window'

26-34: Consider capturing the unregister function for cleanup.

If coreBoxTransport.register returns an unregister function (as suggested in the review of core-box-transport.ts), this method should expose or store it to allow proper cleanup during module destruction.

-  public register(): void {
-    coreBoxTransport.register<CoreBoxInputChange>(
+  public register(): () => void {
+    return coreBoxTransport.register<CoreBoxInputChange>(
       ChannelType.MAIN,
       'core-box:input-change',
       (data) => {
         this.handleRendererInput(data)
       }
     )
   }
apps/core-app/src/renderer/src/modules/box/adapter/transport/input-transport.ts (1)

10-12: Consider consolidating ChannelLike interface.

This ChannelLike interface is also defined in core-box-transport.ts. Consider extracting it to a shared location to avoid duplication and ensure consistency.

apps/core-app/src/main/modules/box-tool/search-engine/sort/tuff-sorter.ts (1)

42-76: Score ordering appears intentional but may need documentation.

Token startsWith returns 800, while source.id startsWith returns 850. This gives source.id prefix matching higher priority than token prefix matching, which may be intentional for English→Chinese feature searches. Consider adding a brief comment explaining this priority choice to help future maintainers.

apps/core-app/src/renderer/src/modules/box/adapter/hooks/useSearch.ts (1)

143-143: Minor style inconsistency flagged by linter.

ESLint reports brace-style and operator-linebreak issues. While these don't affect functionality, they should be addressed for consistency.

Apply this diff to align with the project's style rules:

-      } else if (boxOptions.mode === BoxMode.FILE && boxOptions.file?.paths?.length > 0) {
+      }
+      else if (boxOptions.mode === BoxMode.FILE && boxOptions.file?.paths?.length > 0) {
-      } else if (
-        clipboardOptions?.last?.type === 'text' ||
-        clipboardOptions?.last?.type === 'html'
+      }
+      else if (
+        clipboardOptions?.last?.type === 'text'
+        || clipboardOptions?.last?.type === 'html'
       ) {

Also applies to: 155-158

packages/utils/plugin/sdk/hooks/bridge.ts (1)

2-2: Import order issue.

ESLint reports that ../channel should come before ../enum/bridge-event per the perfectionist/sort-imports rule.

+import { ensureRendererChannel } from '../channel'
 import { BridgeEventForCoreBox } from '../enum/bridge-event'
-import { ensureRendererChannel } from '../channel'
apps/core-app/src/renderer/src/modules/box/adapter/transport/core-box-transport.ts (2)

23-28: Remove unnecessary eslint-disable comment.

The comment // eslint-disable-next-line @typescript-eslint/no-var-requires references a rule that doesn't apply here since useDebounceFn is imported at the top of the file via ES modules, not require(). The static analysis confirms the rule definition wasn't found.

   const maybeDebounce = <T extends (...args: any[]) => void>(fn: T): T => {
-    if (!debounceMs) return fn
-    // eslint-disable-next-line @typescript-eslint/no-var-requires
-    return useDebounceFn(fn, debounceMs) as unknown as T
+    if (!debounceMs)
+      return fn
+    return useDebounceFn(fn, debounceMs) as unknown as T
   }

32-36: Minor style adjustment for brace placement.

ESLint flags the brace style at line 34.

     channel.send(event, payload).catch((error: unknown) => {
       if (onError) {
         onError(error)
-      } else {
+      }
+      else {
         console.error(`[coreBoxTransport] Failed to send ${event}:`, error)
       }
     })
apps/core-app/src/renderer/src/modules/channel/channel-core.ts (1)

122-124: Multiple style issues flagged by ESLint.

These are formatting issues (brace-style, if-newline) that don't affect functionality but should be addressed for consistency with project style guidelines.

Consider running the project's linter auto-fix to resolve these style issues:

npx eslint --fix apps/core-app/src/renderer/src/modules/channel/channel-core.ts

Also applies to: 138-138, 143-143, 169-169, 185-185, 218-218, 221-221

apps/core-app/src/main/modules/plugin/adapters/plugin-features-adapter.ts (1)

21-22: Import order lint error.

ESLint flags that "../../../core" should come before "../view/plugin-view-loader". This is a minor style issue that can be addressed when convenient.

 import { pluginModule } from '../plugin-module'
 
+import { genTouchApp } from '../../../core'
 import { PluginViewLoader } from '../view/plugin-view-loader'
-import { genTouchApp } from '../../../core'
 import { buildFeatureSearchTokens } from './feature-search-tokens'
apps/core-app/src/main/modules/plugin/adapters/feature-search-tokens.ts (2)

1-7: Well-designed tokenization utility.

The regex patterns are well-chosen:

  • CHINESE_CHAR_REGEX correctly matches CJK unified ideographs
  • CAMEL_BOUNDARY properly splits camelCase words
  • WORD_SEPARATORS handles common separators

The import order lint error (type import should come before value import) can be addressed for consistency.

+import type { IPluginFeature } from '@talex-touch/utils/plugin'
 import { pinyin } from 'pinyin-pro'
-import type { IPluginFeature } from '@talex-touch/utils/plugin'

14-23: Note: Similar splitWords exists in search-index-service.ts.

There's a splitWords method in search-index-service.ts (lines 328-333). This implementation differs by handling CamelCase boundaries (CAMEL_BOUNDARY), which is appropriate for feature names. Consider whether consolidating these into a shared utility would reduce duplication, though the different requirements may justify separate implementations.

apps/core-app/src/renderer/src/modules/box/adapter/hooks/useVisibility.ts (2)

32-39: Shortcut trigger detection mechanism.

The wasTriggeredByShortcut flag and channel listener provide a way to distinguish between keyboard-triggered and other CoreBox activations. This enables conditional auto-fill behavior.

However, ESLint flags console.debug as not allowed. Consider using a structured logger or removing the debug statement if not needed in production.

  const unregisterShortcutTrigger = touchChannel.regChannel('core-box:shortcut-triggered', () => {
-   console.debug('[Visibility] CoreBox triggered by keyboard shortcut')
    wasTriggeredByShortcut.value = true
  })

99-107: Conditional auto-fill based on trigger source.

The logic correctly restricts auto-fill to shortcut-triggered activations, resetting the flag afterward. This prevents unexpected auto-fill when CoreBox is opened through other means (e.g., clicking).

The else if on line 105 has a linting brace-style issue and a debug statement. Consider adjusting:

        // Reset flag after auto-filling
        wasTriggeredByShortcut.value = false
-     } else if (clipboardOptions.last) {
-       console.debug('[Visibility] Skipping auto-fill (not triggered by shortcut)')
      }
packages/utils/plugin/sdk/channel.ts (1)

16-26: Consider adding HMR handling to prevent stale cache references during development.

ensureRendererChannel properly handles SSR and provides a sensible fallback mechanism. However, cachedWindowChannel persists at module scope and is never cleared—during hot module replacement in development, if the channel instance changes, the cached reference becomes stale. While the primary check (globalWindow?.$channel) mitigates this in most scenarios, adding explicit HMR cleanup would improve robustness:

For Vite, consider:

if (import.meta.hot) {
  import.meta.hot.dispose(() => {
    cachedWindowChannel = null
  })
}

This ensures the cache is cleared on module replacement, allowing the next call to re-fetch the current channel instance.

apps/core-app/src/main/modules/box-tool/core-box/window.ts (1)

22-22: Fix import order for consistency.

The import statement for CoreBoxInputChange should come before ./manager to satisfy the import ordering rules.

 import { coreBoxManager } from './manager'
-import type { CoreBoxInputChange } from './input-transport'
+import type { CoreBoxInputChange } from './input-transport'

Move this import before line 21 (before ./manager import).

apps/core-app/src/renderer/src/modules/box/adapter/hooks/useClipboard.ts (1)

258-259: Consider static import over dynamic import for hot path.

Using dynamic import() for applyClipboardToActiveApp adds latency on each call. Since this module is already importing from ./useClipboardChannel at the top of the file, consider importing applyClipboardToActiveApp statically to avoid the async overhead.

-import { getLatestClipboardSync, useClipboardChannel } from './useClipboardChannel'
+import { applyClipboardToActiveApp, getLatestClipboardSync, useClipboardChannel } from './useClipboardChannel'

Then simplify the function:

   async function applyToActiveApp(item?: IClipboardItem): Promise<boolean> {
     const target = item ?? clipboardOptions.last
     if (!target) {
       return false
     }

     try {
-      const { applyClipboardToActiveApp } = await import('./useClipboardChannel')
       return await applyClipboardToActiveApp(target)
     }
     catch (error) {
       console.error('[Clipboard] Failed to apply to active app:', error)
       return false
     }
   }
apps/core-app/src/main/modules/plugin/plugin.ts (2)

17-17: Fix import order for type imports.

Per ESLint hint, the type import for ITouchClientChannel and StandardChannelData should come before the value import from the same module. Consider restructuring:

-import { ChannelType } from '@talex-touch/utils/channel'
-import type { ITouchClientChannel, StandardChannelData } from '@talex-touch/utils/channel'
+import type { ITouchClientChannel, StandardChannelData } from '@talex-touch/utils/channel'
+import { ChannelType } from '@talex-touch/utils/channel'

164-168: Minor style: Consider restructuring the conditional.

Per ESLint hints, the && operator spanning multiple lines should have the operator at the beginning of lines. However, this is a minor style issue.

-    channel &&
-      channel.send(ChannelType.MAIN, 'plugin-status-updated', {
-        plugin: this.name,
-        status: this._status
-      })
+    channel
+      && channel.send(ChannelType.MAIN, 'plugin-status-updated', {
+        plugin: this.name,
+        status: this._status,
+      })

The `TuffIcon` component's colorful variant now correctly uses `currentColor` instead of `unset` for its color and background, ensuring more reliable rendering.

The `PluginItem` icon now utilizes the `colorful` prop and includes a `dark:text-white` class to maintain visibility in dark mode.
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: 2

🧹 Nitpick comments (2)
apps/core-app/src/renderer/src/components/base/TuffIcon.vue (1)

120-123: Color variable fallback for colorful icons looks good

Using var(--icon-color, currentColor) for both color and background-color makes the icon tint configurable while keeping a safe fallback to the surrounding text color when --icon-color is not provided. This change is consistent with the mask-based rendering used by .TuffIcon-Svg and should not introduce regressions.

As a longer-term cleanup (not required for this PR), you might consider whether these SCSS rules could eventually be expressed via UnoCSS utilities to better align with the repo’s styling direction. Based on learnings, this is optional here.

apps/core-app/src/renderer/src/components/plugin/layout/PluginItem.vue (1)

67-74: Icon theming and colorful usage look consistent

The added dark:text-white class and colorful prop on <TuffIcon> fit the dark‑mode + colorful icon behavior and keep the component API simple. No issues from a correctness standpoint.

If colorful is only meaningful when plugin.icon is present, you could optionally gate it (:colorful="!!plugin.icon") to avoid unnecessary prop handling, but this is non‑blocking.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 586703b and 317e203.

📒 Files selected for processing (3)
  • apps/core-app/src/renderer/src/components/base/TuffIcon.vue (1 hunks)
  • apps/core-app/src/renderer/src/components/plugin/layout/PluginItem.vue (2 hunks)
  • apps/core-app/src/renderer/src/modules/box/adapter/transport/core-box-transport.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
apps/core-app/src/renderer/src/**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (CLAUDE.md)

apps/core-app/src/renderer/src/**/*.{ts,tsx,vue}: Implement Vue 3 components with TypeScript in the renderer process. Organize components in src/components/, view layouts in src/views/, and state management via Pinia stores and composables in src/modules/hooks/.
Use Pinia stores and composables in src/modules/hooks/ for state management in the renderer process instead of local component state.
Use Vue Router 4.5.1 for client-side routing in the renderer application.

apps/core-app/src/renderer/src/**/*.{ts,tsx,vue}: Use Pinia stores and composables in src/modules/hooks/ for state management in renderer process Vue components
Use Vue 3, TypeScript, Pinia for state management, and UnoCSS for styling in renderer process

Files:

  • apps/core-app/src/renderer/src/components/plugin/layout/PluginItem.vue
  • apps/core-app/src/renderer/src/components/base/TuffIcon.vue
  • apps/core-app/src/renderer/src/modules/box/adapter/transport/core-box-transport.ts
apps/core-app/src/renderer/src/**/*.vue

📄 CodeRabbit inference engine (CLAUDE.md)

Use Element Plus 2.10.4+ for UI components in the renderer process.

Files:

  • apps/core-app/src/renderer/src/components/plugin/layout/PluginItem.vue
  • apps/core-app/src/renderer/src/components/base/TuffIcon.vue
apps/core-app/src/renderer/src/**/*.{vue,ts,tsx,css,scss}

📄 CodeRabbit inference engine (CLAUDE.md)

Use UnoCSS 66.3.3+ for utility-first CSS styling instead of traditional CSS frameworks.

Files:

  • apps/core-app/src/renderer/src/components/plugin/layout/PluginItem.vue
  • apps/core-app/src/renderer/src/components/base/TuffIcon.vue
  • apps/core-app/src/renderer/src/modules/box/adapter/transport/core-box-transport.ts
apps/core-app/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

apps/core-app/src/**/*.{ts,tsx}: Use log4js for logging with structured namespaces, timestamps, and colored output. Provide meaningful namespace identifiers for debugging.
Import and use shared types and utilities from @talex-touch/utils package. Use enums like TuffInputType, TalexEvents, and ChannelType from the shared package.

Files:

  • apps/core-app/src/renderer/src/modules/box/adapter/transport/core-box-transport.ts
apps/core-app/src/renderer/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use Pinia 3.0.3 for state management in the renderer application.

Files:

  • apps/core-app/src/renderer/src/modules/box/adapter/transport/core-box-transport.ts
apps/core-app/src/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Import shared types and utilities from @talex-touch/utils package in plugins and application code

Files:

  • apps/core-app/src/renderer/src/modules/box/adapter/transport/core-box-transport.ts
🧠 Learnings (8)
📚 Learning: 2025-11-29T07:45:45.435Z
Learnt from: CR
Repo: talex-touch/tuff PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-29T07:45:45.435Z
Learning: Applies to apps/core-app/src/renderer/src/**/*.vue : Use Element Plus 2.10.4+ for UI components in the renderer process.

Applied to files:

  • apps/core-app/src/renderer/src/components/plugin/layout/PluginItem.vue
📚 Learning: 2025-11-29T07:45:45.435Z
Learnt from: CR
Repo: talex-touch/tuff PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-29T07:45:45.435Z
Learning: Applies to apps/core-app/src/renderer/src/**/*.{vue,ts,tsx,css,scss} : Use UnoCSS 66.3.3+ for utility-first CSS styling instead of traditional CSS frameworks.

Applied to files:

  • apps/core-app/src/renderer/src/components/base/TuffIcon.vue
📚 Learning: 2025-11-29T07:46:02.249Z
Learnt from: CR
Repo: talex-touch/tuff PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-29T07:46:02.249Z
Learning: Applies to apps/core-app/src/main/modules/storage/**/*.ts : Storage module broadcasts updates to all windows to maintain UI sync across multiple renderer instances

Applied to files:

  • apps/core-app/src/renderer/src/modules/box/adapter/transport/core-box-transport.ts
📚 Learning: 2025-11-29T07:46:02.249Z
Learnt from: CR
Repo: talex-touch/tuff PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-29T07:46:02.249Z
Learning: Applies to apps/core-app/src/main/**/*.ts : Register IPC channels using `regChannel(type: ChannelType, eventName: string, callback)` and send messages via `send()`, `sendTo()`, or `sendPlugin()` methods

Applied to files:

  • apps/core-app/src/renderer/src/modules/box/adapter/transport/core-box-transport.ts
📚 Learning: 2025-11-29T07:45:45.435Z
Learnt from: CR
Repo: talex-touch/tuff PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-29T07:45:45.435Z
Learning: Applies to apps/core-app/src/main/modules/box-tool/**/*.{ts,tsx} : Position CoreBox windows screen-aware using cursor position to select the appropriate display in multi-monitor setups.

Applied to files:

  • apps/core-app/src/renderer/src/modules/box/adapter/transport/core-box-transport.ts
📚 Learning: 2025-11-29T07:45:45.435Z
Learnt from: CR
Repo: talex-touch/tuff PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-29T07:45:45.435Z
Learning: Applies to apps/core-app/src/**/*.{ts,tsx} : Import and use shared types and utilities from talex-touch/utils package. Use enums like TuffInputType, TalexEvents, and ChannelType from the shared package.

Applied to files:

  • apps/core-app/src/renderer/src/modules/box/adapter/transport/core-box-transport.ts
📚 Learning: 2025-11-29T07:45:45.435Z
Learnt from: CR
Repo: talex-touch/tuff PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-29T07:45:45.435Z
Learning: Applies to apps/core-app/src/main/**/*.{ts,tsx} : Use TouchWindow wrapper for window creation instead of directly using Electron BrowserWindow. Enable platform-specific effects: Vibrancy on macOS and Mica on Windows.

Applied to files:

  • apps/core-app/src/renderer/src/modules/box/adapter/transport/core-box-transport.ts
📚 Learning: 2025-11-29T07:46:02.249Z
Learnt from: CR
Repo: talex-touch/tuff PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-29T07:46:02.249Z
Learning: Applies to apps/core-app/src/main/modules/**/*.ts : In main process architecture, inherit from BaseModule with required `onInit()` and `onDestroy()` methods, and optional `created()`, `start()`, and `stop()` lifecycle methods

Applied to files:

  • apps/core-app/src/renderer/src/modules/box/adapter/transport/core-box-transport.ts
🧬 Code graph analysis (1)
apps/core-app/src/renderer/src/modules/box/adapter/transport/core-box-transport.ts (1)
packages/utils/channel/index.ts (2)
  • ITouchClientChannel (100-133)
  • ChannelType (1-4)
🪛 ESLint
apps/core-app/src/renderer/src/modules/box/adapter/transport/core-box-transport.ts

[error] 1-1: All imports in the declaration are only used as types. Use import type.

(ts/consistent-type-imports)


[error] 21-21: Expect newline after if

(antfu/if-newline)


[error] 30-30: Closing curly brace appears on the same line as the subsequent block.

(style/brace-style)

🔇 Additional comments (1)
apps/core-app/src/renderer/src/modules/box/adapter/transport/core-box-transport.ts (1)

14-40: CoreBox transport abstraction and debounce wiring look solid

The generic createCoreBoxTransport shape, optional debounce wrapper, and fire‑and‑forget dispatch API are cohesive and align well with the channel contract; no functional issues stand out here.

TalexDreamSoul and others added 8 commits December 3, 2025 18:46
… execution

This commit introduces a major overhaul of the plugin widget system to improve extensibility, security, and developer experience.

- **Processor-based Compilation:** The widget compiler is refactored to use a processor registry. This decouples the compilation logic from a specific file type (Vue SFC) and allows for easily adding support for other widget types in the future.

- **Sandboxed Execution:** Widgets now run in a sandboxed environment in the renderer process. A custom `require` function restricts module access to a safe allowlist (`vue`, `@talex-touch/utils`), preventing widgets from accessing sensitive APIs.

- **Improved DX:** The file watcher for widget hot-reloading in development mode is now more responsive.

This commit also includes a fix for resolving the application's tray and dock icon path, making it more reliable across development and packaged builds.
This commit introduces a centralized storage layer to persist user data within the renderer process, replacing previous placeholder implementations like localStorage and in-memory arrays.

Key changes include:
- A new `divisionBoxStorage` module to manage the state of pinned sessions, ensuring they are saved and reloaded across application restarts.
- A new `promptLibraryStorage` module to handle the persistence of custom user-created prompts.
- Refactored `useDivisionBoxStore` and `usePromptManager` to integrate with the new storage system, removing TODOs and providing a robust data persistence solution.
implement comprehensive keyboard event system that forwards specific keys (enter, arrow keys, meta+key combos) from corebox input to attached plugin ui views. includes esc key handling for automatic ui mode exit, new key-transport layer, and updated plugin sdk with onKeyEvent api. adds detailed documentation for keyboard handling behavior and new channel events for bidirectional communication between main process and plugin renderer.
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Signed-off-by: TalexDreamSoul <59305952+TalexDreamSoul@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Signed-off-by: TalexDreamSoul <59305952+TalexDreamSoul@users.noreply.github.com>
…ore-box-transport.ts

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Signed-off-by: TalexDreamSoul <59305952+TalexDreamSoul@users.noreply.github.com>
…rove error handling

- Add CoreBox window destroyed checks in IPC handlers to prevent crashes
- Convert plugin feature handling to async with proper error catching
- Remove debug console.log from PluginItem component
- Add preload-exposed ipcRenderer type to global window interface
- Update input transport to use proper ITouchClientChannel interface
- Fix channel reply mechanism to prevent duplicate responses

BREAKING CHANGE: PluginFeaturesAdapter.handleActiveFeatureInput is now async
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: 7

♻️ Duplicate comments (3)
apps/core-app/src/main/modules/box-tool/core-box/ipc.ts (1)

162-213: Guard core-box:show-input and improve core-box:get-input window checks

core-box:hide-input now correctly handles the case where the CoreBox window is missing or destroyed, but the neighboring handlers still have issues:

  • Line 182 uses coreBoxWindow!.window in core-box:show-input without checking for null or isDestroyed(). If a plugin calls BoxSDK.showInput before CoreBox has been created (or after it’s been torn down), this will throw synchronously and the plugin will not receive a reply.
  • core-box:get-input calls coreBoxWindow!.window inside a try block; while the thrown error is caught and sent back, the message will be a generic TypeError rather than a clear “CoreBox window not available”, and it diverges from the explicit error handling used in hide-input.

Consider aligning both handlers with the hide-input pattern, for example:

this.touchApp.channel.regChannel(ChannelType.PLUGIN, 'core-box:show-input', ({ reply }) => {
  const coreBoxWindow = getCoreBoxWindow()
- 
-  this.touchApp.channel
-    .sendTo(coreBoxWindow!.window, ChannelType.MAIN, 'core-box:set-input-visibility', {
+  if (!coreBoxWindow || coreBoxWindow.window.isDestroyed()) {
+    reply(DataCode.ERROR, { error: 'CoreBox window not available' })
+    return
+  }
+
+  this.touchApp.channel
+    .sendTo(coreBoxWindow.window, ChannelType.MAIN, 'core-box:set-input-visibility', {
       visible: true
     })
     .then(() => {
       reply(DataCode.SUCCESS, { shown: true })
     })
     .catch((error) => {
       reply(DataCode.ERROR, { error: error.message })
     })
})

And similarly for core-box:get-input, perform an explicit early check and avoid the non‑null assertion.

packages/utils/plugin/sdk/feature-sdk.ts (2)

195-204: Backward compatibility for string query format still missing.

The input extraction doesn't handle the legacy case where query is a string rather than a TuffQuery object. Based on learnings, plugins should check if query is a string before treating it as an object.

The suggested fix from the previous review applies:

       channel.onMain('core-box:input-change', (event: any) => {
-        const input = event.data?.input || event.data?.query?.text || event.input || ''
+        const query = event.data?.query
+        const input = event.data?.input || (typeof query === 'string' ? query : query?.text) || event.input || ''
         inputChangeHandlers.forEach(handler => handler(input))
       })
     } else if (channel.on) {
       // Renderer process context
       channel.on('core-box:input-change', (data: any) => {
-        const input = data?.input || data?.query?.text || data || ''
+        const query = data?.query
+        const input = data?.input || (typeof query === 'string' ? query : query?.text) || data || ''
         inputChangeHandlers.forEach(handler => handler(input))
       })

301-301: Use @ts-expect-error instead of @ts-ignore.

Per the ts/ban-ts-comment rule, @ts-expect-error is preferred as it will error if the suppression becomes unnecessary.

-  // @ts-ignore - window.$boxItems is injected by the plugin system
+  // @ts-expect-error - window.$boxItems is injected by the plugin system
🧹 Nitpick comments (20)
apps/core-app/src/renderer/src/views/base/intelligence/IntelligencePromptsPage.vue (1)

158-169: Consider using i18n for auto-save status text.

The autoSaveStatusText computed property uses hardcoded Chinese strings while the rest of the component uses t() for internationalization. For consistency:

 const autoSaveStatusText = computed(() => {
   switch (autoSaveStatus.value) {
     case 'pending':
-      return '待保存...'
+      return t('settings.intelligence.autoSavePending')
     case 'saving':
-      return '保存中...'
+      return t('settings.intelligence.autoSaveSaving')
     case 'saved':
-      return '已保存'
+      return t('settings.intelligence.autoSaveSaved')
     default:
-      return '自动保存已启用'
+      return t('settings.intelligence.autoSaveEnabled')
   }
 })
apps/core-app/src/renderer/src/modules/storage/division-box-storage.ts (1)

22-28: Consider returning a copy from getPinnedSessionIds for consistency.

setPinnedSessionIds defensively copies the input array, but getPinnedSessionIds returns a direct reference to the reactive array. This inconsistency could lead to unintended external mutations.

   getPinnedSessionIds(): string[] {
-    return this.data.pinnedSessionIds
+    return [...this.data.pinnedSessionIds]
   }
apps/core-app/src/renderer/src/modules/hooks/usePromptManager.ts (1)

150-159: Consider removing duplicate storage call.

persistCustomPrompts already calls promptLibraryStorage.replaceCustomPrompts followed by saveToRemote. However, saveCustomPrompts also calls replaceCustomPrompts before saveToRemote, resulting in potential redundancy when persistCustomPromptssaveCustomPrompts is invoked.

This is currently fine since the same data is being set, but could be simplified:

   const saveCustomPrompts = async () => {
     try {
-      promptLibraryStorage.replaceCustomPrompts(prompts.custom)
       await promptLibraryStorage.saveToRemote({ force: true })
     }
     catch (error) {
       console.error('Failed to save custom prompts:', error)
     }
   }

Or keep replaceCustomPrompts here and remove from the call chain above. The current implementation works but has redundant operations.

plugins/touch-translation/widgets/TestWidget.vue (1)

34-36: Specify type="button" to avoid unintended form submission.

If this widget is ever rendered inside a <form>, a plain <button> will submit the form by default. Safer to make it explicit:

-    <button @click="increment">
+    <button type="button" @click="increment">
       Increment
     </button>
apps/core-app/src/main/modules/box-tool/search-engine/sort/tuff-sorter.ts (2)

28-28: Minor inefficiency: redundant normalization.

The searchKey is normalized at line 144 (trim().toLowerCase()), then normalized again at line 28 in calculateMatchScore. While harmless, this adds unnecessary string operations for every item in the search results.

Consider documenting that calculateMatchScore expects a pre-normalized key, or rename the parameter to normalizedSearchKey to clarify the expected input:

-function calculateMatchScore(item: TuffItem, searchKey?: string): number {
-  const normalizedKey = searchKey?.trim().toLowerCase()
+function calculateMatchScore(item: TuffItem, normalizedSearchKey?: string): number {
+  const normalizedKey = normalizedSearchKey

Also applies to: 144-144


90-90: Translate comment to English for consistency.

The comment at line 90 is in Chinese while all other comments in the file are in English. For better maintainability and accessibility to international contributors, consider translating it.

-      score += 300 // 开头匹配,大幅加分
+      score += 300 // Beginning match, significant boost
apps/core-app/src/renderer/src/modules/plugin/widget-registry.ts (1)

15-53: Module allowlist is duplicated and may become inconsistent.

The talexModules list here duplicates ALLOWED_PACKAGES in vue-processor.ts. If one is updated without the other, widgets may compile successfully but fail at runtime (or vice versa).

Consider extracting the shared allowlist to a single source of truth in @talex-touch/utils/plugin/widget or a dedicated constants file.

apps/core-app/src/main/modules/plugin/widget/processors/vue-processor.ts (1)

15-24: ALLOWED_PACKAGES is duplicated.

This list is also defined in widget-registry.ts (lines 22-30 as talexModules). As mentioned in the review of that file, consider extracting to a shared constant.

apps/core-app/src/main/modules/plugin/widget/widget-compiler.ts (1)

8-9: Side-effect processor registration at module load time.

Registering the processor as a module-level side effect works but may complicate testing (hard to reset registry state) and tree-shaking.

Consider exposing an explicit initialization function or registering in an application bootstrap phase instead:

// Alternative: explicit initialization
export function initializeDefaultProcessors(): void {
  widgetProcessorRegistry.register(new WidgetVueProcessor())
}

This is a minor concern for maintainability, not a blocking issue.

apps/core-app/src/main/modules/plugin/widget/widget-processor.ts (1)

63-66: Consider enhanced error reporting for compilation failures.

The compile method returns null on failure, which provides no information about what went wrong. This makes debugging widget compilation failures difficult for plugin developers.

Consider one of these alternatives:

  • Return a Result type: Promise<{ success: true, widget: CompiledWidget } | { success: false, error: string }>
  • Throw descriptive errors and let callers handle them with try-catch
  • Add an optional errors array to CompiledWidget similar to DependencyValidationResult
apps/core-app/src/main/modules/tray/tray-manager.ts (1)

290-331: Safer Dock icon setup; consider using a shared logger and static fs-extra import

The additional validation around appIconPath, file existence, and app.dock makes Dock setup much more robust and avoids hard‑to‑debug runtime errors on macOS. One minor follow‑up:

  • Instead of const fs = require('fs-extra') inside setupDockIcon, consider a top‑level ES import (e.g. import * as fse from 'fs-extra') and reusing it here, and prefer the structured logger used elsewhere in core‑app over raw console.* for these new logs to stay consistent with logging guidelines.
apps/core-app/src/main/modules/box-tool/core-box/manager.ts (1)

5-7: Trigger options and UI-mode exit notification look good; consider handling send failures

Plumbing triggeredByShortcut through TriggerOptions into windowManager.show() and emitting core-box:ui-mode-exited over the MAIN channel is consistent with the new renderer behavior and keeps shortcut origin explicit.

One minor improvement: the genTouchApp().channel.sendTo(...) in exitUIMode is currently fire‑and‑forget. If that send fails (e.g., window goes away mid‑flight), the rejection will be unobserved. Consider either awaiting it with a .catch that logs via your logger, or explicitly documenting that failures are intentionally ignored.

Also applies to: 20-26, 98-103, 135-135, 169-178

apps/core-app/src/main/modules/tray/tray-icon-provider.ts (1)

248-255: New getAppIconPath behavior is clearer; verify all callers handle empty/missing paths

The refactor to getAppIconPath makes dev vs packaged resolution much more deterministic, and logging the dev‑mode failure case is helpful. Two things to double‑check:

  • In packaged mode, the fallback path.join(appPath, '..', '..', 'Resources', iconName) is returned without an existsSync check. This is fine as long as all callers either validate the path (as TrayManager.setupDockIcon now does) or are tolerant of a non‑existent path.
  • In dev mode you now explicitly return '' on failure. Please verify any other consumers of TrayIconProvider.getAppIconPath() (beyond TrayManager) are robust to an empty string and won’t attempt to load it directly.

Also applies to: 258-294

apps/core-app/src/main/modules/box-tool/core-box/window.ts (2)

904-907: Plugin lifecycle inactive event: ensure all listeners use the new string

Changing the deactivation notification to

genTouchApp().channel.send(ChannelType.PLUGIN, 'plugin:lifecycle:inactive', {
  plugin: plugin.name
})

is fine, but it assumes all consumers that previously listened for LifecycleHooks.INACTIVE have been updated to this string‑based event name. It’s worth double‑checking there are no remaining listeners using the old constant.


930-941: Keyboard forwarding helpers are well-structured; add a destroyed check for extra safety

The new UI helpers (sendChannelMessageToUIView, isUIViewActive, isUIViewFocused) plus forwardKeyEvent/buildKeyModifiers/mapKeyToElectronKeyCode provide a clean abstraction for simulating native key input into the plugin UI view, and the key mapping table covers the common navigation and control keys.

One small hardening improvement for forwardKeyEvent:

  • Before calling this.uiView.webContents.sendInputEvent(...), also check !this.uiView.webContents.isDestroyed() to avoid potential runtime errors if a late key event arrives just after the UI view has been torn down.

For example:

  public forwardKeyEvent(event: { /* ... */ }): void {
-    if (!this.uiView) {
+    if (!this.uiView || this.uiView.webContents.isDestroyed()) {
       coreBoxWindowLog.debug('Cannot forward key event: no UI view attached')
       return
     }
    // rest unchanged
  }

Also applies to: 951-963, 980-1068

apps/core-app/src/main/modules/box-tool/core-box/key-transport.ts (1)

10-37: Consider centralizing shared interfaces to avoid duplication.

The ForwardedKeyEvent and UIViewStateResponse interfaces are duplicated across multiple files:

  • apps/core-app/src/main/modules/box-tool/core-box/key-transport.ts (this file)
  • apps/core-app/src/renderer/src/modules/box/adapter/transport/key-transport.ts
  • packages/utils/plugin/sdk/feature-sdk.ts

Consider moving these interfaces to a shared location in @talex-touch/utils to maintain a single source of truth. Based on coding guidelines, shared types should be imported from @talex-touch/utils.

apps/core-app/src/renderer/src/modules/box/adapter/transport/key-transport.ts (2)

7-34: Interface duplication - same feedback as main process file.

These interfaces are duplicated from the main process key-transport.ts. Consider centralizing in @talex-touch/utils as per coding guidelines for shared types.


42-64: LGTM with minor suggestion.

The factory function is well-designed:

  • Accepts channel for dependency injection (testability)
  • Uses debounceMs: 0 for responsive keyboard forwarding
  • getUIViewState has proper error handling with safe fallback

Consider adding debug logging in the catch block for troubleshooting IPC failures:

     async getUIViewState(): Promise<UIViewStateResponse> {
       try {
         const result = await channel.send('core-box:get-ui-view-state')
         return result as UIViewStateResponse
-      } catch {
+      } catch (error) {
+        console.debug('[KeyTransport] Failed to get UI view state:', error)
         return { isActive: false, isFocused: false, isUIMode: false }
       }
     }
packages/utils/plugin/sdk/feature-sdk.ts (2)

17-33: Consider importing ForwardedKeyEvent from a shared location.

This interface is duplicated in at least three places:

  • apps/core-app/src/main/modules/box-tool/core-box/key-transport.ts
  • apps/core-app/src/renderer/src/modules/box/adapter/transport/key-transport.ts
  • Here in feature-sdk.ts

The other definitions include detailed JSDoc comments for each property. Consolidating to a single source of truth (e.g., in packages/utils) would prevent divergence and improve maintainability.


209-227: Consider adding minimal validation for forwarded key events.

The type cast event.data as ForwardedKeyEvent assumes the data matches the expected shape. While malformed data is unlikely in internal IPC, a defensive check on the key property would make the SDK more robust:

       channel.onMain('core-box:key-event', (event: any) => {
         const keyEvent = event.data as ForwardedKeyEvent
-        if (keyEvent) {
+        if (keyEvent && typeof keyEvent.key === 'string') {
           keyEventHandlers.forEach(handler => handler(keyEvent))
         }
       })

Same pattern for the renderer context block.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 317e203 and f162b43.

📒 Files selected for processing (35)
  • apps/core-app/plan-prd/01-project/TODO_PLAN.md (1 hunks)
  • apps/core-app/plan-prd/README.md (2 hunks)
  • apps/core-app/src/main/modules/box-tool/core-box/ipc.ts (6 hunks)
  • apps/core-app/src/main/modules/box-tool/core-box/key-transport.ts (1 hunks)
  • apps/core-app/src/main/modules/box-tool/core-box/manager.ts (5 hunks)
  • apps/core-app/src/main/modules/box-tool/core-box/transport/core-box-transport.ts (1 hunks)
  • apps/core-app/src/main/modules/box-tool/core-box/window.ts (15 hunks)
  • apps/core-app/src/main/modules/box-tool/search-engine/sort/tuff-sorter.ts (4 hunks)
  • apps/core-app/src/main/modules/plugin/widget/processors/vue-processor.ts (1 hunks)
  • apps/core-app/src/main/modules/plugin/widget/widget-compiler.ts (1 hunks)
  • apps/core-app/src/main/modules/plugin/widget/widget-manager.ts (4 hunks)
  • apps/core-app/src/main/modules/plugin/widget/widget-processor.ts (1 hunks)
  • apps/core-app/src/main/modules/tray/tray-icon-provider.ts (1 hunks)
  • apps/core-app/src/main/modules/tray/tray-manager.ts (1 hunks)
  • apps/core-app/src/main/plugins/internal/internal-ai-plugin.ts (1 hunks)
  • apps/core-app/src/main/plugins/internal/internal-plugin-logger.ts (1 hunks)
  • apps/core-app/src/renderer/src/modules/box/adapter/hooks/useKeyboard.ts (7 hunks)
  • apps/core-app/src/renderer/src/modules/box/adapter/transport/key-transport.ts (1 hunks)
  • apps/core-app/src/renderer/src/modules/division-box/store/division-box.ts (3 hunks)
  • apps/core-app/src/renderer/src/modules/hooks/usePromptManager.ts (7 hunks)
  • apps/core-app/src/renderer/src/modules/intelligence/prompt-types.ts (1 hunks)
  • apps/core-app/src/renderer/src/modules/plugin/widget-registry.ts (3 hunks)
  • apps/core-app/src/renderer/src/modules/storage/division-box-storage.ts (1 hunks)
  • apps/core-app/src/renderer/src/modules/storage/prompt-library.ts (1 hunks)
  • apps/core-app/src/renderer/src/views/base/intelligence/IntelligencePromptsPage.vue (1 hunks)
  • apps/core-app/src/renderer/src/views/box/CoreBox.vue (4 hunks)
  • apps/docs/dev/api/channel.zh.md (1 hunks)
  • apps/docs/dev/api/keyboard.en.md (1 hunks)
  • apps/docs/dev/api/keyboard.zh.md (1 hunks)
  • packages/utils/plugin/sdk/README.md (6 hunks)
  • packages/utils/plugin/sdk/enum/bridge-event.ts (1 hunks)
  • packages/utils/plugin/sdk/feature-sdk.ts (5 hunks)
  • packages/utils/plugin/sdk/hooks/bridge.ts (4 hunks)
  • packages/utils/plugin/widget.ts (1 hunks)
  • plugins/touch-translation/widgets/TestWidget.vue (1 hunks)
✅ Files skipped from review due to trivial changes (4)
  • apps/docs/dev/api/channel.zh.md
  • apps/core-app/src/main/plugins/internal/internal-ai-plugin.ts
  • apps/core-app/src/main/plugins/internal/internal-plugin-logger.ts
  • apps/docs/dev/api/keyboard.zh.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/core-app/src/main/modules/box-tool/core-box/transport/core-box-transport.ts
🧰 Additional context used
📓 Path-based instructions (10)
apps/core-app/src/renderer/src/**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (CLAUDE.md)

apps/core-app/src/renderer/src/**/*.{ts,tsx,vue}: Implement Vue 3 components with TypeScript in the renderer process. Organize components in src/components/, view layouts in src/views/, and state management via Pinia stores and composables in src/modules/hooks/.
Use Pinia stores and composables in src/modules/hooks/ for state management in the renderer process instead of local component state.
Use Vue Router 4.5.1 for client-side routing in the renderer application.

apps/core-app/src/renderer/src/**/*.{ts,tsx,vue}: Use Pinia stores and composables in src/modules/hooks/ for state management in renderer process Vue components
Use Vue 3, TypeScript, Pinia for state management, and UnoCSS for styling in renderer process

Files:

  • apps/core-app/src/renderer/src/modules/intelligence/prompt-types.ts
  • apps/core-app/src/renderer/src/modules/division-box/store/division-box.ts
  • apps/core-app/src/renderer/src/modules/box/adapter/hooks/useKeyboard.ts
  • apps/core-app/src/renderer/src/modules/storage/division-box-storage.ts
  • apps/core-app/src/renderer/src/modules/storage/prompt-library.ts
  • apps/core-app/src/renderer/src/modules/box/adapter/transport/key-transport.ts
  • apps/core-app/src/renderer/src/views/base/intelligence/IntelligencePromptsPage.vue
  • apps/core-app/src/renderer/src/modules/plugin/widget-registry.ts
  • apps/core-app/src/renderer/src/modules/hooks/usePromptManager.ts
  • apps/core-app/src/renderer/src/views/box/CoreBox.vue
apps/core-app/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

apps/core-app/src/**/*.{ts,tsx}: Use log4js for logging with structured namespaces, timestamps, and colored output. Provide meaningful namespace identifiers for debugging.
Import and use shared types and utilities from @talex-touch/utils package. Use enums like TuffInputType, TalexEvents, and ChannelType from the shared package.

Files:

  • apps/core-app/src/renderer/src/modules/intelligence/prompt-types.ts
  • apps/core-app/src/renderer/src/modules/division-box/store/division-box.ts
  • apps/core-app/src/renderer/src/modules/box/adapter/hooks/useKeyboard.ts
  • apps/core-app/src/main/modules/tray/tray-icon-provider.ts
  • apps/core-app/src/renderer/src/modules/storage/division-box-storage.ts
  • apps/core-app/src/renderer/src/modules/storage/prompt-library.ts
  • apps/core-app/src/renderer/src/modules/box/adapter/transport/key-transport.ts
  • apps/core-app/src/main/modules/box-tool/core-box/key-transport.ts
  • apps/core-app/src/main/modules/box-tool/core-box/manager.ts
  • apps/core-app/src/renderer/src/modules/plugin/widget-registry.ts
  • apps/core-app/src/renderer/src/modules/hooks/usePromptManager.ts
  • apps/core-app/src/main/modules/plugin/widget/processors/vue-processor.ts
  • apps/core-app/src/main/modules/plugin/widget/widget-compiler.ts
  • apps/core-app/src/main/modules/plugin/widget/widget-manager.ts
  • apps/core-app/src/main/modules/box-tool/core-box/ipc.ts
  • apps/core-app/src/main/modules/tray/tray-manager.ts
  • apps/core-app/src/main/modules/plugin/widget/widget-processor.ts
  • apps/core-app/src/main/modules/box-tool/search-engine/sort/tuff-sorter.ts
  • apps/core-app/src/main/modules/box-tool/core-box/window.ts
apps/core-app/src/renderer/src/**/*.{vue,ts,tsx,css,scss}

📄 CodeRabbit inference engine (CLAUDE.md)

Use UnoCSS 66.3.3+ for utility-first CSS styling instead of traditional CSS frameworks.

Files:

  • apps/core-app/src/renderer/src/modules/intelligence/prompt-types.ts
  • apps/core-app/src/renderer/src/modules/division-box/store/division-box.ts
  • apps/core-app/src/renderer/src/modules/box/adapter/hooks/useKeyboard.ts
  • apps/core-app/src/renderer/src/modules/storage/division-box-storage.ts
  • apps/core-app/src/renderer/src/modules/storage/prompt-library.ts
  • apps/core-app/src/renderer/src/modules/box/adapter/transport/key-transport.ts
  • apps/core-app/src/renderer/src/views/base/intelligence/IntelligencePromptsPage.vue
  • apps/core-app/src/renderer/src/modules/plugin/widget-registry.ts
  • apps/core-app/src/renderer/src/modules/hooks/usePromptManager.ts
  • apps/core-app/src/renderer/src/views/box/CoreBox.vue
apps/core-app/src/renderer/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use Pinia 3.0.3 for state management in the renderer application.

Files:

  • apps/core-app/src/renderer/src/modules/intelligence/prompt-types.ts
  • apps/core-app/src/renderer/src/modules/division-box/store/division-box.ts
  • apps/core-app/src/renderer/src/modules/box/adapter/hooks/useKeyboard.ts
  • apps/core-app/src/renderer/src/modules/storage/division-box-storage.ts
  • apps/core-app/src/renderer/src/modules/storage/prompt-library.ts
  • apps/core-app/src/renderer/src/modules/box/adapter/transport/key-transport.ts
  • apps/core-app/src/renderer/src/modules/plugin/widget-registry.ts
  • apps/core-app/src/renderer/src/modules/hooks/usePromptManager.ts
apps/core-app/src/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Import shared types and utilities from @talex-touch/utils package in plugins and application code

Files:

  • apps/core-app/src/renderer/src/modules/intelligence/prompt-types.ts
  • apps/core-app/src/renderer/src/modules/division-box/store/division-box.ts
  • apps/core-app/src/renderer/src/modules/box/adapter/hooks/useKeyboard.ts
  • apps/core-app/src/main/modules/tray/tray-icon-provider.ts
  • apps/core-app/src/renderer/src/modules/storage/division-box-storage.ts
  • apps/core-app/src/renderer/src/modules/storage/prompt-library.ts
  • apps/core-app/src/renderer/src/modules/box/adapter/transport/key-transport.ts
  • apps/core-app/src/main/modules/box-tool/core-box/key-transport.ts
  • apps/core-app/src/main/modules/box-tool/core-box/manager.ts
  • apps/core-app/src/renderer/src/modules/plugin/widget-registry.ts
  • apps/core-app/src/renderer/src/modules/hooks/usePromptManager.ts
  • apps/core-app/src/main/modules/plugin/widget/processors/vue-processor.ts
  • apps/core-app/src/main/modules/plugin/widget/widget-compiler.ts
  • apps/core-app/src/main/modules/plugin/widget/widget-manager.ts
  • apps/core-app/src/main/modules/box-tool/core-box/ipc.ts
  • apps/core-app/src/main/modules/tray/tray-manager.ts
  • apps/core-app/src/main/modules/plugin/widget/widget-processor.ts
  • apps/core-app/src/main/modules/box-tool/search-engine/sort/tuff-sorter.ts
  • apps/core-app/src/main/modules/box-tool/core-box/window.ts
apps/core-app/src/main/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

apps/core-app/src/main/**/*.{ts,tsx}: Register IPC channel handlers in the main process using regChannel(type, eventName, callback). Use ChannelType.MAIN for main-renderer communication and ChannelType.PLUGIN for plugin-specific channels.
Use sendPlugin(pluginName, eventName, arg) to send messages from main process to plugins, and use requestKey(name) to manage encrypted keys for plugin isolation.
Use TouchWindow wrapper for window creation instead of directly using Electron BrowserWindow. Enable platform-specific effects: Vibrancy on macOS and Mica on Windows.
Use two-phase window setup with TouchWindow: separate creation from rendering. Use autoShow option to control initial visibility.
Use DevProcessManager to prevent app quit events in development environment, allowing custom cleanup without forcing application exit.

Files:

  • apps/core-app/src/main/modules/tray/tray-icon-provider.ts
  • apps/core-app/src/main/modules/box-tool/core-box/key-transport.ts
  • apps/core-app/src/main/modules/box-tool/core-box/manager.ts
  • apps/core-app/src/main/modules/plugin/widget/processors/vue-processor.ts
  • apps/core-app/src/main/modules/plugin/widget/widget-compiler.ts
  • apps/core-app/src/main/modules/plugin/widget/widget-manager.ts
  • apps/core-app/src/main/modules/box-tool/core-box/ipc.ts
  • apps/core-app/src/main/modules/tray/tray-manager.ts
  • apps/core-app/src/main/modules/plugin/widget/widget-processor.ts
  • apps/core-app/src/main/modules/box-tool/search-engine/sort/tuff-sorter.ts
  • apps/core-app/src/main/modules/box-tool/core-box/window.ts
apps/core-app/src/main/modules/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

apps/core-app/src/main/modules/**/*.ts: In main process architecture, inherit from BaseModule with required onInit() and onDestroy() methods, and optional created(), start(), and stop() lifecycle methods
Module directory pattern: request isolated directory from ModuleManager for module-specific persistent storage without knowing root path

Files:

  • apps/core-app/src/main/modules/tray/tray-icon-provider.ts
  • apps/core-app/src/main/modules/box-tool/core-box/key-transport.ts
  • apps/core-app/src/main/modules/box-tool/core-box/manager.ts
  • apps/core-app/src/main/modules/plugin/widget/processors/vue-processor.ts
  • apps/core-app/src/main/modules/plugin/widget/widget-compiler.ts
  • apps/core-app/src/main/modules/plugin/widget/widget-manager.ts
  • apps/core-app/src/main/modules/box-tool/core-box/ipc.ts
  • apps/core-app/src/main/modules/tray/tray-manager.ts
  • apps/core-app/src/main/modules/plugin/widget/widget-processor.ts
  • apps/core-app/src/main/modules/box-tool/search-engine/sort/tuff-sorter.ts
  • apps/core-app/src/main/modules/box-tool/core-box/window.ts
apps/core-app/src/main/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

apps/core-app/src/main/**/*.ts: Register IPC channels using regChannel(type: ChannelType, eventName: string, callback) and send messages via send(), sendTo(), or sendPlugin() methods
Use log4js for structured logging with namespaces, timestamps, and colored output for debugging
DevProcessManager prevents application quit events during development to allow custom cleanup logic

Files:

  • apps/core-app/src/main/modules/tray/tray-icon-provider.ts
  • apps/core-app/src/main/modules/box-tool/core-box/key-transport.ts
  • apps/core-app/src/main/modules/box-tool/core-box/manager.ts
  • apps/core-app/src/main/modules/plugin/widget/processors/vue-processor.ts
  • apps/core-app/src/main/modules/plugin/widget/widget-compiler.ts
  • apps/core-app/src/main/modules/plugin/widget/widget-manager.ts
  • apps/core-app/src/main/modules/box-tool/core-box/ipc.ts
  • apps/core-app/src/main/modules/tray/tray-manager.ts
  • apps/core-app/src/main/modules/plugin/widget/widget-processor.ts
  • apps/core-app/src/main/modules/box-tool/search-engine/sort/tuff-sorter.ts
  • apps/core-app/src/main/modules/box-tool/core-box/window.ts
apps/core-app/src/renderer/src/**/*.vue

📄 CodeRabbit inference engine (CLAUDE.md)

Use Element Plus 2.10.4+ for UI components in the renderer process.

Files:

  • apps/core-app/src/renderer/src/views/base/intelligence/IntelligencePromptsPage.vue
  • apps/core-app/src/renderer/src/views/box/CoreBox.vue
apps/core-app/src/main/modules/box-tool/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Position CoreBox windows screen-aware using cursor position to select the appropriate display in multi-monitor setups.

Files:

  • apps/core-app/src/main/modules/box-tool/core-box/key-transport.ts
  • apps/core-app/src/main/modules/box-tool/core-box/manager.ts
  • apps/core-app/src/main/modules/box-tool/core-box/ipc.ts
  • apps/core-app/src/main/modules/box-tool/search-engine/sort/tuff-sorter.ts
  • apps/core-app/src/main/modules/box-tool/core-box/window.ts
🧠 Learnings (25)
📚 Learning: 2025-11-29T07:45:45.435Z
Learnt from: CR
Repo: talex-touch/tuff PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-29T07:45:45.435Z
Learning: Applies to apps/core-app/src/renderer/src/**/*.{ts,tsx,vue} : Use Pinia stores and composables in src/modules/hooks/ for state management in the renderer process instead of local component state.

Applied to files:

  • apps/core-app/src/renderer/src/modules/division-box/store/division-box.ts
  • apps/core-app/src/renderer/src/modules/storage/division-box-storage.ts
  • apps/core-app/src/renderer/src/modules/hooks/usePromptManager.ts
📚 Learning: 2025-11-29T07:46:02.249Z
Learnt from: CR
Repo: talex-touch/tuff PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-29T07:46:02.249Z
Learning: Applies to apps/core-app/src/main/modules/storage/**/*.ts : Storage module broadcasts updates to all windows to maintain UI sync across multiple renderer instances

Applied to files:

  • apps/core-app/src/renderer/src/modules/division-box/store/division-box.ts
  • apps/core-app/src/renderer/src/modules/storage/division-box-storage.ts
  • apps/core-app/src/renderer/src/modules/storage/prompt-library.ts
  • apps/core-app/src/renderer/src/modules/box/adapter/transport/key-transport.ts
  • apps/core-app/src/main/modules/box-tool/core-box/key-transport.ts
  • apps/core-app/src/main/modules/box-tool/core-box/manager.ts
  • apps/core-app/src/main/modules/box-tool/core-box/ipc.ts
  • apps/core-app/src/main/modules/box-tool/core-box/window.ts
📚 Learning: 2025-11-29T07:46:02.249Z
Learnt from: CR
Repo: talex-touch/tuff PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-29T07:46:02.249Z
Learning: Applies to apps/core-app/src/renderer/src/**/*.{ts,tsx,vue} : Use Pinia stores and composables in src/modules/hooks/ for state management in renderer process Vue components

Applied to files:

  • apps/core-app/src/renderer/src/modules/division-box/store/division-box.ts
  • apps/core-app/src/renderer/src/modules/storage/division-box-storage.ts
  • apps/core-app/src/renderer/src/views/base/intelligence/IntelligencePromptsPage.vue
  • apps/core-app/src/main/modules/plugin/widget/processors/vue-processor.ts
📚 Learning: 2025-11-29T07:45:45.435Z
Learnt from: CR
Repo: talex-touch/tuff PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-29T07:45:45.435Z
Learning: Applies to apps/core-app/src/renderer/src/**/*.{ts,tsx} : Use Pinia 3.0.3 for state management in the renderer application.

Applied to files:

  • apps/core-app/src/renderer/src/modules/division-box/store/division-box.ts
📚 Learning: 2025-11-29T07:45:45.435Z
Learnt from: CR
Repo: talex-touch/tuff PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-29T07:45:45.435Z
Learning: Applies to apps/core-app/src/main/**/*.{ts,tsx} : Use sendPlugin(pluginName, eventName, arg) to send messages from main process to plugins, and use requestKey(name) to manage encrypted keys for plugin isolation.

Applied to files:

  • apps/core-app/src/renderer/src/modules/box/adapter/hooks/useKeyboard.ts
  • apps/docs/dev/api/keyboard.en.md
  • apps/core-app/src/renderer/src/modules/box/adapter/transport/key-transport.ts
  • packages/utils/plugin/sdk/hooks/bridge.ts
  • apps/core-app/src/main/modules/box-tool/core-box/key-transport.ts
  • apps/core-app/src/main/modules/box-tool/core-box/manager.ts
  • packages/utils/plugin/sdk/feature-sdk.ts
  • apps/core-app/src/main/modules/box-tool/core-box/ipc.ts
  • apps/core-app/src/main/modules/box-tool/core-box/window.ts
📚 Learning: 2025-11-29T07:45:45.435Z
Learnt from: CR
Repo: talex-touch/tuff PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-29T07:45:45.435Z
Learning: Applies to **/plugins/**/*.{ts,tsx,js,jsx} : Use TuffInputType enum values (text, image, files, html) when handling clipboard data in plugins. Check query.inputs array to find specific input types and access their content and thumbnail properties.

Applied to files:

  • apps/core-app/src/renderer/src/modules/box/adapter/hooks/useKeyboard.ts
  • packages/utils/plugin/sdk/hooks/bridge.ts
  • apps/core-app/src/main/modules/box-tool/core-box/manager.ts
  • packages/utils/plugin/sdk/feature-sdk.ts
  • apps/core-app/src/main/modules/box-tool/core-box/ipc.ts
  • apps/core-app/src/main/modules/box-tool/core-box/window.ts
📚 Learning: 2025-11-29T07:45:45.435Z
Learnt from: CR
Repo: talex-touch/tuff PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-29T07:45:45.435Z
Learning: Applies to apps/core-app/src/main/**/*.{ts,tsx} : Use TouchWindow wrapper for window creation instead of directly using Electron BrowserWindow. Enable platform-specific effects: Vibrancy on macOS and Mica on Windows.

Applied to files:

  • apps/core-app/src/renderer/src/modules/box/adapter/hooks/useKeyboard.ts
  • apps/core-app/src/renderer/src/modules/box/adapter/transport/key-transport.ts
  • packages/utils/plugin/sdk/hooks/bridge.ts
  • apps/core-app/src/main/modules/box-tool/core-box/manager.ts
  • apps/core-app/src/main/modules/box-tool/core-box/ipc.ts
  • apps/core-app/src/main/modules/tray/tray-manager.ts
  • apps/core-app/src/main/modules/box-tool/core-box/window.ts
📚 Learning: 2025-11-29T07:45:45.435Z
Learnt from: CR
Repo: talex-touch/tuff PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-29T07:45:45.435Z
Learning: Applies to apps/core-app/src/main/modules/box-tool/**/*.{ts,tsx} : Position CoreBox windows screen-aware using cursor position to select the appropriate display in multi-monitor setups.

Applied to files:

  • apps/core-app/src/renderer/src/modules/box/adapter/hooks/useKeyboard.ts
  • apps/core-app/src/renderer/src/modules/box/adapter/transport/key-transport.ts
  • apps/core-app/src/main/modules/box-tool/core-box/key-transport.ts
  • apps/core-app/src/main/modules/box-tool/core-box/manager.ts
  • apps/core-app/src/main/modules/box-tool/core-box/ipc.ts
  • apps/core-app/src/renderer/src/views/box/CoreBox.vue
  • apps/core-app/src/main/modules/box-tool/core-box/window.ts
📚 Learning: 2025-11-29T07:46:02.249Z
Learnt from: CR
Repo: talex-touch/tuff PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-29T07:46:02.249Z
Learning: Applies to apps/core-app/src/main/**/*.ts : Register IPC channels using `regChannel(type: ChannelType, eventName: string, callback)` and send messages via `send()`, `sendTo()`, or `sendPlugin()` methods

Applied to files:

  • apps/core-app/src/renderer/src/modules/box/adapter/hooks/useKeyboard.ts
  • apps/core-app/src/renderer/src/modules/box/adapter/transport/key-transport.ts
  • packages/utils/plugin/sdk/hooks/bridge.ts
  • apps/core-app/src/main/modules/box-tool/core-box/key-transport.ts
  • apps/core-app/src/main/modules/box-tool/core-box/manager.ts
  • packages/utils/plugin/sdk/feature-sdk.ts
  • apps/core-app/src/main/modules/box-tool/core-box/ipc.ts
  • apps/core-app/src/main/modules/box-tool/core-box/window.ts
📚 Learning: 2025-11-29T07:45:45.435Z
Learnt from: CR
Repo: talex-touch/tuff PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-29T07:45:45.435Z
Learning: Applies to apps/core-app/src/main/**/*.{ts,tsx} : Register IPC channel handlers in the main process using regChannel(type, eventName, callback). Use ChannelType.MAIN for main-renderer communication and ChannelType.PLUGIN for plugin-specific channels.

Applied to files:

  • apps/core-app/src/renderer/src/modules/box/adapter/hooks/useKeyboard.ts
  • apps/core-app/src/renderer/src/modules/box/adapter/transport/key-transport.ts
  • packages/utils/plugin/sdk/hooks/bridge.ts
  • apps/core-app/src/main/modules/box-tool/core-box/key-transport.ts
  • apps/core-app/src/main/modules/box-tool/core-box/manager.ts
  • packages/utils/plugin/sdk/feature-sdk.ts
  • apps/core-app/src/main/modules/box-tool/core-box/ipc.ts
  • apps/core-app/src/main/modules/box-tool/core-box/window.ts
📚 Learning: 2025-11-29T07:46:02.249Z
Learnt from: CR
Repo: talex-touch/tuff PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-29T07:46:02.249Z
Learning: Applies to apps/core-app/src/main/modules/**/*.ts : Module directory pattern: request isolated directory from ModuleManager for module-specific persistent storage without knowing root path

Applied to files:

  • apps/core-app/src/renderer/src/modules/storage/division-box-storage.ts
📚 Learning: 2025-11-29T07:46:02.249Z
Learnt from: CR
Repo: talex-touch/tuff PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-29T07:46:02.249Z
Learning: Applies to apps/core-app/src/main/modules/storage/**/*.ts : Store plugin configuration files using cleaned filenames to prevent path traversal attacks

Applied to files:

  • apps/core-app/src/renderer/src/modules/storage/division-box-storage.ts
📚 Learning: 2025-11-29T07:45:45.435Z
Learnt from: CR
Repo: talex-touch/tuff PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-29T07:45:45.435Z
Learning: Applies to apps/core-app/src/renderer/src/**/*.{ts,tsx,vue} : Implement Vue 3 components with TypeScript in the renderer process. Organize components in src/components/, view layouts in src/views/, and state management via Pinia stores and composables in src/modules/hooks/.

Applied to files:

  • apps/core-app/plan-prd/01-project/TODO_PLAN.md
  • apps/core-app/src/main/modules/plugin/widget/processors/vue-processor.ts
📚 Learning: 2025-11-29T07:45:45.435Z
Learnt from: CR
Repo: talex-touch/tuff PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-29T07:45:45.435Z
Learning: Applies to apps/core-app/src/**/*.{ts,tsx} : Import and use shared types and utilities from talex-touch/utils package. Use enums like TuffInputType, TalexEvents, and ChannelType from the shared package.

Applied to files:

  • apps/core-app/src/renderer/src/modules/box/adapter/transport/key-transport.ts
  • apps/core-app/src/main/modules/box-tool/core-box/manager.ts
  • packages/utils/plugin/sdk/feature-sdk.ts
  • apps/core-app/src/renderer/src/modules/hooks/usePromptManager.ts
  • apps/core-app/src/main/modules/box-tool/core-box/ipc.ts
  • apps/core-app/src/main/modules/box-tool/core-box/window.ts
📚 Learning: 2025-11-29T07:45:45.435Z
Learnt from: CR
Repo: talex-touch/tuff PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-29T07:45:45.435Z
Learning: Applies to **/plugins/**/manifest.json : Declare acceptedInputTypes array in plugin manifest features to specify supported input types (text, image, files, html) from clipboard data.

Applied to files:

  • packages/utils/plugin/sdk/README.md
📚 Learning: 2025-11-29T07:46:02.249Z
Learnt from: CR
Repo: talex-touch/tuff PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-29T07:46:02.249Z
Learning: Applies to apps/core-app/src/main/core/**/*.ts : TouchWindow uses two-phase setup: creation phase vs rendering phase, with autoShow option to control display timing

Applied to files:

  • apps/core-app/src/main/modules/box-tool/core-box/manager.ts
  • apps/core-app/src/main/modules/box-tool/core-box/ipc.ts
  • apps/core-app/src/main/modules/box-tool/core-box/window.ts
📚 Learning: 2025-11-29T07:45:45.435Z
Learnt from: CR
Repo: talex-touch/tuff PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-29T07:45:45.435Z
Learning: Applies to apps/core-app/src/main/**/*.{ts,tsx} : Use two-phase window setup with TouchWindow: separate creation from rendering. Use autoShow option to control initial visibility.

Applied to files:

  • apps/core-app/src/main/modules/box-tool/core-box/manager.ts
  • apps/core-app/src/main/modules/box-tool/core-box/ipc.ts
  • apps/core-app/src/main/modules/box-tool/core-box/window.ts
📚 Learning: 2025-11-29T07:46:02.249Z
Learnt from: CR
Repo: talex-touch/tuff PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-29T07:46:02.249Z
Learning: Applies to apps/core-app/src/**/*.ts : Import shared types and utilities from talex-touch/utils package in plugins and application code

Applied to files:

  • apps/core-app/src/main/modules/box-tool/core-box/manager.ts
  • apps/core-app/src/main/modules/box-tool/core-box/window.ts
📚 Learning: 2025-11-29T07:45:45.435Z
Learnt from: CR
Repo: talex-touch/tuff PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-29T07:45:45.435Z
Learning: Maintain the talex-touch/utils package as a shared npm package for external plugin developers. Ensure type definitions and utilities are exported for public use.

Applied to files:

  • apps/core-app/src/main/modules/box-tool/core-box/manager.ts
  • apps/core-app/src/main/modules/box-tool/core-box/window.ts
📚 Learning: 2025-11-29T07:45:45.435Z
Learnt from: CR
Repo: talex-touch/tuff PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-29T07:45:45.435Z
Learning: Use TouchEventBus for application-wide event dispatching. Subscribe to events like APP_READY, APP_START, ALL_MODULES_LOADED, PLUGIN_STORAGE_UPDATED using the TalexEvents enum.

Applied to files:

  • apps/core-app/src/main/modules/box-tool/core-box/manager.ts
📚 Learning: 2025-11-29T07:45:45.435Z
Learnt from: CR
Repo: talex-touch/tuff PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-29T07:45:45.435Z
Learning: Applies to **/plugins/**/*.{ts,tsx,js,jsx} : Handle backward compatibility in plugins by checking if query is a string (legacy text-only query) before treating it as a TuffQuery object with inputs array.

Applied to files:

  • packages/utils/plugin/sdk/feature-sdk.ts
  • apps/core-app/src/main/modules/box-tool/search-engine/sort/tuff-sorter.ts
  • apps/core-app/src/main/modules/box-tool/core-box/window.ts
📚 Learning: 2025-11-29T07:46:02.249Z
Learnt from: CR
Repo: talex-touch/tuff PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-29T07:46:02.249Z
Learning: Applies to plugins/**/*.ts : Handle clipboard data in plugins by checking if query is a string (backward compatibility) or TuffQuery object with inputs array containing type-specific data

Applied to files:

  • packages/utils/plugin/sdk/feature-sdk.ts
  • apps/core-app/src/main/modules/box-tool/core-box/window.ts
📚 Learning: 2025-11-29T07:46:02.249Z
Learnt from: CR
Repo: talex-touch/tuff PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-29T07:46:02.249Z
Learning: Applies to apps/core-app/src/renderer/src/**/*.{ts,tsx,vue} : Use Vue 3, TypeScript, Pinia for state management, and UnoCSS for styling in renderer process

Applied to files:

  • apps/core-app/src/main/modules/plugin/widget/processors/vue-processor.ts
📚 Learning: 2025-11-29T07:45:45.435Z
Learnt from: CR
Repo: talex-touch/tuff PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-29T07:45:45.435Z
Learning: Applies to apps/core-app/src/renderer/src/**/*.vue : Use Element Plus 2.10.4+ for UI components in the renderer process.

Applied to files:

  • apps/core-app/src/main/modules/plugin/widget/processors/vue-processor.ts
  • apps/core-app/src/renderer/src/views/box/CoreBox.vue
📚 Learning: 2025-11-29T07:45:45.435Z
Learnt from: CR
Repo: talex-touch/tuff PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-29T07:45:45.435Z
Learning: Load modules sequentially after Electron ready event in the specified order: DatabaseModule → StorageModule → ShortcutModule → ExtensionLoaderModule → CommonChannelModule → PluginModule → PluginLogModule → CoreBoxModule → TrayHolderModule → AddonOpenerModule → ClipboardModule → TuffDashboardModule → FileSystemWatcher → FileProtocolModule → TerminalModule.

Applied to files:

  • apps/core-app/src/main/modules/box-tool/core-box/ipc.ts
🧬 Code graph analysis (12)
apps/core-app/src/renderer/src/modules/division-box/store/division-box.ts (3)
apps/core-app/src/renderer/src/modules/division-box/index.ts (1)
  • useDivisionBoxStore (18-18)
apps/core-app/src/renderer/src/modules/division-box/types.ts (1)
  • DivisionBoxStoreState (35-47)
apps/core-app/src/renderer/src/modules/storage/division-box-storage.ts (1)
  • divisionBoxStorage (31-34)
apps/core-app/src/renderer/src/modules/storage/division-box-storage.ts (1)
packages/utils/renderer/storage/base-storage.ts (2)
  • TouchStorage (121-483)
  • createStorageProxy (104-114)
apps/core-app/src/renderer/src/modules/storage/prompt-library.ts (2)
apps/core-app/src/renderer/src/modules/intelligence/prompt-types.ts (1)
  • PromptTemplate (1-10)
packages/utils/renderer/storage/base-storage.ts (2)
  • TouchStorage (121-483)
  • createStorageProxy (104-114)
apps/core-app/src/renderer/src/modules/box/adapter/transport/key-transport.ts (3)
apps/core-app/src/main/modules/box-tool/core-box/key-transport.ts (2)
  • ForwardedKeyEvent (10-25)
  • UIViewStateResponse (30-37)
packages/utils/channel/index.ts (1)
  • ITouchClientChannel (100-133)
apps/core-app/src/renderer/src/modules/box/adapter/transport/core-box-transport.ts (1)
  • createCoreBoxTransport (14-41)
apps/core-app/src/main/modules/box-tool/core-box/key-transport.ts (6)
apps/core-app/src/renderer/src/modules/box/adapter/transport/key-transport.ts (2)
  • ForwardedKeyEvent (7-22)
  • UIViewStateResponse (27-34)
packages/utils/plugin/sdk/feature-sdk.ts (1)
  • ForwardedKeyEvent (20-28)
apps/core-app/src/main/utils/logger.ts (1)
  • createLogger (203-245)
apps/core-app/src/main/modules/box-tool/core-box/transport/core-box-transport.ts (1)
  • coreBoxTransport (41-41)
apps/core-app/src/main/modules/box-tool/core-box/window.ts (1)
  • windowManager (1100-1100)
apps/core-app/src/main/modules/box-tool/core-box/manager.ts (1)
  • coreBoxManager (209-209)
apps/core-app/src/main/modules/box-tool/core-box/manager.ts (2)
apps/core-app/src/main/modules/box-tool/core-box/window.ts (1)
  • show (277-296)
apps/core-app/src/main/core/index.ts (1)
  • genTouchApp (12-20)
apps/core-app/src/renderer/src/modules/plugin/widget-registry.ts (1)
apps/core-app/src/renderer/src/modules/market/providers/base-provider.ts (1)
  • id (29-31)
packages/utils/plugin/sdk/feature-sdk.ts (3)
apps/core-app/src/main/modules/box-tool/core-box/key-transport.ts (1)
  • ForwardedKeyEvent (10-25)
apps/core-app/src/renderer/src/modules/box/adapter/transport/key-transport.ts (1)
  • ForwardedKeyEvent (7-22)
packages/utils/plugin/channel.ts (2)
  • TouchChannel (53-310)
  • ensureIpcRenderer (37-47)
apps/core-app/src/renderer/src/modules/hooks/usePromptManager.ts (2)
apps/core-app/src/renderer/src/modules/storage/prompt-library.ts (1)
  • promptLibraryStorage (50-53)
apps/core-app/src/renderer/src/modules/intelligence/prompt-types.ts (1)
  • PromptTemplate (1-10)
apps/core-app/src/main/modules/plugin/widget/widget-manager.ts (3)
apps/core-app/src/main/modules/plugin/widget/widget-processor.ts (1)
  • WidgetCompilationContext (21-28)
apps/core-app/src/main/modules/plugin/widget/widget-compiler.ts (1)
  • compileWidgetSource (28-54)
packages/utils/renderer/hooks/initialize.ts (1)
  • isDev (205-205)
apps/core-app/src/main/modules/tray/tray-manager.ts (1)
apps/core-app/src/main/modules/tray/tray-icon-provider.ts (1)
  • TrayIconProvider (15-296)
apps/core-app/src/main/modules/box-tool/search-engine/sort/tuff-sorter.ts (2)
packages/utils/core-box/tuff/tuff-dsl.ts (1)
  • TuffItem (47-104)
apps/core-app/src/main/modules/box-tool/search-engine/types.ts (1)
  • TuffItem (29-29)

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Signed-off-by: TalexDreamSoul <59305952+TalexDreamSoul@users.noreply.github.com>
TalexDreamSoul and others added 3 commits December 6, 2025 16:22
…f-sorter.ts

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Signed-off-by: TalexDreamSoul <59305952+TalexDreamSoul@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Signed-off-by: TalexDreamSoul <59305952+TalexDreamSoul@users.noreply.github.com>
- Add support for dynamic imports, re-exports and side-effect imports in vue-processor
- Remove unused allowedModules field from WidgetCompilationContext
- Pre-load and validate all allowed packages at startup in widget-registry
- Throw fatal error if any required module fails to preload
- Update keyboard API docs to show correct window.$channel usage
@TalexDreamSoul TalexDreamSoul merged commit 086af07 into master Dec 6, 2025
3 checks passed
@TalexDreamSoul TalexDreamSoul deleted the fix/2.4.7-251201 branch December 6, 2025 08:28
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