Merge branch 'master' into delFS

pull/5600/head
Aniket 2 weeks ago committed by GitHub
commit de4fa14c15
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 2
      .env.local
  2. 1
      .gitignore
  3. 2
      apps/remix-dapp/src/locales/en/udapp.json
  4. 2
      apps/remix-dapp/src/locales/zh/udapp.json
  5. 17
      apps/remix-ide-e2e/src/commands/selectContract.ts
  6. 18
      apps/remix-ide-e2e/src/tests/terminal.test.ts
  7. 114
      apps/remix-ide/src/app.ts
  8. 2
      apps/remix-ide/src/app/components/main-panel.tsx
  9. 2
      apps/remix-ide/src/app/components/plugin-manager-component.js
  10. 2
      apps/remix-ide/src/app/components/popup-panel.tsx
  11. 4
      apps/remix-ide/src/app/editor/editor.js
  12. 2
      apps/remix-ide/src/app/files/dgitProvider.ts
  13. 4
      apps/remix-ide/src/app/files/fileManager.ts
  14. 2
      apps/remix-ide/src/app/files/remixDProvider.js
  15. 2
      apps/remix-ide/src/app/files/workspaceFileProvider.js
  16. 2
      apps/remix-ide/src/app/panels/file-panel.js
  17. 2
      apps/remix-ide/src/app/panels/layout.ts
  18. 2
      apps/remix-ide/src/app/panels/tab-proxy.js
  19. 3
      apps/remix-ide/src/app/panels/terminal.tsx
  20. 63
      apps/remix-ide/src/app/plugins/remixAIPlugin.tsx
  21. 2
      apps/remix-ide/src/app/tabs/analysis-tab.js
  22. 2
      apps/remix-ide/src/app/tabs/compile-tab.js
  23. 2
      apps/remix-ide/src/app/tabs/debugger-tab.js
  24. 1
      apps/remix-ide/src/app/tabs/locales/en/editor.json
  25. 2
      apps/remix-ide/src/app/tabs/settings-tab.tsx
  26. 2
      apps/remix-ide/src/app/tabs/test-tab.js
  27. 2
      apps/remixdesktop/src/lib/InferenceServerManager.ts
  28. 2
      apps/walletconnect/webpack.config.js
  29. 184
      libs/remix-ai-core/src/agents/securityAgent.ts
  30. 3
      libs/remix-ai-core/src/helpers/streamHandler.ts
  31. 5
      libs/remix-ai-core/src/index.ts
  32. 4
      libs/remix-ai-core/src/inferencers/remote/remoteInference.ts
  33. 2
      libs/remix-ai-core/src/prompts/promptBuilder.ts
  34. 10
      libs/remix-lib/src/execution/txRunner.ts
  35. 4
      libs/remix-lib/src/execution/txRunnerVM.ts
  36. 9
      libs/remix-ui/editor/src/lib/providers/inlineCompletionProvider.ts
  37. 28
      libs/remix-ui/editor/src/lib/remix-ui-editor.tsx
  38. 2
      libs/remix-ui/editor/src/lib/syntaxes/solidity.ts
  39. 2
      libs/remix-ui/home-tab/src/lib/components/types/carouselTypes.ts
  40. 22
      libs/remix-ui/plugin-manager/src/types.d.ts
  41. 4
      libs/remix-ui/run-tab/src/lib/actions/deploy.ts
  42. 10
      libs/remix-ui/run-tab/src/lib/run-tab.tsx
  43. 1
      libs/remix-ui/run-tab/src/lib/types/blockchain.d.ts
  44. 4
      libs/remix-ui/search/src/lib/components/results/ResultSummary.tsx
  45. 4
      libs/remix-ui/search/src/lib/context/context.tsx
  46. 7
      libs/remix-ui/tabs/src/lib/remix-ui-tabs.tsx
  47. 7
      libs/remix-ui/terminal/src/lib/remix-ui-terminal.tsx
  48. 12
      libs/remix-ui/workspace/src/lib/types/index.ts

@ -2,4 +2,4 @@ gist_token=<token>
account_passphrase=<passphrase>
account_password=<password>
NODE_OPTIONS=--max-old-space-size=2048
# WALLET_CONNECT_PROJECT_ID=<walletconnect cloud PROJECT_ID>
WALLET_CONNECT_PROJECT_ID=<project_id>

1
.gitignore vendored

@ -16,6 +16,7 @@ soljson.js
*_group*.ts
stats.json
release
.env
# compiled output

@ -26,7 +26,7 @@
"udapp.contractOptionsTitle2": "Select a compiled contract to deploy or to use with At Address.",
"udapp.contractOptionsTitle3": "Select and compile *.sol file to deploy or access a contract.",
"udapp.contractOptionsTitle4": "When there is a compiled .sol file, choose the contract to deploy or to use with At Address.",
"udapp.checkSumWarning": "It seems you are not using a checksumed address.A checksummed address is an address that contains uppercase letters, as specified in {a}.Checksummed addresses are meant to help prevent users from sending transactions to the wrong address.",
"udapp.checkSumWarning": "It seems you are not using a checksummed address.A checksummed address is an address that contains uppercase letters, as specified in {a}.Checksummed addresses are meant to help prevent users from sending transactions to the wrong address.",
"udapp.isOverSizePromptEip170": "Contract creation initialization returns data with length of more than 24576 bytes. The deployment will likely fail if the current network has activated the eip 170. More info: {a}",
"udapp.isOverSizePromptEip3860": "Contract creation init code exceeds the allowed max code size of 49152 bytes. The deployment will likely fail if the current network has activated the eip 3860. More info: {a}",
"udapp.thisContractMayBeAbstract": "This contract may be abstract, it may not implement an abstract parent's methods completely or it may not invoke an inherited contract's constructor correctly.",

@ -23,7 +23,7 @@
"udapp.contractOptionsTitle2": "选择要部署或与 At Address 一起使用的已编译合约。",
"udapp.contractOptionsTitle3": "选择并编译 *.sol 文件以部署或访问合约。",
"udapp.contractOptionsTitle4": "当有编译的 .sol 文件时,选择 {br} 合约进行部署或与 AtAddress 一起使用。",
"udapp.checkSumWarning": "您似乎没有使用 checksumed address 。{br} checksumed address 是包含大写字母的地址,如 {a} 中所指定。{br} checksumed address 旨在帮助防止用户将交易发送到错误地址。",
"udapp.checkSumWarning": "您似乎没有使用 checksummed address 。{br} checksummed address 是包含大写字母的地址,如 {a} 中所指定。{br} checksummed address 旨在帮助防止用户将交易发送到错误地址。",
"udapp.isOverSizePromptEip170": "合约创建初始化返回长度超过24576字节的数据。部署可能会失败。 {br}更多信息:{a}",
"udapp.isOverSizePromptEip3860": "合约创建初始化代码超出了允许的最大代码大小 49152 字节。如果当前网络已激活 eip 3860,则部署可能会失败。更多信息:{a}",
"udapp.thisContractMayBeAbstract": "这个合约可能是抽象的,它可能没有完全实现抽象父类的方法,或者它可能没有正确调用继承合约的构造函数。",

