Add monaco editor for streamlit (#12)
* Init monaco component * Add monaco editoradd-more-languages
parent
b622bd6762
commit
d8f2d03636
|
|
@ -7,7 +7,6 @@ repos:
|
|||
- id: trailing-whitespace
|
||||
- id: end-of-file-fixer
|
||||
- id: check-yaml
|
||||
- id: check-added-large-files
|
||||
- repo: https://github.com/pycqa/isort
|
||||
rev: 5.12.0
|
||||
hooks:
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import streamlit as st
|
||||
from components import tabby
|
||||
from utils.service_info import ServiceInfo
|
||||
|
||||
SERVICES = [
|
||||
|
|
@ -12,5 +13,7 @@ def make_badge_markdown(x: ServiceInfo):
|
|||
return f""
|
||||
|
||||
|
||||
st.markdown("## Status")
|
||||
st.markdown("## Tabby")
|
||||
st.markdown(" ".join(map(make_badge_markdown, SERVICES)))
|
||||
|
||||
tabby.editor()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,44 @@
|
|||
import os
|
||||
|
||||
import streamlit.components.v1 as components
|
||||
|
||||
_RELEASE = __name__ != "__main_"
|
||||
|
||||
# Declare a Streamlit component. `declare_component` returns a function
|
||||
if not _RELEASE:
|
||||
_editor_func = components.declare_component(
|
||||
# We give the component a simple, descriptive name ("my_component"
|
||||
# does not fit this bill, so please choose something better for your
|
||||
# own component :)
|
||||
"tabby-editor",
|
||||
# Pass `url` here to tell Streamlit that the component will be served
|
||||
# by the local dev server that you run via `npm run start`.
|
||||
# (This is useful while your component is in development.)
|
||||
url="http://localhost:3001",
|
||||
)
|
||||
else:
|
||||
# When we're distributing a production version of the component, we'll
|
||||
# replace the `url` param with `path`, and point it to to the component's
|
||||
# build directory:
|
||||
parent_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
build_dir = os.path.join(parent_dir, "frontend/build")
|
||||
_editor_func = components.declare_component("tabby-editor", path=build_dir)
|
||||
|
||||
|
||||
# Create a wrapper function for the component. This is an optional
|
||||
# best practice - we could simply expose the component function returned by
|
||||
# `declare_component` and call it done. The wrapper allows us to customize
|
||||
# our component's API: we can pre-process its input args, post-process its
|
||||
# output value, and add a docstring for users.
|
||||
def editor(tabby_server_url="http://localhost:5000", key=None):
|
||||
_editor_func(tabby_server_url=tabby_server_url, key=key)
|
||||
|
||||
|
||||
# Add some test code to play with the component while it's in development.
|
||||
# During development, we can run this just as we would any other Streamlit
|
||||
# app: `$ streamlit run my_component/__init__.py`
|
||||
if not _RELEASE:
|
||||
import streamlit as st
|
||||
|
||||
tabby_server_url = st.text_input("Tabby Server URL", value="http://localhost:5000")
|
||||
tabby(tabby_server_url)
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
# Run the component's dev server on :3001
|
||||
# (The Streamlit dev server already runs on :3000)
|
||||
PORT=3001
|
||||
|
||||
# Don't automatically open the web browser on `npm run start`.
|
||||
BROWSER=none
|
||||
|
|
@ -0,0 +1 @@
|
|||
node_modules
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"endOfLine": "lf",
|
||||
"semi": false,
|
||||
"trailingComma": "es5"
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"files": {
|
||||
"main.js": "./static/js/main.3a9265b0.chunk.js",
|
||||
"main.js.map": "./static/js/main.3a9265b0.chunk.js.map",
|
||||
"runtime-main.js": "./static/js/runtime-main.44d30fc2.js",
|
||||
"runtime-main.js.map": "./static/js/runtime-main.44d30fc2.js.map",
|
||||
"static/js/2.ae80075f.chunk.js": "./static/js/2.ae80075f.chunk.js",
|
||||
"static/js/2.ae80075f.chunk.js.map": "./static/js/2.ae80075f.chunk.js.map",
|
||||
"index.html": "./index.html",
|
||||
"precache-manifest.1d3088fc135428c2ea5392e379f82710.js": "./precache-manifest.1d3088fc135428c2ea5392e379f82710.js",
|
||||
"service-worker.js": "./service-worker.js",
|
||||
"static/js/2.ae80075f.chunk.js.LICENSE.txt": "./static/js/2.ae80075f.chunk.js.LICENSE.txt",
|
||||
"static/js/main.3a9265b0.chunk.js.LICENSE.txt": "./static/js/main.3a9265b0.chunk.js.LICENSE.txt"
|
||||
},
|
||||
"entrypoints": [
|
||||
"static/js/runtime-main.44d30fc2.js",
|
||||
"static/js/2.ae80075f.chunk.js",
|
||||
"static/js/main.3a9265b0.chunk.js"
|
||||
]
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1 @@
|
|||
<!doctype html><html lang="en"><head><title>Streamlit Component</title><meta charset="UTF-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="Streamlit Component"/><link rel="stylesheet" href="bootstrap.min.css"/></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script>!function(e){function t(t){for(var n,l,a=t[0],p=t[1],i=t[2],c=0,s=[];c<a.length;c++)l=a[c],Object.prototype.hasOwnProperty.call(o,l)&&o[l]&&s.push(o[l][0]),o[l]=0;for(n in p)Object.prototype.hasOwnProperty.call(p,n)&&(e[n]=p[n]);for(f&&f(t);s.length;)s.shift()();return u.push.apply(u,i||[]),r()}function r(){for(var e,t=0;t<u.length;t++){for(var r=u[t],n=!0,a=1;a<r.length;a++){var p=r[a];0!==o[p]&&(n=!1)}n&&(u.splice(t--,1),e=l(l.s=r[0]))}return e}var n={},o={1:0},u=[];function l(t){if(n[t])return n[t].exports;var r=n[t]={i:t,l:!1,exports:{}};return e[t].call(r.exports,r,r.exports,l),r.l=!0,r.exports}l.m=e,l.c=n,l.d=function(e,t,r){l.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},l.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},l.t=function(e,t){if(1&t&&(e=l(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(l.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var n in e)l.d(r,n,function(t){return e[t]}.bind(null,n));return r},l.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return l.d(t,"a",t),t},l.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},l.p="./";var a=this.webpackJsonpstreamlit_component_template=this.webpackJsonpstreamlit_component_template||[],p=a.push.bind(a);a.push=t,a=a.slice();for(var i=0;i<a.length;i++)t(a[i]);var f=p;r()}([])</script><script src="./static/js/2.ae80075f.chunk.js"></script><script src="./static/js/main.3a9265b0.chunk.js"></script></body></html>
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
self.__precacheManifest = (self.__precacheManifest || []).concat([
|
||||
{
|
||||
"revision": "42fedf3d1999ef9b28619146c4e415cd",
|
||||
"url": "./index.html"
|
||||
},
|
||||
{
|
||||
"revision": "409a462d1d8f6189ac9a",
|
||||
"url": "./static/js/2.ae80075f.chunk.js"
|
||||
},
|
||||
{
|
||||
"revision": "df087e3b51cab167e93df344458ea8f1",
|
||||
"url": "./static/js/2.ae80075f.chunk.js.LICENSE.txt"
|
||||
},
|
||||
{
|
||||
"revision": "ab4b2d8e1d0c358de5ef",
|
||||
"url": "./static/js/main.3a9265b0.chunk.js"
|
||||
},
|
||||
{
|
||||
"revision": "4e0e34f265fae8f33b01b27ae29d9d6f",
|
||||
"url": "./static/js/main.3a9265b0.chunk.js.LICENSE.txt"
|
||||
},
|
||||
{
|
||||
"revision": "7e9d84e346ce158d1e50",
|
||||
"url": "./static/js/runtime-main.44d30fc2.js"
|
||||
}
|
||||
]);
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
/**
|
||||
* Welcome to your Workbox-powered service worker!
|
||||
*
|
||||
* You'll need to register this file in your web app and you should
|
||||
* disable HTTP caching for this file too.
|
||||
* See https://goo.gl/nhQhGp
|
||||
*
|
||||
* The rest of the code is auto-generated. Please don't update this file
|
||||
* directly; instead, make changes to your Workbox build configuration
|
||||
* and re-run your build process.
|
||||
* See https://goo.gl/2aRDsh
|
||||
*/
|
||||
|
||||
importScripts("https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js");
|
||||
|
||||
importScripts(
|
||||
"./precache-manifest.1d3088fc135428c2ea5392e379f82710.js"
|
||||
);
|
||||
|
||||
self.addEventListener('message', (event) => {
|
||||
if (event.data && event.data.type === 'SKIP_WAITING') {
|
||||
self.skipWaiting();
|
||||
}
|
||||
});
|
||||
|
||||
workbox.core.clientsClaim();
|
||||
|
||||
/**
|
||||
* The workboxSW.precacheAndRoute() method efficiently caches and responds to
|
||||
* requests for URLs in the manifest.
|
||||
* See https://goo.gl/S9QRab
|
||||
*/
|
||||
self.__precacheManifest = [].concat(self.__precacheManifest || []);
|
||||
workbox.precaching.precacheAndRoute(self.__precacheManifest, {});
|
||||
|
||||
workbox.routing.registerNavigationRoute(workbox.precaching.getCacheKeyForURL("./index.html"), {
|
||||
|
||||
blacklist: [/^\/_/,/\/[^/?]+\.[^/]+$/],
|
||||
});
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
object-assign
|
||||
(c) Sindre Sorhus
|
||||
@license MIT
|
||||
*/
|
||||
|
||||
/*!
|
||||
* The buffer module from node.js, for the browser.
|
||||
*
|
||||
* @author Feross Aboukhadijeh <http://feross.org>
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
/*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh <https://feross.org/opensource> */
|
||||
|
||||
/*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */
|
||||
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2018-2021 Streamlit Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/** @license React v0.19.1
|
||||
* scheduler.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/** @license React v16.13.1
|
||||
* react-is.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/** @license React v16.14.0
|
||||
* react-dom.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/** @license React v16.14.0
|
||||
* react-jsx-runtime.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/** @license React v16.14.0
|
||||
* react.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1 @@
|
|||
/*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,2 @@
|
|||
!function(e){function t(t){for(var n,l,a=t[0],p=t[1],i=t[2],c=0,s=[];c<a.length;c++)l=a[c],Object.prototype.hasOwnProperty.call(o,l)&&o[l]&&s.push(o[l][0]),o[l]=0;for(n in p)Object.prototype.hasOwnProperty.call(p,n)&&(e[n]=p[n]);for(f&&f(t);s.length;)s.shift()();return u.push.apply(u,i||[]),r()}function r(){for(var e,t=0;t<u.length;t++){for(var r=u[t],n=!0,a=1;a<r.length;a++){var p=r[a];0!==o[p]&&(n=!1)}n&&(u.splice(t--,1),e=l(l.s=r[0]))}return e}var n={},o={1:0},u=[];function l(t){if(n[t])return n[t].exports;var r=n[t]={i:t,l:!1,exports:{}};return e[t].call(r.exports,r,r.exports,l),r.l=!0,r.exports}l.m=e,l.c=n,l.d=function(e,t,r){l.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},l.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},l.t=function(e,t){if(1&t&&(e=l(e)),8&t)return e;if(4&t&&"object"===typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(l.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var n in e)l.d(r,n,function(t){return e[t]}.bind(null,n));return r},l.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return l.d(t,"a",t),t},l.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},l.p="./";var a=this.webpackJsonpstreamlit_component_template=this.webpackJsonpstreamlit_component_template||[],p=a.push.bind(a);a.push=t,a=a.slice();for(var i=0;i<a.length;i++)t(a[i]);var f=p;r()}([]);
|
||||
//# sourceMappingURL=runtime-main.44d30fc2.js.map
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,45 @@
|
|||
{
|
||||
"name": "streamlit_component_template",
|
||||
"version": "1.0.3",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@monaco-editor/react": "^4.4.6",
|
||||
"@testing-library/jest-dom": "^4.2.4",
|
||||
"@testing-library/react": "^9.3.2",
|
||||
"@testing-library/user-event": "^7.1.2",
|
||||
"@types/jest": "^24.0.0",
|
||||
"@types/node": "^12.0.0",
|
||||
"@types/react": "^16.9.0",
|
||||
"@types/react-dom": "^16.9.0",
|
||||
"axios": "^1.3.4",
|
||||
"react": "^16.13.1",
|
||||
"react-dom": "^16.13.1",
|
||||
"react-scripts": "3.4.1",
|
||||
"streamlit-component-lib-react-hooks": "^1.0.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "^4.6.2"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts start",
|
||||
"build": "react-scripts build",
|
||||
"test": "react-scripts test",
|
||||
"eject": "react-scripts eject"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": "react-app"
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
">0.2%",
|
||||
"not dead",
|
||||
"not op_mini all"
|
||||
],
|
||||
"development": [
|
||||
"last 1 chrome version",
|
||||
"last 1 firefox version",
|
||||
"last 1 safari version"
|
||||
]
|
||||
},
|
||||
"homepage": "."
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,25 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>Streamlit Component</title>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<meta name="description" content="Streamlit Component" />
|
||||
<link rel="stylesheet" href="bootstrap.min.css" />
|
||||
</head>
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="root"></div>
|
||||
<!--
|
||||
This HTML file is a template.
|
||||
If you open it directly in the browser, you will see an empty page.
|
||||
|
||||
You can add webfonts, meta tags, or analytics to this file.
|
||||
The build step will place the bundled scripts into the <body> tag.
|
||||
|
||||
To begin the development, run `npm start` or `yarn start`.
|
||||
To create a production bundle, use `npm run build` or `yarn build`.
|
||||
-->
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,145 @@
|
|||
import axios from "axios"
|
||||
import { useRenderData } from "streamlit-component-lib-react-hooks"
|
||||
|
||||
import React, { useEffect } from "react"
|
||||
import Monaco, { useMonaco } from "@monaco-editor/react"
|
||||
|
||||
const PythonParseJSON = `def parse_json_lines(filename: str) -> List[Any]:
|
||||
output = []
|
||||
with open(filename, "r", encoding="utf-8") as f:
|
||||
`
|
||||
|
||||
export default function TabbyEditor() {
|
||||
const renderData = useRenderData()
|
||||
|
||||
;(window as any).tabbyServerURL = renderData.args.tabby_server_url
|
||||
|
||||
const monaco = useMonaco()
|
||||
useEffect(() => {
|
||||
if (!monaco) return
|
||||
monaco.languages.registerInlineCompletionsProvider(
|
||||
{ pattern: "**" },
|
||||
new CompletionProvider(monaco)
|
||||
)
|
||||
}, [monaco])
|
||||
|
||||
return (
|
||||
<div style={{ height: 400 }}>
|
||||
<Monaco
|
||||
theme="vs-dark"
|
||||
defaultLanguage="python"
|
||||
defaultValue={PythonParseJSON}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
class CompletionProvider {
|
||||
private monaco: any
|
||||
private latestTimestamp: number
|
||||
private pendingRequest: any
|
||||
|
||||
constructor(monaco: any) {
|
||||
this.monaco = monaco
|
||||
this.latestTimestamp = 0
|
||||
}
|
||||
|
||||
async provideInlineCompletions(
|
||||
document: any,
|
||||
position: any,
|
||||
context: any,
|
||||
token: any
|
||||
) {
|
||||
const prompt = this.getPrompt(document, position)
|
||||
const emptyResponse = Promise.resolve({ items: [] })
|
||||
|
||||
if (this.isNil(prompt)) {
|
||||
console.debug("Prompt is empty, skipping")
|
||||
return emptyResponse
|
||||
}
|
||||
|
||||
const currentTimestamp = Date.now()
|
||||
this.latestTimestamp = currentTimestamp
|
||||
|
||||
await this.sleep(500)
|
||||
if (this.pendingRequest) await this.pendingRequest
|
||||
if (currentTimestamp < this.latestTimestamp) {
|
||||
return emptyResponse
|
||||
}
|
||||
|
||||
const response = await this.callTabbyApi(currentTimestamp, prompt)
|
||||
const hasSuffixParen = this.hasSuffixParen(document, position)
|
||||
const replaceRange = hasSuffixParen
|
||||
? new this.monaco.Range(
|
||||
position.lineNumber,
|
||||
position.column,
|
||||
position.lineNumber,
|
||||
position.column + 1
|
||||
)
|
||||
: new this.monaco.Range(
|
||||
position.lineNumber,
|
||||
position.column,
|
||||
position.lineNumber,
|
||||
position.column
|
||||
)
|
||||
const items = this.toInlineCompletions(response.data, replaceRange)
|
||||
return Promise.resolve({ items })
|
||||
}
|
||||
|
||||
freeInlineCompletions() {}
|
||||
|
||||
getPrompt(document: any, position: any): string {
|
||||
const firstLine = Math.max(position.lineNumber - 120, 0)
|
||||
|
||||
const range = new this.monaco.Range(
|
||||
firstLine,
|
||||
0,
|
||||
position.lineNumber,
|
||||
position.column
|
||||
)
|
||||
return document.getValueInRange(range)
|
||||
}
|
||||
|
||||
isNil(value: any) {
|
||||
return value === undefined || value === null || value.length === 0
|
||||
}
|
||||
|
||||
sleep(milliseconds: number) {
|
||||
return new Promise((r) => setTimeout(r, milliseconds))
|
||||
}
|
||||
|
||||
async callTabbyApi(timestamp: number, prompt: string) {
|
||||
const request = (this.pendingRequest = axios.post(
|
||||
`${(window as any).tabbyServerURL}/v1/completions`,
|
||||
{
|
||||
prompt,
|
||||
}
|
||||
))
|
||||
const response = await request
|
||||
this.pendingRequest = null
|
||||
return response
|
||||
}
|
||||
|
||||
toInlineCompletions(value: any, range: any) {
|
||||
return (
|
||||
value.choices
|
||||
?.map((choice: any) => choice.text)
|
||||
.map((text: string) => ({
|
||||
range,
|
||||
text,
|
||||
})) || []
|
||||
)
|
||||
}
|
||||
|
||||
hasSuffixParen(document: any, position: any): boolean {
|
||||
const suffix = document.getValueInRange(
|
||||
new this.monaco.Range(
|
||||
position.lineNumber,
|
||||
position.column,
|
||||
position.lineNumber,
|
||||
position.column + 1
|
||||
)
|
||||
)
|
||||
return ")]}".indexOf(suffix) > -1
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
import React from "react"
|
||||
import ReactDOM from "react-dom"
|
||||
import { StreamlitProvider } from "streamlit-component-lib-react-hooks"
|
||||
import Tabby from "./Tabby"
|
||||
|
||||
ReactDOM.render(
|
||||
<React.StrictMode>
|
||||
<StreamlitProvider>
|
||||
<Tabby />
|
||||
</StreamlitProvider>
|
||||
</React.StrictMode>,
|
||||
document.getElementById("root")
|
||||
)
|
||||
|
|
@ -0,0 +1 @@
|
|||
/// <reference types="react-scripts" />
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"strict": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
"jsx": "react"
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -3,6 +3,7 @@ import os
|
|||
|
||||
import uvicorn
|
||||
from fastapi import FastAPI, Response
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from fastapi.responses import JSONResponse
|
||||
|
||||
from . import events
|
||||
|
|
@ -16,6 +17,14 @@ app = FastAPI(
|
|||
docs_url="/",
|
||||
)
|
||||
|
||||
app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=["*"],
|
||||
allow_credentials=False,
|
||||
allow_methods=["*"],
|
||||
allow_headers=["*"],
|
||||
)
|
||||
|
||||
MODEL_NAME = os.environ.get("MODEL_NAME")
|
||||
MODEL_BACKEND = os.environ.get("MODEL_BACKEND", "python")
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue