Skip to content

feat: add remote control page, update next dependency #3501

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 13, 2025

Conversation

zzcr
Copy link
Member

@zzcr zzcr commented Jun 13, 2025

feat: 添加遥控器页面,更新next依赖

PR

PR Checklist

Please check if your PR fulfills the following requirements:

  • The commit message follows our Commit Message Guidelines
  • Tests for the changes have been added (for bug fixes / features)
  • Docs have been added / updated (for bug fixes / features)

PR Type

What kind of change does this PR introduce?

  • Bugfix
  • Feature
  • Code style update (formatting, local variables)
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • CI related changes
  • Documentation content changes
  • Other... Please describe:

What is the current behavior?

Issue Number: N/A

What is the new behavior?

Does this PR introduce a breaking change?

  • Yes
  • No

Other information

Summary by CodeRabbit

  • New Features

    • Introduced a new "Remoter" view with a bottom drawer to switch between chat and voice controllers.
    • Added a voice controller component featuring real-time speech recognition and voice message input.
    • Added a message card component for enhanced chat message display with distinct styling and localized timestamps.
  • Enhancements

    • Improved session management by integrating session IDs into client proxy options and making session data reactive.
    • Updated session URL construction to use a stable domain for consistent navigation.
  • Chores

    • Updated dependencies to newer versions and removed obsolete packages for better stability.

Copy link

coderabbitai bot commented Jun 13, 2025

Walkthrough

The changes introduce new features and enhancements to a Vue 3 application. A new "remoter" route and associated views are added, including components for chat message display and voice interaction. Dependency updates and refactoring improve session handling and reactivity. Several new components implement chat UI and speech recognition functionality.

Changes

File(s) Change Summary
examples/sites/package.json Updated @opentiny/vue-docs version; updated @opentiny/next-vue version; removed @opentiny/next dependency.
examples/sites/src/App.vue Imported $session; passed sessionId via proxyOptions in useNextClient call; changed SSE URL.
examples/sites/src/composable/utils.ts Made globalConversation reactive; exported $session from storage.
examples/sites/src/components/MessageCard.vue New: Added chat message display component with role-based styling and timestamp formatting.
examples/sites/src/router.js Added lazy-loaded Remoter component and new route for /remoter.
examples/sites/src/views/comprehensive/index.vue Changed URL generation for sessionUrl to use new domain; reformatted CSS box-shadow declarations.
examples/sites/src/views/remoter/index.vue New: Added main "Remoter" component with encrypted session ID handling and controller selection UI.
examples/sites/src/views/remoter/sound.vue New: Added voice recording and speech recognition chat component with real-time feedback and error handling.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant Router
  participant RemoterView
  participant globalConversation
  participant RobotChat
  participant Sound

  User->>Router: Navigate to /remoter route
  Router->>RemoterView: Load Remoter component
  RemoterView->>RemoterView: Decrypt session ID from URL
  RemoterView->>globalConversation: Set sessionId
  RemoterView->>User: Show drawer with controller options
  User->>RemoterView: Select Voice or Chat controller
  RemoterView->>Sound: Show Sound component (if selected)
  RemoterView->>RobotChat: Show RobotChat component (if selected)
Loading
sequenceDiagram
  participant User
  participant Sound
  participant SpeechRecognition
  participant useTinyRobot
  participant MessageList

  User->>Sound: Tap and hold record button
  Sound->>SpeechRecognition: Start listening
  SpeechRecognition-->>Sound: Transcribe speech to text
  Sound->>useTinyRobot: Send transcribed message
  useTinyRobot-->>Sound: Receive response
  Sound->>MessageList: Update with new messages
  User->>Sound: Release record button or timeout
  Sound->>SpeechRecognition: Stop listening
Loading

Poem

🐇
A remoter route hops into view,
With voice and chat, there's much to do!
Session secrets now decrypted,
Messages styled and time depicted.
Speak aloud, let rabbits hear—
In Vue, new features now appear!
🎤💬

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

examples/sites/src/App.vue

