[web] Add AI workbench to alpha users (#29417)
Co-authored-by: Alf Eaton <alf.eaton@overleaf.com> GitOrigin-RevId: 79bb329932b1e6fcc88f648bca9cc4bee215cd41
This commit is contained in:
committed by
Copybot
co-authored by
Alf Eaton
parent
c84cfc815a
commit
8024fe2c58
@@ -2,6 +2,7 @@
|
||||
.eslint*
|
||||
.prettier*
|
||||
libraries/access-token-encryptor/**
|
||||
libraries/ai/**
|
||||
libraries/eslint-plugin/**
|
||||
libraries/fetch-utils/**
|
||||
libraries/logger/**
|
||||
|
||||
@@ -24,6 +24,7 @@ FROM base AS deps-prod
|
||||
|
||||
COPY package.json package-lock.json /overleaf/
|
||||
COPY libraries/access-token-encryptor/package.json /overleaf/libraries/access-token-encryptor/package.json
|
||||
COPY libraries/ai/package.json /overleaf/libraries/ai/package.json
|
||||
COPY libraries/eslint-plugin/package.json /overleaf/libraries/eslint-plugin/package.json
|
||||
COPY libraries/fetch-utils/package.json /overleaf/libraries/fetch-utils/package.json
|
||||
COPY libraries/logger/package.json /overleaf/libraries/logger/package.json
|
||||
@@ -58,6 +59,7 @@ FROM deps AS dev
|
||||
ARG SENTRY_RELEASE
|
||||
ENV SENTRY_RELEASE=$SENTRY_RELEASE
|
||||
COPY libraries/access-token-encryptor/ /overleaf/libraries/access-token-encryptor/
|
||||
COPY libraries/ai/ /overleaf/libraries/ai/
|
||||
COPY libraries/eslint-plugin/ /overleaf/libraries/eslint-plugin/
|
||||
COPY libraries/fetch-utils/ /overleaf/libraries/fetch-utils/
|
||||
COPY libraries/logger/ /overleaf/libraries/logger/
|
||||
@@ -95,6 +97,7 @@ RUN nice find /overleaf/services/web/public -name '*.js.map' -delete
|
||||
# copy source code and precompile pug images
|
||||
FROM deps-prod AS pug
|
||||
COPY libraries/access-token-encryptor/ /overleaf/libraries/access-token-encryptor/
|
||||
COPY libraries/ai/ /overleaf/libraries/ai/
|
||||
COPY libraries/eslint-plugin/ /overleaf/libraries/eslint-plugin/
|
||||
COPY libraries/fetch-utils/ /overleaf/libraries/fetch-utils/
|
||||
COPY libraries/logger/ /overleaf/libraries/logger/
|
||||
|
||||
@@ -570,6 +570,7 @@ IMAGE_SCRATCH ?= $(IMAGE_REPO):do-not-use-this-tag-for-deploys--it-is-used-for-e
|
||||
IMAGE_CACHE ?= $(IMAGE_REPO):cache-$(shell cat \
|
||||
$(MONOREPO)/package.json \
|
||||
$(MONOREPO)/package-lock.json \
|
||||
$(MONOREPO)/libraries/ai/package.json \
|
||||
$(MONOREPO)/libraries/access-token-encryptor/package.json \
|
||||
$(MONOREPO)/libraries/eslint-plugin/package.json \
|
||||
$(MONOREPO)/libraries/fetch-utils/package.json \
|
||||
|
||||
@@ -403,6 +403,7 @@ const _ProjectController = {
|
||||
'writefull-frontend-migration',
|
||||
'chat-edit-delete',
|
||||
'compile-timeout-remove-info',
|
||||
'ai-workbench',
|
||||
'compile-timeout-target-plans',
|
||||
].filter(Boolean)
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ const Usage = new Schema({
|
||||
const UserFeatureUsageSchema = new Schema({
|
||||
features: {
|
||||
aiErrorAssistant: Usage,
|
||||
aiWorkbench: Usage,
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
@@ -1040,6 +1040,7 @@ module.exports = {
|
||||
referenceSearchSetting: [],
|
||||
errorLogsComponents: [],
|
||||
referenceIndices: [],
|
||||
railEntries: [],
|
||||
},
|
||||
|
||||
moduleImportSequence: [
|
||||
|
||||
@@ -124,6 +124,7 @@
|
||||
"ai_feedback_the_suggestion_didnt_fix_the_error": "",
|
||||
"ai_feedback_the_suggestion_wasnt_the_best_fix_available": "",
|
||||
"ai_feedback_there_was_no_code_fix_suggested": "",
|
||||
"ai_workbench": "",
|
||||
"alignment": "",
|
||||
"all_borders": "",
|
||||
"all_events": "",
|
||||
|
||||
BIN
Binary file not shown.
@@ -49,6 +49,7 @@ export default /** @type {const} */ ([
|
||||
'shuffle',
|
||||
'smart_toy',
|
||||
'space_dashboard',
|
||||
'star',
|
||||
'strikethrough_s',
|
||||
'table_chart',
|
||||
'table_chart',
|
||||
|
||||
@@ -52,7 +52,9 @@ export default function RailPanel({
|
||||
>
|
||||
<Tab.Content className="ide-rail-tab-content">
|
||||
{railTabs
|
||||
.filter(({ hide }) => !hide)
|
||||
.filter(({ hide }) => {
|
||||
return typeof hide === 'function' ? !hide() : !hide
|
||||
})
|
||||
.map(({ key, component, mountOnFirstLoad }) => (
|
||||
<Tab.Pane
|
||||
eventKey={key}
|
||||
|
||||
@@ -26,6 +26,14 @@ import RailResizeHandle from './rail-resize-handle'
|
||||
import RailModals from './rail-modals'
|
||||
import RailOverflowDropdown from './rail-overflow-dropdown'
|
||||
import useRailOverflow from '../../hooks/use-rail-overflow'
|
||||
import importOverleafModules from '../../../../../macros/import-overleaf-module.macro'
|
||||
|
||||
const moduleRailEntries = (
|
||||
importOverleafModules('railEntries') as {
|
||||
import: { default: RailElement }
|
||||
path: string
|
||||
}[]
|
||||
).map(({ import: { default: element } }) => element)
|
||||
|
||||
export const RailLayout = () => {
|
||||
const { sendEvent } = useEditorAnalytics()
|
||||
@@ -79,6 +87,7 @@ export const RailLayout = () => {
|
||||
title: t('chat'),
|
||||
hide: !getMeta('ol-capabilities')?.includes('chat'),
|
||||
},
|
||||
...moduleRailEntries,
|
||||
],
|
||||
[t, features.trackChangesVisible, view]
|
||||
)
|
||||
@@ -125,7 +134,13 @@ export const RailLayout = () => {
|
||||
} else {
|
||||
// HACK: Apparently the onSelect event is triggered with href attributes
|
||||
// from DropdownItems
|
||||
if (!railTabs.some(tab => !tab.hide && tab.key === key)) {
|
||||
if (
|
||||
!railTabs.some(tab =>
|
||||
typeof tab.hide === 'function'
|
||||
? !tab.hide()
|
||||
: !tab.hide && tab.key === key
|
||||
)
|
||||
) {
|
||||
// Attempting to open a non-existent tab
|
||||
return
|
||||
}
|
||||
@@ -150,7 +165,9 @@ export const RailLayout = () => {
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
const validTabKeys = railTabs.filter(tab => !tab.hide).map(tab => tab.key)
|
||||
const validTabKeys = railTabs
|
||||
.filter(tab => (typeof tab.hide === 'function' ? !tab.hide() : !tab.hide))
|
||||
.map(tab => tab.key)
|
||||
if (!validTabKeys.includes(selectedTab) && isOpen) {
|
||||
// If the selected tab is no longer valid (e.g. due to permissions changes),
|
||||
// switch back to the file tree
|
||||
@@ -199,7 +216,9 @@ export const RailLayout = () => {
|
||||
<Nav activeKey={selectedTab} className="ide-rail-tabs-nav">
|
||||
<div className="ide-rail-tabs-wrapper" ref={tabWrapperRef}>
|
||||
{tabsInRail
|
||||
.filter(({ hide }) => !hide)
|
||||
.filter(({ hide }) =>
|
||||
typeof hide === 'function' ? !hide() : !hide
|
||||
)
|
||||
.map(({ icon, key, indicator, title, disabled }) => (
|
||||
<RailTab
|
||||
open={isOpen && selectedTab === key}
|
||||
|
||||
@@ -23,6 +23,7 @@ export type RailTabKey =
|
||||
| 'review-panel'
|
||||
| 'chat'
|
||||
| 'full-project-search'
|
||||
| 'workbench'
|
||||
|
||||
export type RailModalKey = 'keyboard-shortcuts' | 'contact-us' | 'dictionary'
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ export type RailElement = {
|
||||
component: ReactElement | null
|
||||
indicator?: ReactElement
|
||||
title: string
|
||||
hide?: boolean
|
||||
hide?: boolean | (() => boolean)
|
||||
disabled?: boolean
|
||||
mountOnFirstLoad?: boolean
|
||||
}
|
||||
|
||||
@@ -148,6 +148,7 @@
|
||||
"ai_feedback_the_suggestion_didnt_fix_the_error": "The suggestion didn’t fix the error",
|
||||
"ai_feedback_the_suggestion_wasnt_the_best_fix_available": "The suggestion wasn’t the best fix available",
|
||||
"ai_feedback_there_was_no_code_fix_suggested": "There was no code fix suggested",
|
||||
"ai_workbench": "AI workbench",
|
||||
"alignment": "Alignment",
|
||||
"all": "All",
|
||||
"all_borders": "All borders",
|
||||
|
||||
@@ -81,6 +81,8 @@
|
||||
"safari > 14"
|
||||
],
|
||||
"dependencies": {
|
||||
"@ai-sdk/mcp": "^1.0.0-beta.13",
|
||||
"@ai-sdk/openai": "^3.0.0-beta.44",
|
||||
"@aws-sdk/client-ses": "^3.864.0",
|
||||
"@contentful/rich-text-html-renderer": "^16.0.2",
|
||||
"@contentful/rich-text-types": "^16.0.2",
|
||||
@@ -107,6 +109,7 @@
|
||||
"@stripe/stripe-js": "^7.7.0",
|
||||
"@xmldom/xmldom": "^0.7.13",
|
||||
"accepts": "^1.3.7",
|
||||
"ai": "^6.0.0-beta.84",
|
||||
"ajv": "^8.12.0",
|
||||
"archiver": "^5.3.0",
|
||||
"async": "^3.2.5",
|
||||
@@ -217,6 +220,7 @@
|
||||
"@lezer/highlight": "^1.2.1",
|
||||
"@lezer/lr": "^1.4.2",
|
||||
"@lezer/markdown": "^1.4.3",
|
||||
"@overleaf/ai": "^1.0.0",
|
||||
"@overleaf/codemirror-tree-view": "^0.1.3",
|
||||
"@overleaf/dictionaries": "https://github.com/overleaf/dictionaries/archive/refs/tags/v0.0.3.tar.gz",
|
||||
"@overleaf/eslint-plugin": "*",
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
"emitDecoratorMetadata": true /* Allow decorators in writefull - inversify */,
|
||||
"paths": {
|
||||
"@/*": ["./frontend/js/*"],
|
||||
"@modules/*": ["./modules/*"],
|
||||
"@overleaf/o-error": ["../../libraries/o-error"],
|
||||
"@overleaf/ranges-tracker": ["../../libraries/ranges-tracker"],
|
||||
/* can't make this entry @types because that conflicts with the "types" entry below */
|
||||
|
||||
@@ -10,6 +10,7 @@ const {
|
||||
|
||||
const PackageVersions = require('./app/src/infrastructure/PackageVersions.js')
|
||||
const invalidateBabelCacheIfNeeded = require('./frontend/macros/invalidate-babel-cache-if-needed')
|
||||
const { dirname } = require('node:path')
|
||||
|
||||
// Make sure that babel-macros are re-evaluated after changing the modules config
|
||||
invalidateBabelCacheIfNeeded()
|
||||
@@ -260,6 +261,26 @@ module.exports = {
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
// CSS from AI module
|
||||
include: dirname(require.resolve('@overleaf/ai')),
|
||||
use: [
|
||||
{
|
||||
loader: 'css-loader',
|
||||
options: {
|
||||
exportType: 'css-style-sheet',
|
||||
},
|
||||
},
|
||||
{
|
||||
loader: 'postcss-loader',
|
||||
options: {
|
||||
postcssOptions: {
|
||||
config: require.resolve('@overleaf/ai/postcss.config.js'),
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
// Standard CSS processing (extracted into separate file)
|
||||
use: [MiniCssExtractPlugin.loader, 'css-loader'],
|
||||
@@ -309,6 +330,7 @@ module.exports = {
|
||||
alias: {
|
||||
// custom prefixes for import paths
|
||||
'@': path.resolve(__dirname, './frontend/js/'),
|
||||
'@modules': path.resolve(__dirname, './modules/'),
|
||||
'@ol-types': path.resolve(__dirname, './types/'),
|
||||
'@wf': path.resolve(
|
||||
__dirname,
|
||||
|
||||
Reference in New Issue
Block a user