@ -4,19 +4,14 @@ import EventEmitter from 'events'
const selector = '.udapp_contractNames'
class SelectContract extends EventEmitter {
command (this: NightwatchBrowser, contractName: string): NightwatchBrowser {
this.api.waitForElementVisible(selector).perform((done) => {
selectContract(this.api, contractName, () => {
done()
this.emit('complete')
})
})
command(this: NightwatchBrowser, contractName: string): NightwatchBrowser {
this.api
.waitForElementVisible(selector)
.waitForElementPresent(`${selector} option[value="${contractName}"]`)
.click(`${selector} option[value="${contractName}"]`)
.perform(() => this.emit('complete'))
return this
}
}
function selectContract (browser: NightwatchBrowser, contractName: string, callback: VoidFunction) {
browser.click(`${selector} option[value="${contractName}"]`).perform(() => callback())
}
module.exports = SelectContract

@ -209,18 +209,16 @@ module.exports = {
.createContract('')
.getAddressAtPosition(0, (address) => {
addressRef = address
})
.perform((done) => {
browser.addFile('scripts/test_filtering_event.ts', { content: test_filtering_event.replace('<ADDRESS>', addressRef) })
.perform(() => done())
.executeScriptInTerminal('remix.execute(\'scripts/test_filtering_event.ts\')')
.pause(1000)
.waitForElementContainsText('*[data-id="terminalJournal"]', '1')
.waitForElementContainsText('*[data-id="terminalJournal"]', 'true')
.executeScriptInTerminal('remix.execute(\'scripts/test_filtering_event.ts\')') // re-emit the event
.waitForElementContainsText('*[data-id="terminalJournal"]', '2')
.waitForElementContainsText('*[data-id="terminalJournal"]', 'false')
})
.executeScriptInTerminal('remix.execute(\'scripts/test_filtering_event.ts\')')
.pause(1000)
.waitForElementContainsText('*[data-id="terminalJournal"]', '1')
.waitForElementContainsText('*[data-id="terminalJournal"]', 'true')
.executeScriptInTerminal('remix.execute(\'scripts/test_filtering_event.ts\')') // re-emit the event
.waitForElementContainsText('*[data-id="terminalJournal"]', '2')
.waitForElementContainsText('*[data-id="terminalJournal"]', 'false')
},
'Should display auto-complete menu #group4': function (browser: NightwatchBrowser) {

@ -26,21 +26,21 @@ import { WalkthroughService } from './walkthroughService'
import { OffsetToLineColumnConverter, CompilerMetadata, CompilerArtefacts, FetchAndCompile, CompilerImports, GistHandler } from '@remix-project/core-plugin'
import {Registry} from '@remix-project/remix-lib'
import {ConfigPlugin} from './app/plugins/config'
import {StoragePlugin} from './app/plugins/storage'
import {Layout} from './app/panels/layout'
import {NotificationPlugin} from './app/plugins/notification'
import {Blockchain} from './blockchain/blockchain'
import {MergeVMProvider, LondonVMProvider, BerlinVMProvider, ShanghaiVMProvider, CancunVMProvider} from './app/providers/vm-provider'
import {MainnetForkVMProvider} from './app/providers/mainnet-vm-fork-provider'
import {SepoliaForkVMProvider} from './app/providers/sepolia-vm-fork-provider'
import {GoerliForkVMProvider} from './app/providers/goerli-vm-fork-provider'
import {CustomForkVMProvider} from './app/providers/custom-vm-fork-provider'
import {HardhatProvider} from './app/providers/hardhat-provider'
import {GanacheProvider} from './app/providers/ganache-provider'
import {FoundryProvider} from './app/providers/foundry-provider'
import {ExternalHttpProvider} from './app/providers/external-http-provider'
import { Registry } from '@remix-project/remix-lib'
import { ConfigPlugin } from './app/plugins/config'
import { StoragePlugin } from './app/plugins/storage'
import { Layout } from './app/panels/layout'
import { NotificationPlugin } from './app/plugins/notification'
import { Blockchain } from './blockchain/blockchain'
import { MergeVMProvider, LondonVMProvider, BerlinVMProvider, ShanghaiVMProvider, CancunVMProvider } from './app/providers/vm-provider'
import { MainnetForkVMProvider } from './app/providers/mainnet-vm-fork-provider'
import { SepoliaForkVMProvider } from './app/providers/sepolia-vm-fork-provider'
import { GoerliForkVMProvider } from './app/providers/goerli-vm-fork-provider'
import { CustomForkVMProvider } from './app/providers/custom-vm-fork-provider'
import { HardhatProvider } from './app/providers/hardhat-provider'
import { GanacheProvider } from './app/providers/ganache-provider'
import { FoundryProvider } from './app/providers/foundry-provider'
import { ExternalHttpProvider } from './app/providers/external-http-provider'
import { EnvironmentExplorer } from './app/providers/environment-explorer'
import { FileDecorator } from './app/plugins/file-decorator'
import { CodeFormat } from './app/plugins/code-format'
@ -72,9 +72,9 @@ import { Matomo } from './app/plugins/matomo'
import { TemplatesSelectionPlugin } from './app/plugins/templates-selection/templates-selection-plugin'
const isElectron = require('is-electron')
import isElectron from 'is-electron'
const remixLib = require('@remix-project/remix-lib')
import * as remixLib from '@remix-project/remix-lib'
import { QueryParams } from '@remix-project/remix-lib'
import { SearchPlugin } from './app/tabs/search'
@ -82,27 +82,27 @@ import { ScriptRunnerUIPlugin } from './app/tabs/script-runner-ui'
import { ElectronProvider } from './app/files/electronProvider'
const Storage = remixLib.Storage
const RemixDProvider = require('./app/files/remixDProvider')
const Config = require('./config')
import RemixDProvider from './app/files/remixDProvider'
import Config from './config'
const FileManager = require('./app/files/fileManager')
import FileManager from './app/files/fileManager'
import FileProvider from "./app/files/fileProvider"
import { appPlatformTypes } from '@remix-ui/app'
const DGitProvider = require('./app/files/dgitProvider')
const WorkspaceFileProvider = require('./app/files/workspaceFileProvider')
import DGitProvider from './app/files/dgitProvider'
import WorkspaceFileProvider from './app/files/workspaceFileProvider'
const PluginManagerComponent = require('./app/components/plugin-manager-component')
import PluginManagerComponent from './app/components/plugin-manager-component'
const CompileTab = require('./app/tabs/compile-tab')
const SettingsTab = require('./app/tabs/settings-tab')
const AnalysisTab = require('./app/tabs/analysis-tab')
const { DebuggerTab } = require('./app/tabs/debugger-tab')
const TestTab = require('./app/tabs/test-tab')
const FilePanel = require('./app/panels/file-panel')
const Editor = require('./app/editor/editor')
const Terminal = require('./app/panels/terminal')
const { TabProxy } = require('./app/panels/tab-proxy.js')
import CompileTab from './app/tabs/compile-tab'
import SettingsTab from './app/tabs/settings-tab'
import AnalysisTab from './app/tabs/analysis-tab'
import DebuggerTab from './app/tabs/debugger-tab'
import TestTab from './app/tabs/test-tab'
import Filepanel from './app/panels/file-panel'
import Editor from './app/editor/editor'
import Terminal from './app/panels/terminal'
import TabProxy from './app/panels/tab-proxy.js'
const _paq = (window._paq = window._paq || [])
@ -115,16 +115,49 @@ export class platformApi {
}
}
type Components = {
filesProviders: {
browser?: any
localhost?: any
workspace?: any
electron?: any
}
}
class AppComponent {
appManager: RemixAppManager
queryParams: QueryParams
private _components: Components
panels: any
workspace: any
engine: RemixEngine
matomoConfAlreadySet: any
matomoCurrentSetting: any
showMatomo: boolean
walkthroughService: WalkthroughService
platform: 'desktop' | 'web'
gistHandler: GistHandler
themeModule: ThemeModule
localeModule: LocaleModule
notification: NotificationPlugin
layout: Layout
mainview: any
menuicons: VerticalIcons
sidePanel: SidePanel
hiddenPanel: HiddenPanel
pinnedPanel: PinnedPanel
popupPanel: PopupPanel
statusBar: StatusBar
settings: SettingsTab
constructor() {
const PlatFormAPi = new platformApi()
Registry.getInstance().put({
api: PlatFormAPi,
name: 'platform'
})
this.appManager = new RemixAppManager({})
this.appManager = new RemixAppManager()
this.queryParams = new QueryParams()
this._components = {}
this._components = {} as Components
// setup storage
const configStorage = new Storage('config-v0.8:')
@ -161,7 +194,6 @@ class AppComponent {
name: 'fileproviders'
})
}
async run() {
@ -184,7 +216,7 @@ class AppComponent {
this.matomoConfAlreadySet = Registry.getInstance().get('config').api.exists('settings/matomo-analytics')
this.matomoCurrentSetting = Registry.getInstance().get('config').api.get('settings/matomo-analytics')
let electronTracking = window.electronAPI ? await window.electronAPI.canTrackMatomo() : false
const electronTracking = (window as any).electronAPI ? await (window as any).electronAPI.canTrackMatomo() : false
const lastMatomoCheck = window.localStorage.getItem('matomo-analytics-consent')
const sixMonthsAgo = new Date();
@ -456,10 +488,10 @@ class AppComponent {
this.popupPanel = new PopupPanel()
const pluginManagerComponent = new PluginManagerComponent(appManager, this.engine)
const filePanel = new FilePanel(appManager, contentImport)
const filePanel = new Filepanel(appManager, contentImport)
this.statusBar = new StatusBar(filePanel, this.menuicons)
const landingPage = new LandingPage(appManager, this.menuicons, fileManager, filePanel, contentImport)
this.settings = new SettingsTab(Registry.getInstance().get('config').api, editor, appManager)
this.settings = new SettingsTab(Registry.getInstance().get('config').api, editor)//, appManager)
this.engine.register([this.menuicons, landingPage, this.hiddenPanel, this.sidePanel, this.statusBar, filePanel, pluginManagerComponent, this.settings, this.pinnedPanel, this.popupPanel])
@ -514,7 +546,7 @@ class AppComponent {
async activate() {
const queryParams = new QueryParams()
const params = queryParams.get()
const params: any = queryParams.get()
try {
this.engine.register(await this.appManager.registeredPlugins())
@ -610,10 +642,11 @@ class AppComponent {
}
if (params.call) {
const callDetails = params.call.split('//')
const callDetails: any = params.call.split('//')
if (callDetails.length > 1) {
this.appManager.call('notification', 'toast', `initiating ${callDetails[0]} and calling "${callDetails[1]}" ...`)
// @todo(remove the timeout when activatePlugin is on 0.3.0)
//@ts-ignore
await this.appManager.call(...callDetails).catch(console.error)
}
}
@ -629,6 +662,7 @@ class AppComponent {
// @todo(remove the timeout when activatePlugin is on 0.3.0)
try {
//@ts-ignore
await this.appManager.call(...callDetails)
} catch (e) {
console.error(e)

@ -15,7 +15,7 @@ const profile = {
export class MainPanel extends AbstractPanel {
element: HTMLDivElement
dispatch: React.Dispatch<any> = () => {}
constructor(config) {
constructor(config = null) {
super(profile)
this.element = document.createElement('div')
this.element.setAttribute('data-id', 'mainPanelPluginsContainer')

@ -19,7 +19,7 @@ const profile = {
maintainedBy: "Remix"
}
class PluginManagerComponent extends ViewPlugin {
export default class PluginManagerComponent extends ViewPlugin {
constructor (appManager, engine) {
super(profile)
this.appManager = appManager

@ -24,7 +24,7 @@ export class PopupPanel extends AbstractPanel {
dispatch: React.Dispatch<any> = () => { }
appStateDispatch: React.Dispatch<AppAction> = () => { }
constructor(config) {
constructor(config = null) {
super(profile)
this.event = new EventEmitter()
}

@ -16,7 +16,7 @@ const profile = {
methods: ['highlight', 'discardHighlight', 'clearAnnotations', 'addLineText', 'discardLineTexts', 'addAnnotation', 'gotoLine', 'revealRange', 'getCursorPosition', 'open', 'addModel','addErrorMarker', 'clearErrorMarkers', 'getText', 'getPositionAt', 'openReadOnly'],
}
class Editor extends Plugin {
export default class Editor extends Plugin {
constructor () {
super(profile)
@ -601,5 +601,3 @@ class Editor extends Plugin {
return this.api.getPositionAt(offset)
}
}
module.exports = Editor

@ -28,7 +28,7 @@ const profile: LibraryProfile = {
, 'getGitHubUser', 'remotebranches', 'remotecommits', 'repositories', 'getCommitChanges', 'compareBranches'],
kind: 'file-system'
}
class DGitProvider extends Plugin<any, CustomRemixApi> {
export default class DGitProvider extends Plugin<any, CustomRemixApi> {
constructor() {
super(profile)
}

@ -26,7 +26,7 @@ const profile = {
'readFile', 'copyFile', 'copyDir', 'rename', 'mkdir', 'readdir', 'dirList', 'fileList', 'remove', 'getCurrentFile', 'getFile',
'getFolder', 'setFile', 'switchFile', 'refresh', 'getProviderOf', 'getProviderByName', 'getPathFromUrl', 'getUrlFromPath',
'saveCurrentFile', 'setBatchFiles', 'isGitRepo', 'isFile', 'isDirectory', 'hasGitSubmodule', 'copyFolderToJson', 'diff',
'hasGitSubmodules'
'hasGitSubmodules', 'getOpenedFiles'
],
kind: 'file-system'
}
@ -40,7 +40,7 @@ const errorMsg = {
const createError = (err) => {
return new Error(`${errorMsg[err.code]} ${err.message || ''}`)
}
class FileManager extends Plugin {
export default class FileManager extends Plugin {
mode: string
openedFiles: any
editor: any

@ -1,7 +1,7 @@
'use strict'
import FileProvider from "./fileProvider"
module.exports = class RemixDProvider extends FileProvider {
export default class RemixDProvider extends FileProvider {
constructor (appManager) {
super('localhost')
this._appManager = appManager

@ -3,7 +3,7 @@
const EventManager = require('events')
import FileProvider from "./fileProvider"
class WorkspaceFileProvider extends FileProvider {
export default class WorkspaceFileProvider extends FileProvider {
constructor () {
super('')
this.workspacesPath = '.workspaces'

@ -55,7 +55,7 @@ const profile = {
version: packageJson.version,
maintainedBy: 'Remix'
}
module.exports = class Filepanel extends ViewPlugin {
export default class Filepanel extends ViewPlugin {
constructor(appManager, contentImport) {
super(profile)
this.registry = Registry.getInstance()

@ -12,7 +12,7 @@ const profile: Profile = {
interface panelState {
active: boolean
plugin: Plugin
minimized: boolean
minimized?: boolean
}
interface panels {
tabs: panelState

@ -10,7 +10,7 @@ const profile = {
kind: 'other'
}
export class TabProxy extends Plugin {
export default class TabProxy extends Plugin {
constructor (fileManager, editor) {
super(profile)
this.event = new EventEmitter()

@ -24,7 +24,7 @@ const profile = {
version: packageJson.version
}
class Terminal extends Plugin {
export default class Terminal extends Plugin {
fileImport: CompilerImports
event: any
globalRegistry: Registry
@ -163,4 +163,3 @@ class Terminal extends Plugin {
}
}
module.exports = Terminal

@ -3,7 +3,7 @@ import { ViewPlugin } from '@remixproject/engine-web'
import { Plugin } from '@remixproject/engine';
import { RemixAITab, ChatApi } from '@remix-ui/remix-ai'
import React, { useCallback } from 'react';
import { ICompletions, IModel, RemoteInferencer, IRemoteModel, IParams, GenerationParams, CodeExplainAgent } from '@remix/remix-ai-core';
import { ICompletions, IModel, RemoteInferencer, IRemoteModel, IParams, GenerationParams, CodeExplainAgent, SecurityAgent } from '@remix/remix-ai-core';
import { CustomRemixApi } from '@remix-api'
import { PluginViewWrapper } from '@remix-ui/helper'
const _paq = (window._paq = window._paq || [])
@ -17,9 +17,8 @@ const profile = {
displayName: 'RemixAI',
methods: ['code_generation', 'code_completion',
"solidity_answer", "code_explaining",
"code_insertion", "error_explaining",
"initialize", 'chatPipe', 'ProcessChatRequestBuffer',
'isChatRequestPending'],
"code_insertion", "error_explaining", "vulnerability_check",
"initialize", 'chatPipe', 'ProcessChatRequestBuffer', 'isChatRequestPending'],
events: [],
icon: 'assets/img/remix-logo-blue.png',
description: 'RemixAI provides AI services to Remix IDE.',
@ -38,15 +37,16 @@ export class RemixAIPlugin extends ViewPlugin {
remoteInferencer:RemoteInferencer = null
isInferencing: boolean = false
chatRequestBuffer: chatRequestBufferT<any> = null
agent: CodeExplainAgent
codeExpAgent: CodeExplainAgent
securityAgent: SecurityAgent
useRemoteInferencer:boolean = false
dispatch: any
constructor(inDesktop:boolean) {
super(profile)
this.isOnDesktop = inDesktop
this.agent = new CodeExplainAgent(this)
// user machine dont use resource for remote inferencing
this.codeExpAgent = new CodeExplainAgent(this)
// user machine dont use ressource for remote inferencing
}
onActivation(): void {
@ -62,6 +62,8 @@ export class RemixAIPlugin extends ViewPlugin {
this.useRemoteInferencer = true
this.initialize()
}
this.securityAgent = new SecurityAgent(this)
}
async initialize(model1?:IModel, model2?:IModel, remoteModel?:IRemoteModel, useRemote?:boolean){
@ -97,11 +99,6 @@ export class RemixAIPlugin extends ViewPlugin {
}
async code_generation(prompt: string): Promise<any> {
if (this.isInferencing) {
this.call('terminal', 'log', { type: 'aitypewriterwarning', value: "RemixAI is already busy!" })
return
}
if (this.isOnDesktop && !this.useRemoteInferencer) {
return await this.call(this.remixDesktopPluginName, 'code_generation', prompt)
} else {
@ -118,17 +115,8 @@ export class RemixAIPlugin extends ViewPlugin {
}
async solidity_answer(prompt: string, params: IParams=GenerationParams): Promise<any> {
if (this.isInferencing) {
this.call('terminal', 'log', { type: 'aitypewriterwarning', value: "RemixAI is already busy!" })
return
}
if (prompt.trimStart().startsWith('gpt') || prompt.trimStart().startsWith('sol-gpt')) {
params.terminal_output = true
params.stream_result = false
params.return_stream_response = false
}
const newPrompt = await this.codeExpAgent.chatCommand(prompt)
const newPrompt = await this.agent.chatCommand(prompt)
let result
if (this.isOnDesktop && !this.useRemoteInferencer) {
result = await this.call(this.remixDesktopPluginName, 'solidity_answer', newPrompt)
@ -142,11 +130,6 @@ export class RemixAIPlugin extends ViewPlugin {
}
async code_explaining(prompt: string, context: string, params: IParams=GenerationParams): Promise<any> {
if (this.isInferencing) {
this.call('terminal', 'log', { type: 'aitypewriterwarning', value: "RemixAI is already busy!" })
return
}
let result
if (this.isOnDesktop && !this.useRemoteInferencer) {
result = await this.call(this.remixDesktopPluginName, 'code_explaining', prompt, context, params)
@ -159,11 +142,6 @@ export class RemixAIPlugin extends ViewPlugin {
}
async error_explaining(prompt: string, context: string="", params: IParams=GenerationParams): Promise<any> {
if (this.isInferencing) {
this.call('terminal', 'log', { type: 'aitypewriterwarning', value: "RemixAI is already busy!" })
return
}
let result
if (this.isOnDesktop && !this.useRemoteInferencer) {
result = await this.call(this.remixDesktopPluginName, 'error_explaining', prompt)
@ -174,6 +152,22 @@ export class RemixAIPlugin extends ViewPlugin {
return result
}
async vulnerability_check(prompt: string, params: IParams=GenerationParams): Promise<any> {
let result
if (this.isOnDesktop && !this.useRemoteInferencer) {
result = await this.call(this.remixDesktopPluginName, 'vulnerability_check', prompt)
} else {
result = await this.remoteInferencer.vulnerability_check(prompt, params)
}
if (result && params.terminal_output) this.call('terminal', 'log', { type: 'aitypewriterwarning', value: result })
return result
}
getVulnerabilityReport(file: string): any {
return this.securityAgent.getReport(file)
}
async code_insertion(msg_pfx: string, msg_sfx: string): Promise<any> {
if (this.isOnDesktop && !this.useRemoteInferencer) {
return await this.call(this.remixDesktopPluginName, 'code_insertion', msg_pfx, msg_sfx)
@ -194,11 +188,12 @@ export class RemixAIPlugin extends ViewPlugin {
if (fn === "code_explaining") ChatApi.composer.send("Explain the current code")
else if (fn === "error_explaining") ChatApi.composer.send("Explain the error")
else if (fn === "solidity_answer") ChatApi.composer.send("Answer the following question")
else console.log("chatRequestBuffer is not empty. First process the last request.")
else if (fn === "vulnerability_check") ChatApi.composer.send("Is there any vulnerability in the pasted code?")
else console.log("chatRequestBuffer function name not recognized.")
}
}
else {
console.log("chatRequestBuffer is not empty. First process the last request.")
console.log("chatRequestBuffer is not empty. First process the last request.", this.chatRequestBuffer)
}
_paq.push(['trackEvent', 'ai', 'remixAI_chat', 'askFromTerminal'])
}

@ -22,7 +22,7 @@ const profile = {
maintainedBy: 'Remix'
}
class AnalysisTab extends ViewPlugin {
export default class AnalysisTab extends ViewPlugin {
constructor () {
super(profile)
this.event = new EventManager()

@ -28,7 +28,7 @@ const profile = {
// - events: ['compilationFinished'],
// - methods: ['getCompilationResult']
class CompileTab extends CompilerApiMixin(ViewPlugin) { // implements ICompilerApi
export default class CompileTab extends CompilerApiMixin(ViewPlugin) { // implements ICompilerApi
constructor (config, fileManager) {
super(profile)
this.fileManager = fileManager

@ -22,7 +22,7 @@ const profile = {
maintainedBy: 'Remix'
}
export class DebuggerTab extends DebuggerApiMixin(ViewPlugin) {
export default class DebuggerTab extends DebuggerApiMixin(ViewPlugin) {
constructor () {
super(profile)
this.el = document.createElement('div')

@ -28,6 +28,7 @@
"editor.explainFunctionByAI": "```\n{content}\n```\nExplain the function {currentFunction}",
"editor.explainFunctionByAISol": "```\n{content}\n```\nExplain the function {currentFunction}",
"editor.ExplainPipeMessage": "```\n {content}\n```\nExplain the snipped above",
"editor.PastedCodeSafety": "```\n {content}\n```\n\nReply in a short manner: Does this code contain major security vulnerabilities leading to a scam or loss of funds?",
"editor.executeFreeFunction": "Run a free function",
"editor.executeFreeFunction2": "Run the free function \"{name}\"",
"editor.toastText1": "This can only execute free function",

@ -27,7 +27,7 @@ const profile = {
maintainedBy: 'Remix'
}
module.exports = class SettingsTab extends ViewPlugin {
export default class SettingsTab extends ViewPlugin {
config: any = {}
editor: any
private _deps: {

@ -22,7 +22,7 @@ const profile = {
maintainedBy: 'Remix'
}
module.exports = class TestTab extends ViewPlugin {
export default class TestTab extends ViewPlugin {
constructor (fileManager, offsetToLineColumnConverter, filePanel, compileTab, appManager, contentImport) {
super(profile)
this.compileTab = compileTab

@ -6,7 +6,7 @@ import { EventEmitter } from 'events';
import { ICompletions, IModel, IParams, InsertionParams,
CompletionParams, GenerationParams, ModelType, AIRequestType,
IStreamResponse, ChatHistory, downloadLatestReleaseExecutable,
buildSolgptPromt } from "@remix/remix-ai-core"
buildSolgptPrompt } from "@remix/remix-ai-core"
import { platform } from 'os';
class ServerStatusTimer {

@ -46,7 +46,7 @@ module.exports = composePlugins(withNx(), (config) => {
process: 'process/browser'
})
)
console.log(process.env.WALLET_CONNECT_PROJECT_ID)
// set the define plugin to load the WALLET_CONNECT_PROJECT_ID
config.plugins.push(
new webpack.DefinePlugin({

@ -1,28 +1,188 @@
// security checks
import * as fs from 'fs';
class SecurityAgent {
private codebase: string[]; // list of codebase files
interface SecurityReport {
compiled: boolean;
vulnerabilities: string[];
isNotSafe: string;
fileName: string;
reportTimestamp: string;
recommendations: string[];
fileModifiedSinceLastReport: boolean;
hasPastedCode: boolean;
}
class WorkspaceWatcher {
private intervalId: NodeJS.Timeout | null = null;
public interval: number;
private task: () => void;
constructor(task: () => void, interval: number) {
this.task = task;
this.interval = interval;
}
start(): void {
if (this.intervalId === null) {
this.intervalId = setInterval(() => {
this.task();
}, this.interval);
}
}
stop(): void {
if (this.intervalId !== null) {
clearInterval(this.intervalId);
this.intervalId = null;
}
}
isRunning(): boolean {
return this.intervalId !== null;
}
}
export class SecurityAgent {
public currentFile: string;
public openedFiles: any;
private basePlugin: any;
private watcher: WorkspaceWatcher;
public reports: SecurityReport[] = [];
constructor(plugin) {
this.basePlugin = plugin;
this.basePlugin.on('fileManager', 'fileAdded', (path) => { });
this.basePlugin.on('fileManager', 'fileChanged', (path) => { //this.modifiedFile(path)
});
this.basePlugin.on('fileManager', 'fileRemoved', (path) => { this.removeFileFromReport(path) });
this.basePlugin.on('fileManager', 'fileRenamed', (oldName, newName) => {
this.removeFileFromReport(oldName);
this.addFileToReport(newName);
});
this.basePlugin.on('solidity', 'compilationFinished', async (fileName, source, languageVersion, data) => { this.onCompilationFinished(fileName) });
this.basePlugin.on('vyper', 'compilationFinished', async (fileName, source, languageVersion, data) => { this.onCompilationFinished(fileName) });
this.basePlugin.on('hardhat', 'compilationFinished', async (fileName, source, languageVersion, data) => { this.onCompilationFinished(fileName) });
this.basePlugin.on('foundry', 'compilationFinished', async (fileName, source, languageVersion, data) => { this.onCompilationFinished(fileName) });
this.watcher = new WorkspaceWatcher(async () => {
try {
this.currentFile = await this.basePlugin.call('fileManager', 'getCurrentFile');
this.openedFiles = await this.basePlugin.call('fileManager', 'getOpenedFiles');
Object.keys(this.openedFiles).forEach(key => {
this.addFileToReport(this.openedFiles[key]);
});
} catch (error) {
// no file selected or opened currently
}
}, 10000);
this.watcher.start();
}
addFileToReport(file: string): void {
const report = this.reports.find((r) => r.fileName === file);
if (report) {
// nothing to do
} else {
this.reports.push({
compiled: false,
isNotSafe: 'No',
vulnerabilities: [],
fileName: file,
reportTimestamp: null,
recommendations: [],
fileModifiedSinceLastReport: false,
hasPastedCode: false
});
}
constructor(codebasePath: string) {
// git or fs
this.codebase = this.loadCodebase(codebasePath);
}
private loadCodebase(path: string): string[] {
const files = fs.readdirSync(path);
return files
.filter(file => file.endsWith('.ts'))
.flatMap(file => fs.readFileSync(`${path}/${file}`, 'utf-8').split('\n'));
async onCompilationFinished(file: string) {
let report = this.reports.find((r) => r.fileName === file);
if (report) {
report.compiled = true;
report.fileModifiedSinceLastReport = false;
} else {
report = {
compiled: true,
isNotSafe: 'No',
vulnerabilities: [],
fileName: file,
reportTimestamp: null,
recommendations: [],
fileModifiedSinceLastReport: false,
hasPastedCode: false
}
this.reports.push(report);
}
try {
this.processFile(file);
console.log('Checking for vulnerabilities after compilation', this.reports);
} catch (error) {
console.error('Error checking for vulnerabilities after compilation: ', error);
}
// check for security vulnerabilities
}
public update(currentFile, lineNumber){
removeFileFromReport(file: string): void {
const index = this.reports.findIndex((r) => r.fileName === file);
if (index !== -1) {
this.reports.splice(index, 1);
}
}
modifiedFile(file: string): void {
const report = this.reports.find((r) => r.fileName === file);
if (report) {
report.fileModifiedSinceLastReport = true;
}
}
async processFile(file: string) {
try {
const report = this.reports.find((r) => r.fileName === file);
if (report) { }
else {
this.reports.push({
compiled: false,
isNotSafe: 'No',
vulnerabilities: [],
fileName: file,
reportTimestamp: null,
recommendations: [],
fileModifiedSinceLastReport: false,
hasPastedCode: false
});
}
if (!report.reportTimestamp || report.fileModifiedSinceLastReport) {
const content = await this.basePlugin.call('fileManager', 'getFile', file);
const prompt = "```\n" + content + "\n```\n\nReply in a short manner: Does this code contain major security vulnerabilities leading to a scam or loss of funds?"
let result = await this.basePlugin.call('remixAI', 'vulnerability_check', prompt)
result = JSON.parse(result);
report.vulnerabilities = result.Reason;
report.recommendations = result.Suggestion;
report.isNotSafe = result.Answer;
report.reportTimestamp = new Date().toISOString();
}
} catch (error) {
console.error('Error processing file: ', error);
}
}
getReport(file: string): SecurityReport {
return this.reports.find((r) => r.fileName === file);
}
public getRecommendations(currentLine: string, numSuggestions: number = 3): string[] {
// process the codebase highlighting security vulnerabilities and deliver recommendations
const suggestions: string[] = [];
return suggestions;
}

@ -46,6 +46,7 @@ export const HandleStreamResponse = async (streamResponse,
}
catch (error) {
console.error('Error parsing JSON:', error);
return { 'generateText': 'Try again!', 'isGenerating': false }
}
}
if (done_cb) {
@ -54,7 +55,7 @@ export const HandleStreamResponse = async (streamResponse,
}
catch (error) {
console.error('Error parsing JSON:', error);
return { 'generateText': '', 'isGenerating': false }
return { 'generateText': 'Try again!', 'isGenerating': false }
}
}

@ -6,7 +6,7 @@ import { IModel, IModelResponse, IModelRequest, InferenceModel, ICompletions,
import { ModelType } from './types/constants'
import { DefaultModels, InsertionParams, CompletionParams, GenerationParams } from './types/models'
import { getCompletionPrompt, getInsertionPrompt } from './prompts/completionPrompts'
import { buildSolgptPromt, PromptBuilder } from './prompts/promptBuilder'
import { buildSolgptPrompt, PromptBuilder } from './prompts/promptBuilder'
import { RemoteInferencer } from './inferencers/remote/remoteInference'
import { ChatHistory } from './prompts/chat'
import { downloadLatestReleaseExecutable } from './helpers/inferenceServerReleases'
@ -14,7 +14,7 @@ import { downloadLatestReleaseExecutable } from './helpers/inferenceServerReleas
export {
IModel, IModelResponse, IModelRequest, InferenceModel,
ModelType, DefaultModels, ICompletions, IParams, IRemoteModel,
getCompletionPrompt, getInsertionPrompt, IStreamResponse, buildSolgptPromt,
getCompletionPrompt, getInsertionPrompt, IStreamResponse, buildSolgptPrompt,
RemoteInferencer, InsertionParams, CompletionParams, GenerationParams,
ChatEntry, AIRequestType, RemoteBackendOPModel, ChatHistory, downloadLatestReleaseExecutable
}
@ -22,3 +22,4 @@ export {
export * from './types/types'
export * from './helpers/streamHandler'
export * from './agents/codeExplainAgent'
export * from './agents/securityAgent'

@ -1,6 +1,6 @@
import { ICompletions, IParams, AIRequestType, RemoteBackendOPModel, JsonStreamParser } from "../../types/types";
import { GenerationParams, CompletionParams, InsertionParams } from "../../types/models";
import { buildSolgptPromt } from "../../prompts/promptBuilder";
import { buildSolgptPrompt } from "../../prompts/promptBuilder";
import EventEmitter from "events";
import { ChatHistory } from "../../prompts/chat";
import axios from 'axios';
@ -127,7 +127,7 @@ export class RemoteInferencer implements ICompletions {
}
async solidity_answer(prompt, options:IParams=GenerationParams): Promise<any> {
const main_prompt = buildSolgptPromt(prompt, this.model_op)
const main_prompt = buildSolgptPrompt(prompt, this.model_op)
const payload = { 'prompt': main_prompt, "endpoint":"solidity_answer", ...options }
if (options.stream_result) return this._streamInferenceRequest(payload, AIRequestType.GENERAL)
else return this._makeRequest(payload, AIRequestType.GENERAL)

@ -7,7 +7,7 @@ export const PromptBuilder = (inst, answr, modelop) => {
if (modelop === RemoteBackendOPModel.MISTRAL) return ""
}
export const buildSolgptPromt = (userPrompt:string, modelOP:RemoteBackendOPModel) => {
export const buildSolgptPrompt = (userPrompt:string, modelOP:RemoteBackendOPModel) => {
if (modelOP === undefined) {
console.log('WARNING: modelOP is undefined. Provide a valid model OP for chat history')
return userPrompt

@ -16,7 +16,7 @@ export type Transaction = {
export class TxRunner {
event
pendingTxs
queusTxs
queueTxs
opt
internalRunner
constructor (internalRunner, opt) {
@ -25,7 +25,7 @@ export class TxRunner {
this.event = new EventManager()
this.pendingTxs = {}
this.queusTxs = []
this.queueTxs = []
}
rawRun (args: Transaction, confirmationCb, gasEstimationForceSend, promptCb, cb) {
@ -42,14 +42,14 @@ export class TxRunner {
function run (self, tx: Transaction, stamp, confirmationCb, gasEstimationForceSend = null, promptCb = null, callback = null) {
if (Object.keys(self.pendingTxs).length) {
return self.queusTxs.push({ tx, stamp, confirmationCb, gasEstimationForceSend, promptCb, callback })
return self.queueTxs.push({ tx, stamp, confirmationCb, gasEstimationForceSend, promptCb, callback })
}
self.pendingTxs[stamp] = tx
self.execute(tx, confirmationCb, gasEstimationForceSend, promptCb, function (error, result) {
delete self.pendingTxs[stamp]
if (callback && typeof callback === 'function') callback(error, result)
if (self.queusTxs.length) {
const next = self.queusTxs.pop()
if (self.queueTxs.length) {
const next = self.queueTxs.pop()
run(self, next.tx, next.stamp, next.confirmationCb, next.gasEstimationForceSend, next.promptCb, next.callback)
}
})

@ -24,7 +24,7 @@ export class TxRunnerVM {
blockNumber
pendingTxs
vmaccounts
queusTxs
queueTxs
blocks: Uint8Array[]
logsManager
commonContext
@ -41,7 +41,7 @@ export class TxRunnerVM {
this.commonContext = this.getVMObject().common
this.pendingTxs = {}
this.vmaccounts = vmaccounts
this.queusTxs = []
this.queueTxs = []
/*
txHash is generated using the nonce,
in order to have unique transaction hash, we need to keep using different nonce (in case of a call)

@ -9,7 +9,7 @@ export class RemixInLineCompletionProvider implements monacoTypes.languages.Inli
props: EditorUIProps
monaco: any
completionEnabled: boolean
task: string
task: string = 'code_completion'
currentCompletion: any
private lastRequestTime: number = 0;
private readonly minRequestInterval: number = 200;
@ -60,13 +60,6 @@ export class RemixInLineCompletionProvider implements monacoTypes.languages.Inli
endColumn: getTextAtLine(model.getLineCount()).length + 1,
});
if (!word.endsWith(' ') &&
!word.endsWith('.') &&
!word.endsWith('"') &&
!word.endsWith('(')) {
return;
}
try {
const split = word.split('\n')
if (split.length < 2) return

@ -2,7 +2,7 @@ import React, { useState, useRef, useEffect, useReducer } from 'react' // eslint
import { FormattedMessage, useIntl } from 'react-intl'
import { isArray } from 'lodash'
import Editor, { DiffEditor, loader, Monaco } from '@monaco-editor/react'
import { AlertModal } from '@remix-ui/app'
import { AppModal } from '@remix-ui/app'
import { ConsoleLogs, QueryParams } from '@remix-project/remix-lib'
import { reducerActions, reducerListener, initialState } from './actions/editor'
import { solidityTokensProvider, solidityLanguageConfig } from './syntaxes/solidity'
@ -664,11 +664,26 @@ export const EditorUI = (props: EditorUIProps) => {
}
})
editor.onDidPaste((e) => {
editor.onDidPaste(async (e) => {
if (!pasteCodeRef.current && e && e.range && e.range.startLineNumber >= 0 && e.range.endLineNumber >= 0 && e.range.endLineNumber - e.range.startLineNumber > 10) {
const modalContent: AlertModal = {
// get the file name
const pastedCode = editor.getModel().getValueInRange(e.range)
const pastedCodePrompt = intl.formatMessage({ id: 'editor.PastedCodeSafety' }, { content:pastedCode })
const modalContent: AppModal = {
id: 'newCodePasted',
title: intl.formatMessage({ id: 'editor.title1' }),
title: "New code pasted",
okLabel: 'Ask RemixAI',
cancelLabel: 'Close',
cancelFn: () => {},
okFn: async () => {
await props.plugin.call('popupPanel', 'showPopupPanel', true)
setTimeout(async () => {
props.plugin.call('remixAI', 'chatPipe', 'vulnerability_check', pastedCodePrompt)
}, 500)
// add matamo event
_paq.push(['trackEvent', 'ai', 'remixAI', 'vulnerability_check_pasted_code'])
},
message: (
<div>
{' '}
@ -699,10 +714,9 @@ export const EditorUI = (props: EditorUIProps) => {
</div>
</div>
</div>
),
)
}
props.plugin.call('notification', 'alert', modalContent)
pasteCodeRef.current = true
props.plugin.call('notification', 'modal', modalContent)
_paq.push(['trackEvent', 'editor', 'onDidPaste', 'more_than_10_lines'])
}
})

@ -1236,7 +1236,7 @@ export const solidityTokensProvider = {
'abstract',
'payable',
'nonpayable',
'constants',
'constant',
'immutable',
'assert',
'require',

@ -34,7 +34,7 @@ export interface CarouselProps {
beforeChange?: (nextSlide: number, state: StateCallBack) => void; // Change callback before sliding every time. `(previousSlide, currentState) => ...`
sliderClass?: string; // Use this to style your own track list.
itemClass?: string; // Use this to style your own Carousel item. For example add padding-left and padding-right
itemAriaLabel?: string; // Use this to add your own Carousel item aria-label.if it is not defined the child aria label will be applied if the child dont have one than a default empty string will be applied
itemAriaLabel?: string; // Use this to add your own Carousel item aria-label.if it is not defined the child aria label will be applied if the child doesn't have one, then a default empty string will be applied
containerClass?: string; // Use this to style the whole container. For example add padding to allow the "dots" or "arrows" to go to other places without being overflown.
className?: string; // Use this to style the whole container with styled-components
dotListClass?: string; // Use this to style the dot list.

@ -34,14 +34,11 @@ export class RemixAppManager extends PluginManager {
event: EventEmitter
pluginsDirectory: string
pluginLoader: PluginLoader // eslint-disable-line no-use-before-define
permissionHandler: PermissionHandler
getAll(): import('@remixproject/plugin-utils').Profile<any>[]
getIds(): string[]
isDependent(name: any): any
isRequired(name: any): any
registeredPlugins(): Promise<any>
turnPluginOn(name: string | string[])
turnPluginOff(name: string)
}
export class PluginManagerSettings {
@ -67,7 +64,7 @@ export type PluginPermissions = {
}
}
export class PluginManagerComponent extends ViewPlugin extends Plugin implements PluginBase {
export class PluginManagerComponent extends ViewPlugin implements PluginBase {
constructor(appManager: RemixAppManager, engine: Engine)
appManager: RemixAppManager
pluginSettings: PluginManagerSettings
@ -154,14 +151,6 @@ declare class PluginLoader {
set(plugin: any, actives: any): void
get(): any
}
// eslint-disable-next-line no-redeclare
export type PluginManagerSettings = {
openDialog: () => void
onValidation: () => void
clearPermission: (from: any, to: any, method: any) => void
settings: () => HTMLElement
render: () => HTMLElement
}
export interface DefaultLocalPlugin extends Profile {
name: string
@ -198,14 +187,5 @@ export type PluginManagerProfile = Profile & {
type: 'iframe' | 'ws'
hash: string
}
// eslint-disable-next-line no-redeclare
export type LocalPlugin = {
create: () => Profile
updateName: (target: string) => void
updateDisplayName: (displayName: string) => void
updateProfile: (key: string, e: Event) => void
updateMethods: (target: any) => void
form: () => HTMLElement
}
export { }

@ -22,7 +22,7 @@ const txHelper = remixLib.execution.txHelper
const txFormat = remixLib.execution.txFormat
const loadContractFromAddress = (plugin: RunTab, address, confirmCb, cb) => {
if (/.(.abi)$/.exec(plugin.config.get('currentFile'))) {
if (/\.(abi)$/.exec(plugin.config.get('currentFile'))) {
confirmCb(() => {
let abi
try {
@ -42,7 +42,7 @@ const loadContractFromAddress = (plugin: RunTab, address, confirmCb, cb) => {
export const getSelectedContract = (contractName: string, compiler: CompilerAbstractType): ContractData => {
if (!contractName) return null
// const compiler = plugin.compilersArtefacts[compilerAtributeName]
// const compiler = plugin.compilersArtefacts[compilerAttributeName]
if (!compiler) return null

@ -235,6 +235,16 @@ export function RunTabUI(props: RunTabProps) {
}
}, [runTab.popup])
useEffect(() => {
if (runTab.selectExEnv.includes('injected') &&
Object.entries(runTab.accounts.loadedAccounts).length === 0 &&
runTab.accounts.selectedAccount.length > 0) {
// switch to vm-cancum because no account is loaded from injected provider
const context = plugin.blockchain.defaultPinnedProviders[0] // vm-cancun
setExecutionEnvironment({ context, fork: '' })
}
}, [runTab.accounts.loadedAccounts])
const setCheckIpfs = (value: boolean) => {
dispatch(setIpfsCheckedState(value))
}

@ -25,6 +25,7 @@ export class Blockchain extends Plugin<any, any> {
};
setupProviders(): void;
providers: any;
defaultPinnedProviders: string[];
getCurrentProvider(): any;
/** Return the list of accounts */
getAccounts(cb?: any): any;

@ -13,10 +13,10 @@ interface ResultSummaryProps {
export const ResultSummary = (props: ResultSummaryProps) => {
const intl = useIntl()
const { hightLightInPath, replaceText, state } = useContext(SearchContext)
const { highlightInPath, replaceText, state } = useContext(SearchContext)
const { modal } = useDialogDispatchers()
const selectLine = async (line: SearchResultLineLine) => {
await hightLightInPath(props.searchResult, line)
await highlightInPath(props.searchResult, line)
}
const confirmReplace = async (line: SearchResultLineLine) => {

@ -19,7 +19,7 @@ export interface SearchingStateInterface {
setWholeWord: (value: boolean) => void
setSearchResults: (value: SearchResult[]) => void
findText: (path: string) => Promise<SearchResultLine[]>
hightLightInPath: (result: SearchResult, line: SearchResultLineLine) => void
highlightInPath: (result: SearchResult, line: SearchResultLineLine) => void
replaceText: (result: SearchResult, line: SearchResultLineLine) => Promise<void>
reloadFile: (file: string) => void
toggleCaseSensitive: () => void
@ -194,7 +194,7 @@ export const SearchProvider = ({ children = [], reducer = SearchReducer, initial
// do nothing
}
},
hightLightInPath: async (result: SearchResult, line: SearchResultLineLine) => {
highlightInPath: async (result: SearchResult, line: SearchResultLineLine) => {
await plugin.call('editor', 'discardHighlight')
await plugin.call('editor', 'highlight', line.position, result.path)
await plugin.call('editor', 'revealRange', line.position.start.line, line.position.start.column, line.position.end.line, line.position.end.column)

@ -88,7 +88,12 @@ export const TabsUI = (props: TabsUIProps) => {
const getAI = async () => {
try {
return await props.plugin.call('settings', 'getCopilotSetting')
const init_state = await props.plugin.call('settings', 'getCopilotSetting')
if (init_state === undefined || init_state === null) {
await props.plugin.call('settings', 'updateCopilotChoice', ai_switch)
return ai_switch
}
return init_state
} catch (e) {
return false
}

@ -235,12 +235,7 @@ export const RemixUiTerminal = (props: RemixUiTerminalProps) => {
try {
if (script.trim().startsWith('git')) {
// await this.call('git', 'execute', script) code might be used in the future
// TODO: rm gpt or redirect gpt to sol-pgt
} else if (script.trim().startsWith('gpt')) {
call('terminal', 'log',{ type: 'warn', value: `> ${script}` })
await call('remixAI', 'solidity_answer', script) // No streaming supported in terminal
_paq.push(['trackEvent', 'ai', 'remixAI', 'askFromTerminal'])
} else if (script.trim().startsWith('sol-gpt')) {
} else if (script.trim().startsWith('gpt') || script.trim().startsWith('sol-gpt')) {
call('terminal', 'log',{ type: 'warn', value: `> ${script}` })
await call('remixAI', 'solidity_answer', script) // No streaming supported in terminal
_paq.push(['trackEvent', 'ai', 'remixAI', 'askFromTerminal'])

@ -70,7 +70,7 @@ export interface FilePanelType extends ViewPlugin {
setWorkspace: ({ name, isLocalhost }, setEvent: boolean) => void
createWorkspace: (name: string, workspaceTemplateName: string) => void
renameWorkspace: (oldName: string, newName: string) => void
compileContractForUml: (path: string) => void
compileContractForUml?: (path: string) => void
workspaceRenamed: ({ name }) => void
workspaceCreated: ({ name }) => void
workspaceDeleted: ({ name }) => void
@ -81,7 +81,7 @@ export interface FilePanelType extends ViewPlugin {
appManager: RemixAppManager
registry?: any // registry
pluginApi?: any
request: {
request?: {
createWorkspace: () => void
setWorkspace: (workspaceName: string) => void
createNewFile: () => void
@ -89,10 +89,10 @@ export interface FilePanelType extends ViewPlugin {
getCurrentWorkspace: () => void
} // api request,
workspaces: any
registeredMenuItems: MenuItems // menu items
removedMenuItems: MenuItems
initialWorkspace: string
resetNewFile: () => void
registeredMenuItems?: MenuItems // menu items
removedMenuItems?: MenuItems
initialWorkspace?: string
resetNewFile?: () => void
getWorkspaces: () => string[]
expandPath: string[]
}

Loading…
Cancel
Save