Oops! Something went wrong! :(

ESLint: 8.57.1

ESLint couldn't find the plugin "eslint-plugin-vue".

(The package "eslint-plugin-vue" was not found when loaded as a Node module from the directory "".)

It's likely that the plugin isn't installed correctly. Try reinstalling by running the following:

npm install eslint-plugin-vue@latest --save-dev

The plugin "eslint-plugin-vue" was referenced from the config file in ".eslintrc.js » @antfu/eslint-config » @antfu/eslint-config-vue".

If you still can't figure out the problem, please stop by https://eslint.org/chat/help to chat with the team.

examples/sites/src/views/comprehensive/index.vue

Oops! Something went wrong! :(

ESLint: 8.57.1

ESLint couldn't find the plugin "eslint-plugin-vue".

(The package "eslint-plugin-vue" was not found when loaded as a Node module from the directory "".)

It's likely that the plugin isn't installed correctly. Try reinstalling by running the following:

npm install eslint-plugin-vue@latest --save-dev

The plugin "eslint-plugin-vue" was referenced from the config file in ".eslintrc.js » @antfu/eslint-config » @antfu/eslint-config-vue".

If you still can't figure out the problem, please stop by https://eslint.org/chat/help to chat with the team.


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 16174d6 and 87888c8.

📒 Files selected for processing (3)
  • examples/sites/package.json (2 hunks)
  • examples/sites/src/App.vue (2 hunks)
  • examples/sites/src/views/comprehensive/index.vue (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • examples/sites/src/views/comprehensive/index.vue
  • examples/sites/src/App.vue
  • examples/sites/package.json

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@github-actions github-actions bot added the enhancement New feature or request (功能增强) label Jun 13, 2025
Copy link

@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: 6

🧹 Nitpick comments (4)
examples/sites/src/composable/utils.ts (1)

14-17: Guard the mutable global with accessors

globalConversation is now a writable reactive singleton. Any import can mutate it directly, which makes tracking changes difficult and hampers debugging.
Consider exposing setter / getter helpers (or readonly(globalConversation)) and updating it only through explicit functions.

examples/sites/src/views/comprehensive/index.vue (1)

92-100: Build the remoter URL with the URL API to avoid double “?”

If location.href already contains a query string you’ll end up with two ? characters.
Safer construction:

-      sessionUrl.value = `${location.href.replace('comprehensive', 'remoter')}?id=${secretId}`
+      const url = new URL(location.href)
+      url.pathname = url.pathname.replace('comprehensive', 'remoter')
+      url.search = `?id=${secretId}`
+      sessionUrl.value = url.toString()
examples/sites/src/views/remoter/index.vue (1)

21-22: Fix inconsistent comment

The comment mentions storing to window.sessionId but the code stores to globalConversation.sessionId.

-  // 存储解密后的 id 到 window.sessionId
+  // 存储解密后的 id 到 globalConversation.sessionId
examples/sites/src/components/MessageCard.vue (1)

30-37: Consider making locale configurable for internationalization

The time format is hardcoded to 'zh-CN' locale. For better internationalization support, consider making this configurable.

 interface Props {
   role: 'user' | 'assistant'
   message: string
   timestamp: number
+  locale?: string
 }

 const props = defineProps<Props>()

 const formatTime = computed(() => {
   const date = new Date(props.timestamp)
-  return date.toLocaleTimeString('zh-CN', {
+  return date.toLocaleTimeString(props.locale || 'zh-CN', {
     hour: '2-digit',
     minute: '2-digit',
     hour12: false
   })
 })
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 299734c and 16174d6.

📒 Files selected for processing (8)
  • examples/sites/package.json (1 hunks)
  • examples/sites/src/App.vue (2 hunks)
  • examples/sites/src/components/MessageCard.vue (1 hunks)
  • examples/sites/src/composable/utils.ts (1 hunks)
  • examples/sites/src/router.js (2 hunks)
  • examples/sites/src/views/comprehensive/index.vue (1 hunks)
  • examples/sites/src/views/remoter/index.vue (1 hunks)
  • examples/sites/src/views/remoter/sound.vue (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build
🔇 Additional comments (7)
examples/sites/src/composable/utils.ts (1)

8-10:

✅ Verification successful

Ensure that storage.ts actually re-exports $session

$session is now being re-exported and referenced all over the app, but the file ./storage is not shown here.
If that module does not export a const $session (or similar) you will hit a compile-time error.

Run a quick grep to make sure the export exists:


🏁 Script executed:

#!/bin/bash
# Check that `$session` is exported from any storage file
rg --context 2 $'export.*\\$session'

Length of output: 1328


Confirmed export of $session in storage.ts
Verified that examples/sites/src/composable/storage.ts includes export { $session, $local, $cache, useAutoStore }. No further changes needed.

examples/sites/package.json (1)

30-30:

✅ Verification successful

Verify availability & compatibility of @opentiny/[email protected]

Jumping from an alpha tag to 0.0.1 will break CI if that version is not published or if its peer-deps changed.


🏁 Script executed:

#!/bin/bash
npm view @opentiny/[email protected] version peerDependencies

Length of output: 517


Let’s check if there are any peer dependencies for version 0.0.1:


🏁 Script executed:

#!/bin/bash
npm view @opentiny/[email protected] peerDependencies --json

Length of output: 59


Let’s fetch the full package metadata to confirm there are no hidden peerDependencies or other breaking changes:


🏁 Script executed:

#!/bin/bash
npm view @opentiny/[email protected] --json

Length of output: 2466


@opentiny/[email protected] is published and defines no peerDependencies
I confirmed via npm view @opentiny/[email protected] --json that version 0.0.1 exists and has no peerDependencies, so upgrading from the alpha tag won’t break CI.

examples/sites/src/App.vue (1)

20-20: Import looks good

Nothing to flag here.

examples/sites/src/router.js (1)

28-32: Route outside Layout – confirm UX intent

comprehensive is rendered inside Layout, but the new remoter route is not.
If that’s deliberate (e.g., full-screen mobile view) please ignore; otherwise you may lose the common header/footer.

examples/sites/src/components/MessageCard.vue (1)

1-117: Well-structured component implementation

The component is cleanly implemented with proper TypeScript types, computed properties, and role-based styling. Good use of scoped styles and semantic class names.

examples/sites/src/views/remoter/sound.vue (2)

1-283: Comprehensive voice recording implementation

The component demonstrates good practices including:

  • Proper error handling for various speech recognition errors
  • Recording time limits to prevent excessive resource usage
  • Cleanup on component unmount
  • User-friendly error messages
  • Touch event handling for mobile devices

276-281:

✅ Verification successful

Verify the correct API method for cleanup

The standard SpeechRecognition API uses stop() method, not abort(). Verify if abort() is supported across browsers.


🏁 Script executed:

#!/bin/bash
# Description: Search for SpeechRecognition API usage patterns and verify abort() method availability

# Search for other SpeechRecognition usage patterns in the codebase
rg -A 3 -B 3 "recognition\.(stop|abort)" --type ts --type js --type vue

# Search for any documentation or comments about SpeechRecognition cleanup
rg -i "speechrecognition.*(cleanup|abort|stop)" --type ts --type js --type vue

Length of output: 210


🌐 Web query:

Does the Web Speech API SpeechRecognition interface support the abort() method, or should stop() be used instead?

💡 Result:

The Web Speech API SpeechRecognition interface supports both the abort() and stop() methods for stopping speech recognition, but they behave differently and are intended for distinct use cases:

  • abort() method: This method immediately stops the speech recognition service from listening to incoming audio and does not attempt to return a final SpeechRecognitionResult. It is used when you want to cancel speech recognition without processing or returning any results. The user agent will fire the end event once the service has stopped[1][2][3][7][8].

  • stop() method: This method stops the service from listening, but it will attempt to process any audio captured so far and return a result if possible (by firing the result or nomatch events before the end event)[1].

Here’s a comparison:

Method Description Returns Result?
abort() Immediately stops recognition, does not return a result, cancels processing mid-stream No
stop() Stops recognition, attempts to return a result with captured audio Yes (if possible)

Conclusion:
You should use abort() when you need to immediately cancel recognition and discard any partial results, and stop() when you wish to end recognition but still receive recognition results for the audio processed so far. Both methods are available and supported by the SpeechRecognition interface in the Web Speech API[1][2][3][7].

Citations:


No change needed: abort() is supported for immediate cleanup

The Web Speech API’s SpeechRecognition interface provides both abort() and stop() methods.

  • abort() immediately cancels recognition without returning any results (fires the end event).
  • stop() ends recognition but tries to process and return any captured audio before firing end.

In this cleanup scenario—where you want to discard any partial results—using recognition.abort() is appropriate.

Comment on lines 34 to 37
const { sessionId } = useNextClient({
clientInfo: { name: 'tiny-vue-website', version: '1.0.0' },
proxyOptions: { url: 'https://39.108.160.245/sse', token: '' }
proxyOptions: { url: 'https://39.108.160.245/sse', token: '', sessionId: $session.sessionId }
})
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Persist the issued sessionId back to $session

$session.sessionId is passed once to useNextClient, but when the server returns a new sessionId you only copy it to globalConversation, not back to storage.
On a page reload you’ll lose the session.

 watch(
   () => sessionId.value,
   (newVal) => {
     if (newVal) {
       globalConversation.sessionId = newVal
+      $session.sessionId = newVal   // keep storage in sync
     }
   }
 )
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const { sessionId } = useNextClient({
clientInfo: { name: 'tiny-vue-website', version: '1.0.0' },
proxyOptions: { url: 'https://39.108.160.245/sse', token: '' }
proxyOptions: { url: 'https://39.108.160.245/sse', token: '', sessionId: $session.sessionId }
})
watch(
() => sessionId.value,
(newVal) => {
if (newVal) {
globalConversation.sessionId = newVal
$session.sessionId = newVal // keep storage in sync
}
}
)
🤖 Prompt for AI Agents
In examples/sites/src/App.vue around lines 34 to 37, the sessionId returned from
useNextClient is assigned to a local variable but not persisted back to
$session.sessionId. To fix this, update the code to assign the new sessionId
value back to $session.sessionId whenever it changes, ensuring the session is
stored persistently and not lost on page reload.

Comment on lines +10 to +11
// 加密密钥,需要和生成二维码的页面保持一致
const secretKey = 'secret-session-id'
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Critical security issue: Hardcoded encryption key

The secret key is hardcoded in the client-side code, which is a significant security vulnerability. Anyone can view this key and decrypt the session IDs.

Consider these more secure alternatives:

  1. Use server-side decryption and only pass the decrypted session ID to the client
  2. Use environment variables or configuration management for the key
  3. Implement proper key rotation and management
🤖 Prompt for AI Agents
In examples/sites/src/views/remoter/index.vue around lines 10 to 11, the
secretKey is hardcoded in the client-side code, posing a critical security risk.
To fix this, remove the hardcoded key from the client code and instead retrieve
the secret key securely from the server or use environment variables injected at
build time. Implement server-side decryption of session IDs and only send
decrypted data to the client, ensuring the key is never exposed in the frontend
code. Also, consider adding key rotation and secure key management practices.

Comment on lines +24 to +27
const showMoter = (type) => {
state.isShow = false
state[type] = true
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Improve function naming and parameter clarity

The function name "showMoter" appears to be a typo, and the parameter name type is too generic for its specific use case.

-const showMoter = (type) => {
+const showController = (controllerType: 'showChat' | 'showSound') => {
   state.isShow = false
-  state[type] = true
+  state[controllerType] = true
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const showMoter = (type) => {
state.isShow = false
state[type] = true
}
const showController = (controllerType: 'showChat' | 'showSound') => {
state.isShow = false
state[controllerType] = true
}
🤖 Prompt for AI Agents
In examples/sites/src/views/remoter/index.vue around lines 24 to 27, rename the
function "showMoter" to a more descriptive and correctly spelled name that
reflects its purpose, such as "showMotor" or "displayMotor". Also, rename the
parameter "type" to a more specific name that clearly indicates what kind of
value it expects, for example "motorType" or "sectionName". Update all
references to this function and parameter accordingly.

Comment on lines +44 to +46
<tiny-button @click="showMoter('showSound')" type="info" size="large">语音控制器</tiny-button>

<tiny-button @click="showMoter('showChat')" type="info" size="large">综合控制器</tiny-button>
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Update function calls to match refactored name

If you apply the suggested refactor above, update these function calls accordingly.

-        <tiny-button @click="showMoter('showSound')" type="info" size="large">语音控制器</tiny-button>
+        <tiny-button @click="showController('showSound')" type="info" size="large">语音控制器</tiny-button>

-        <tiny-button @click="showMoter('showChat')" type="info" size="large">综合控制器</tiny-button>
+        <tiny-button @click="showController('showChat')" type="info" size="large">综合控制器</tiny-button>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<tiny-button @click="showMoter('showSound')" type="info" size="large">语音控制器</tiny-button>
<tiny-button @click="showMoter('showChat')" type="info" size="large">综合控制器</tiny-button>
<tiny-button @click="showController('showSound')" type="info" size="large">语音控制器</tiny-button>
<tiny-button @click="showController('showChat')" type="info" size="large">综合控制器</tiny-button>
🤖 Prompt for AI Agents
In examples/sites/src/views/remoter/index.vue around lines 44 to 46, the
function calls to showMoter need to be updated to match the refactored function
name. Identify the new function name from the refactor and replace all instances
of showMoter with the updated function name in these button click handlers.

Comment on lines +88 to +89
const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent)

Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Browser detection using user agent is fragile

User agent string parsing is unreliable and can be spoofed. Consider using feature detection instead.

-const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent)
+// Feature detection for Safari-specific behavior
+const isSafari = 'webkitSpeechRecognition' in window && !('SpeechRecognition' in window)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent)
// Feature detection for Safari-specific behavior
const isSafari = 'webkitSpeechRecognition' in window && !('SpeechRecognition' in window)
🤖 Prompt for AI Agents
In examples/sites/src/views/remoter/sound.vue around lines 88 to 89, the code
uses user agent string parsing to detect Safari browser, which is unreliable and
can be spoofed. Replace this user agent check with feature detection by
identifying a unique Safari-specific feature or behavior, such as checking for
the existence of a Safari-only API or CSS property, to determine if the browser
is Safari more reliably.

Comment on lines +222 to +227
} catch (error) {
handleRecognitionError({
error: 'start_error',
message: '启动语音识别失败,请重试'
} as SpeechRecognitionErrorEvent)
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Avoid manually constructing error event objects

Creating a manual error object might not match the actual SpeechRecognitionErrorEvent interface, potentially causing issues in the error handler.

   } catch (error) {
-    handleRecognitionError({
-      error: 'start_error',
-      message: '启动语音识别失败,请重试'
-    } as SpeechRecognitionErrorEvent)
+    // Handle start error directly without simulating an event
+    stopRecording()
+    TinyNotify({
+      type: 'error',
+      title: '语音识别出错',
+      message: '启动语音识别失败,请重试',
+      position: 'top-right',
+      duration: 3000
+    })
   }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
} catch (error) {
handleRecognitionError({
error: 'start_error',
message: '启动语音识别失败,请重试'
} as SpeechRecognitionErrorEvent)
}
} catch (error) {
// Handle start error directly without simulating an event
stopRecording()
TinyNotify({
type: 'error',
title: '语音识别出错',
message: '启动语音识别失败,请重试',
position: 'top-right',
duration: 3000
})
}
🤖 Prompt for AI Agents
In examples/sites/src/views/remoter/sound.vue around lines 222 to 227, avoid
manually constructing an object as SpeechRecognitionErrorEvent because it may
not conform to the actual interface. Instead, pass the caught error object
directly to handleRecognitionError or create a proper error event using the
SpeechRecognition API if possible, ensuring the error handler receives a valid
event object.

@zzcr zzcr merged commit 63a172a into release-3.24.0 Jun 13, 2025
11 checks passed
@zzcr zzcr deleted the zzc/add-remote-0613 branch June 13, 2025 09:25
zzcr added a commit that referenced this pull request Jun 14, 2025
* feat: New MCP comprehensive example added to the official website (#3497)

* feat: 官网新增mcp综合示例

* fix: 修复 tiny-robot-chat 组件中的提示项和建议项的传递逻辑,优化 Demo 组件的 QR 码展示样式

* fix: 修复引入路径问题

* chore: Update changelog and add TinyVue intelligent component access documentation (#3498)

* chore: 更新changelog,并添加TinyVue智能化组件接入文档

* chore: 添加菜单优化文档

* chore: 更新mcp.md文档中的sessionId说明,简化调试提示

* chore: 更新mcp-en.md文档中的标题和内容,统一语言为英文

* feat: add remote control page, update next dependency (#3501)

* feat: 添加遥控器页面,更新next依赖

* chore: 修改代理为https url

* feat: 更新会话ID的处理逻辑

* fix: 更新依赖版本约束以支持更高版本

* fix: 更新版本号至3.24.4
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request (功能增强)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant