-
Notifications
You must be signed in to change notification settings - Fork 131
Integrate new AI assistant #3757
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
base: master
Are you sure you want to change the base?
Changes from all commits
6d756dc
35ccd75
56e28f7
b07e96b
76acb67
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -215,12 +215,17 @@ | |
| "description": "Remote-doctype required to send anonymized measures to the DACC shared among mycozy.eu's Cozy." | ||
| }, | ||
| "chatConversations": { | ||
| "description": "Required by the cozy Assistant", | ||
| "description": "Required by the AI Assistant to show conversations", | ||
| "type": "io.cozy.ai.chat.conversations", | ||
| "verbs": ["GET", "POST"] | ||
| "verbs": ["ALL"] | ||
| }, | ||
| "assistants": { | ||
| "type": "io.cozy.ai.chat.assistants", | ||
| "verbs": ["ALL"], | ||
| "description": "Required to fetch, create and update AI assistants" | ||
| }, | ||
|
Comment on lines
217
to
226
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider using least-privilege permissions instead of Both If the assistant only needs to read, create, and update: 🛡️ Suggested restriction "chatConversations": {
"description": "Required by the AI Assistant to show conversations",
"type": "io.cozy.ai.chat.conversations",
- "verbs": ["ALL"]
+ "verbs": ["GET", "POST", "PUT", "PATCH"]
},
"assistants": {
"type": "io.cozy.ai.chat.assistants",
- "verbs": ["ALL"],
+ "verbs": ["GET", "POST", "PUT", "PATCH"],
"description": "Required to fetch, create and update AI assistants"
},If DELETE is genuinely required (e.g., for clearing conversation history), the current configuration is acceptable. 🤖 Prompt for AI Agents |
||
| "chatEvents": { | ||
| "description": "Required by the cozy Assistant", | ||
| "description": "Required by the AI Assistant to receive realtime events", | ||
| "type": "io.cozy.ai.chat.events", | ||
| "verbs": ["GET"] | ||
| }, | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -11,6 +11,8 @@ export const DOCTYPE_PHOTOS_SETTINGS = 'io.cozy.photos.settings' | |||||||||||||||||||||||||||||||||||||||||
| export const DOCTYPE_APPS = 'io.cozy.apps' | ||||||||||||||||||||||||||||||||||||||||||
| export const DOCTYPE_CONTACTS = 'io.cozy.contacts' | ||||||||||||||||||||||||||||||||||||||||||
| export const DOCTYPE_KONNECTORS = 'io.cozy.konnectors' | ||||||||||||||||||||||||||||||||||||||||||
| export const DOCTYPE_AI_CHAT_CONVERSATIONS = 'io.cozy.ai.chat.conversations' | ||||||||||||||||||||||||||||||||||||||||||
| export const DOCTYPE_AI_CHAT_ASSISTANTS = 'io.cozy.ai.chat.assistants' | ||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+14
to
+15
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Check how other doctypes without schema entries are handled
rg -n 'RealTimeQueries' --type=js -A 2 -B 2
# Check if there are other doctypes used without schema entries
rg -n 'DOCTYPE_' src/lib/doctypes.jsRepository: linagora/twake-drive Length of output: 7153 🏁 Script executed: cat -n src/lib/doctypes.jsRepository: linagora/twake-drive Length of output: 1979 Add a schema entry for the
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||
| export const DOCTYPE_CONTACTS_VERSION = 2 | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| export const schema = { | ||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -33,5 +35,15 @@ export const schema = { | |||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||
| groups: { doctype: Group.doctype }, | ||||||||||||||||||||||||||||||||||||||||||
| versions: { doctype: 'io.cozy.files.versions' }, | ||||||||||||||||||||||||||||||||||||||||||
| conversations: { | ||||||||||||||||||||||||||||||||||||||||||
| doctype: DOCTYPE_AI_CHAT_CONVERSATIONS, | ||||||||||||||||||||||||||||||||||||||||||
| attributes: {}, | ||||||||||||||||||||||||||||||||||||||||||
| relationships: { | ||||||||||||||||||||||||||||||||||||||||||
| assistant: { | ||||||||||||||||||||||||||||||||||||||||||
| type: 'has-one', | ||||||||||||||||||||||||||||||||||||||||||
| doctype: 'io.cozy.ai.chat.assistants' | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+38
to
+47
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion | 🟠 Major Use the constant instead of hardcoded doctype string. Line 44 uses the literal string ♻️ Suggested fix conversations: {
doctype: DOCTYPE_AI_CHAT_CONVERSATIONS,
attributes: {},
relationships: {
assistant: {
type: 'has-one',
- doctype: 'io.cozy.ai.chat.assistants'
+ doctype: DOCTYPE_AI_CHAT_ASSISTANTS
}
}
},📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||
| ...extraDoctypes | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,6 +7,7 @@ import flag from 'cozy-flags' | |
| import ExternalRedirect from './ExternalRedirect' | ||
| import Index from './Index' | ||
| import AIAssistantPaywallView from '../views/AI/AIAssistantPaywallView' | ||
| import AssistantLayout from '../views/Assistant/AssistantLayout' | ||
| import { DriveFolderView } from '../views/Drive/DriveFolderView' | ||
| import FilesViewerDrive from '../views/Drive/FilesViewerDrive' | ||
| import OnlyOfficeView from '../views/OnlyOffice' | ||
|
|
@@ -54,6 +55,10 @@ import { SharedDriveFolderView } from '@/modules/views/SharedDrive/SharedDriveFo | |
| import { TrashDestroyView } from '@/modules/views/Trash/TrashDestroyView' | ||
| import { TrashEmptyView } from '@/modules/views/Trash/TrashEmptyView' | ||
|
|
||
| const filteredBarRoutes = BarRoutes.filter( | ||
| r => r.props?.path !== 'assistant/:conversationId' | ||
| ) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do we need to filter bar routes here?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. And why we did not have to do it in home? cc @lethemanh |
||
|
|
||
| const FilesRedirect = () => { | ||
| const { folderId } = useParams() | ||
| return <Navigate to={`/folder/${folderId}`} replace={true} /> | ||
|
|
@@ -76,6 +81,8 @@ const AppRoute = () => ( | |
| <Route path="note/:fileId" element={<PublicNoteRedirect />} /> | ||
| <Route path="note/:driveId/:fileId" element={<PublicNoteRedirect />} /> | ||
|
|
||
| <Route path="assistant/:conversationId" element={<AssistantLayout />} /> | ||
|
|
||
|
Comment on lines
+84
to
+85
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ❌ Getting worse: Large Method |
||
| <Route element={<Layout />}> | ||
| <Route path="upload" element={<UploaderComponent />} /> | ||
| <Route path="/files/:folderId" element={<FilesRedirect />} /> | ||
|
|
@@ -244,7 +251,7 @@ const AppRoute = () => ( | |
| <Route path="move" element={<MoveFilesView />} /> | ||
| </Route> | ||
|
|
||
| {BarRoutes.map(BarRoute => BarRoute)} | ||
| {filteredBarRoutes} | ||
| </Route> | ||
| </SentryRoutes> | ||
| ) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| import cx from 'classnames' | ||
| import React from 'react' | ||
|
|
||
| import { BarComponent } from 'cozy-bar' | ||
| import { RealTimeQueries } from 'cozy-client' | ||
| import { AiText, AssistantView } from 'cozy-search' | ||
| import TwakeWorkplace from 'cozy-ui/transpiled/react/Icons/TwakeWorkplace' | ||
| import { Layout as LayoutUI } from 'cozy-ui/transpiled/react/Layout' | ||
|
|
||
| import styles from './assistant.styl' | ||
|
|
||
| import { | ||
| DOCTYPE_AI_CHAT_ASSISTANTS, | ||
| DOCTYPE_AI_CHAT_CONVERSATIONS | ||
| } from '@/lib/doctypes' | ||
|
|
||
| const AssistantLayout = () => { | ||
| return ( | ||
| <LayoutUI monoColumn> | ||
| <RealTimeQueries doctype={DOCTYPE_AI_CHAT_CONVERSATIONS} /> | ||
| <RealTimeQueries doctype={DOCTYPE_AI_CHAT_ASSISTANTS} /> | ||
| <BarComponent | ||
| searchOptions={{ enabled: true }} | ||
| appSlug="home" // hack to hide the first Twake Workplace icon | ||
| appIcon={TwakeWorkplace} | ||
| appTextIcon={AiText} | ||
| disableInternalStore | ||
| componentsProps={{ | ||
| Wrapper: { | ||
| className: cx('u-elevation-0', styles['assistant-topbar-border']) | ||
| } | ||
| }} | ||
| /> | ||
| <main className={styles['assistant-view']}> | ||
| <AssistantView /> | ||
| </main> | ||
| </LayoutUI> | ||
| ) | ||
| } | ||
|
Comment on lines
+17
to
+39
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Check if AssistantView expects a conversationId prop or uses useParams internally
rg -n --type=js 'AssistantView' -A 10 -B 2
# Check cozy-search for AssistantView props
ast-grep --pattern 'export $_ AssistantView'Repository: linagora/twake-drive Length of output: 1702 🏁 Script executed: # Find router/route configuration files
fd -type f -name "*route*" -o -name "*router*" | head -20Repository: linagora/twake-drive Length of output: 234 🏁 Script executed: # Search for conversationId usage in the codebase
rg -n "conversationId" --type=js | head -20Repository: linagora/twake-drive Length of output: 271 🏁 Script executed: # Search for useParams usage in Assistant-related files
rg -n "useParams" --type=js | grep -i assistantRepository: linagora/twake-drive Length of output: 46 🏁 Script executed: # Check the file structure around AssistantLayout for route configuration
rg -n "assistant/:conversationId\|:/conversationId" --type=jsRepository: linagora/twake-drive Length of output: 46 🏁 Script executed: # Search for conversationId usage more carefully
rg "conversationId" -nRepository: linagora/twake-drive Length of output: 271 🏁 Script executed: # Check the full AssistantLayout.jsx file
cat src/modules/views/Assistant/AssistantLayout.jsxRepository: linagora/twake-drive Length of output: 1072 🏁 Script executed: # Look for any context providers or hooks that might handle conversationId
rg "useParams|useContext|useState.*conversation" -n --type jsxRepository: linagora/twake-drive Length of output: 91 🏁 Script executed: # Check package.json for cozy-search version/documentation
rg "cozy-search" -nRepository: linagora/twake-drive Length of output: 374 🏁 Script executed: # Look for other route patterns with parameters to see how they're handled
rg "useParams" -nRepository: linagora/twake-drive Length of output: 6074 🏁 Script executed: # Check if there's any documentation or comments about AssistantView
rg -B3 -A3 "AssistantView" -nRepository: linagora/twake-drive Length of output: 1142 Extract The route is defined as 🤖 Prompt for AI Agents |
||
|
|
||
| export default AssistantLayout | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| @require 'settings/breakpoints.styl' | ||
| @require '../../../styles/coz-bar-size.styl' | ||
|
|
||
| .assistant-view | ||
| padding 0 | ||
| height 'calc(100vh - %s - 1px)' % $coz-bar-size | ||
| display flex | ||
| flex-direction column | ||
| flex 1 | ||
|
|
||
| +small-screen() | ||
| .assistant-view | ||
| margin-top $coz-bar-size | ||
|
|
||
| .assistant-topbar-border | ||
| border-bottom 1px solid var(--dividerColor) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The minimal
Responsestub may be insufficient.The empty
Responseclass lacks essential properties and methods (ok,status,json(),text(),body, etc.) that code may rely on. Ifassistant-streamor related code accesses these members, tests will fail silently or throw.Consider using a more complete polyfill:
♻️ Suggested improvement
Alternatively, use
whatwg-fetch(already in dependencies) orundici's fetch polyfill which provides a complete implementation.📝 Committable suggestion
🤖 Prompt for AI Agents