From df7fb02cb8c516e8cabe039140542ca6af6268e5 Mon Sep 17 00:00:00 2001 From: Brian Ineza Date: Tue, 25 Feb 2025 14:54:00 +0100 Subject: [PATCH 1/5] ft: python backend --- .vscode/settings.json | 3 +- applications/browser/package.json | 3 +- packages/python/package.json | 51 ++ packages/python/postcss.config.js | 6 + .../src/browser/components/TextAnalysis.tsx | 248 +++++++++ .../python/src/browser/python-contribution.ts | 80 +++ .../src/browser/python-frontend-module.ts | 39 ++ .../python/src/browser/styles/globals.css | 3 + .../src/browser/widgets/checks-widget.tsx | 99 ++++ packages/python/src/common/python-protocol.ts | 9 + .../python/src/node/python-backend-module.ts | 20 + packages/python/src/node/python-service.ts | 476 ++++++++++++++++++ packages/python/tailwind.config.js | 469 +++++++++++++++++ packages/python/tsconfig.json | 10 + yarn.lock | 195 ++++++- 15 files changed, 1691 insertions(+), 20 deletions(-) create mode 100644 packages/python/package.json create mode 100644 packages/python/postcss.config.js create mode 100644 packages/python/src/browser/components/TextAnalysis.tsx create mode 100644 packages/python/src/browser/python-contribution.ts create mode 100644 packages/python/src/browser/python-frontend-module.ts create mode 100644 packages/python/src/browser/styles/globals.css create mode 100644 packages/python/src/browser/widgets/checks-widget.tsx create mode 100644 packages/python/src/common/python-protocol.ts create mode 100644 packages/python/src/node/python-backend-module.ts create mode 100644 packages/python/src/node/python-service.ts create mode 100644 packages/python/tailwind.config.js create mode 100644 packages/python/tsconfig.json diff --git a/.vscode/settings.json b/.vscode/settings.json index 25fa6215..ed23d529 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,4 @@ { - "typescript.tsdk": "node_modules/typescript/lib" + "typescript.tsdk": "node_modules/typescript/lib", + "cSpell.words": ["venv"] } diff --git a/applications/browser/package.json b/applications/browser/package.json index 65d652bc..a0aa47f8 100644 --- a/applications/browser/package.json +++ b/applications/browser/package.json @@ -22,7 +22,8 @@ "@scribe/theia-utils": "0.0.1", "@theia/git": "1.51.0", "@theia/scm": "1.51.0", - "scribe-usfm-editor": "0.0.0" + "scribe-usfm-editor": "0.0.0", + "scribe-python": "0.1.0" }, "devDependencies": { "@theia/cli": "1.51.0" diff --git a/packages/python/package.json b/packages/python/package.json new file mode 100644 index 00000000..72972cb7 --- /dev/null +++ b/packages/python/package.json @@ -0,0 +1,51 @@ +{ + "name": "scribe-python", + "version": "0.1.0", + "keywords": [ + "theia-extension" + ], + "scripts": { + "build:style": "npx tailwindcss -i ./src/browser/styles/globals.css -o ./lib/browser/output-tailwind.css -c ./tailwind.config.js", + "build:ts": "tsc", + "build": "yarn build:ts && yarn build:style", + "production": "yarn build", + "watch": "npm-watch build", + "clean": "rimraf lib node_modules *.tsbuildinfo", + "productionCICD": "yarn build" + }, + "dependencies": { + "@theia/core": "1.51.0", + "axios": "^1.6.2", + "extract-zip": "^2.0.1", + "fs-extra": "^11.2.0", + "inversify": "^6.0.1", + "tar": "^7.4.3" + }, + "devDependencies": { + "rimraf": "^5.0.5", + "tailwindcss": "^3.4.1", + "tailwindcss-animate": "^1.0.7", + "postcss": "^8.4.35", + "autoprefixer": "^10.4.17", + "npm-watch": "^0.13.0" + }, + "files": [ + "lib", + "src" + ], + "theiaExtensions": [ + { + "backend": "lib/node/python-backend-module", + "frontend": "lib/browser/python-frontend-module" + } + ], + "watch": { + "build": { + "patterns": [ + "src/**/*" + ], + "extensions": "ts,html,scss,css,tsx,json", + "quiet": false + } + } +} diff --git a/packages/python/postcss.config.js b/packages/python/postcss.config.js new file mode 100644 index 00000000..12a703d9 --- /dev/null +++ b/packages/python/postcss.config.js @@ -0,0 +1,6 @@ +module.exports = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +}; diff --git a/packages/python/src/browser/components/TextAnalysis.tsx b/packages/python/src/browser/components/TextAnalysis.tsx new file mode 100644 index 00000000..3ed963e7 --- /dev/null +++ b/packages/python/src/browser/components/TextAnalysis.tsx @@ -0,0 +1,248 @@ +import React from "react"; +import { useState } from "react"; +import { ChevronDown, ChevronRight } from "lucide-react"; + +export interface AnalysisData { + n_lines: number; + n_characters: number; + "letter-script": Record; + "number-script": Record; + "other-script": Record; + "non-canonical": Record< + string, + { + orig: string; + norm: string; + "orig-count": number; + "norm-count": number; + "orig-form": string; + "norm-form": string; + changes: string[]; + } + >; + "char-conflict": Record; + "notable-token": Record< + string, + Record + >; + pattern: Record< + string, + Record + >; + block: Record< + string, + Record< + string, + { + char: string; + id: string; + name: string; + count: number; + ex: [string, number][]; + } + > + >; +} + +const CollapsibleSection: React.FC<{ + title: string; + children: React.ReactNode; +}> = ({ title, children }) => { + const [isOpen, setIsOpen] = useState(false); + + return ( +
+ + {isOpen &&
{children}
} +
+ ); +}; + +export const TextAnalysis: React.FC<{ data: AnalysisData }> = ({ data }) => { + return ( +
+

+ Text Analysis Results +

+ +
+
+

+ Number of Lines +

+

{data.n_lines}

+
+
+

+ Number of Characters +

+

{data.n_characters}

+
+
+ + + {Object.entries(data["letter-script"]).map(([script, info]) => ( +
+

+ {script} +

+

Count: {info.count}

+ {info.ex && ( +

Example: {info.ex}

+ )} +
+ ))} +
+ + + {Object.entries(data["number-script"]).map(([script, info]) => ( +
+

+ {script} +

+

Count: {info.count}

+

Example: {info.ex}

+
+ ))} +
+ + + {Object.entries(data["other-script"]).map(([script, info]) => ( +
+

+ {script} +

+

Count: {info.count}

+

Example: {info.ex}

+
+ ))} +
+ + + {Object.entries(data["non-canonical"]).map(([char, info]) => ( +
+

+ {char} +

+

+ Original: {info.orig} (Count: {info["orig-count"]}) +

+

+ Normalized: {info.norm} (Count: {info["norm-count"]}) +

+

+ Changes: {info.changes.join(", ")} +

+
+ ))} +
+ + + {Object.entries(data["notable-token"]).map(([category, tokens]) => ( +
+

+ {category} +

+ {Object.entries(tokens).map(([token, info]) => ( +
+

+ Token: {info.token} +

+

+ Count: {info.count} +

+

+ Examples:{" "} + {info.ex + .map(([ex, line]) => `${ex} (line ${line})`) + .join(", ")} +

+
+ ))} +
+ ))} +
+ + + {Object.entries(data.pattern).map(([category, patterns]) => ( +
+

+ {category} +

+ {Object.entries(patterns).map(([pattern, info]) => ( +
+

+ Pattern: {info.pattern} +

+

+ Count: {info.count} +

+

+ Examples:{" "} + {info.ex + .map(([ex, line]) => `${ex} (line ${line})`) + .join(", ")} +

+
+ ))} +
+ ))} +
+ + + {Object.entries(data.block).map(([blockName, characters]) => ( +
+

+ {blockName} +

+ {Object.entries(characters).map(([char, info]) => ( +
+

+ Character: {info.char} ({info.id}) +

+

Name: {info.name}

+

+ Count: {info.count} +

+

+ Examples:{" "} + {info.ex + .map(([ex, line]) => `${ex} (line ${line})`) + .join(", ")} +

+
+ ))} +
+ ))} +
+
+ ); +}; diff --git a/packages/python/src/browser/python-contribution.ts b/packages/python/src/browser/python-contribution.ts new file mode 100644 index 00000000..67863cd3 --- /dev/null +++ b/packages/python/src/browser/python-contribution.ts @@ -0,0 +1,80 @@ +import { injectable, inject } from "@theia/core/shared/inversify"; +import { + Command, + CommandContribution, + CommandRegistry, + MessageService, +} from "@theia/core/lib/common"; +import { PythonService } from "../common/python-protocol"; + +@injectable() +export class PythonSetupContribution implements CommandContribution { + static readonly SETUP_ENV: Command = { + id: "scribe.python.setup", + label: "Python: Setup Python Environment", + }; + + static readonly SETUP_WILDEBEEST: Command = { + id: "scribe.python.setup-wildebeest", + label: "Python: Setup Wildebeest", + }; + + static readonly EXECUTE_WILDEBEEST: Command = { + id: "scribe.python.execute-wildebeest", + label: "Python: Execute Wildebeest", + }; + + @inject(MessageService) + private messageService: MessageService; + + @inject(PythonService) + private pythonService: PythonService; + + registerCommands(registry: CommandRegistry): void { + registry.registerCommand(PythonSetupContribution.SETUP_ENV, { + execute: async () => { + this.messageService.info("Starting Python environment setup..."); + try { + await this.pythonService.setupEnvironment(); + this.messageService.info("Python environment setup completed!"); + } catch (error) { + this.messageService.error(`Setup failed: ${error.message}`); + } + }, + }); + + registry.registerCommand(PythonSetupContribution.SETUP_WILDEBEEST, { + execute: async () => { + this.messageService.info("Starting Wildebeest setup..."); + try { + await this.pythonService.setupWildebeest(); + this.messageService.info("Wildebeest setup completed!"); + } catch (error) { + this.messageService.error(`Setup failed: ${error.message}`); + } + }, + }); + + registry.registerCommand(PythonSetupContribution.EXECUTE_WILDEBEEST, { + execute: async () => { + await this.pythonService.executeWildebeest(` + This is a problematic text file designed to contain multiple issues for testing purposes: +1. UTF-8 encoding violations: ����� (these should not appear properly). +2. Control characters:  embedded within text. +3. Zero-width characters: word​separator and ‍joiner. +4. Mixed letters/numbers/punctuation/letter-modifiers from various scripts: + - Arabic: العربية. + - Greek: αβγ. + - Cyrillic: АБВ. + - Latin: aͯ́b. + - Hebrew: אבג. +5. Tokens with letters from different scripts: αБاא. +6. XML tokens: Invalid & "special" . +7. Tokens with certain punctuation: foo!bar?baz,hello;world. +8. Orphan letter modifiers: áḅ̂. +9. Non-canonical character combinations: áá (á should be normalized to á). + `); + }, + }); + } +} diff --git a/packages/python/src/browser/python-frontend-module.ts b/packages/python/src/browser/python-frontend-module.ts new file mode 100644 index 00000000..bfb637c6 --- /dev/null +++ b/packages/python/src/browser/python-frontend-module.ts @@ -0,0 +1,39 @@ +import { ContainerModule } from "@theia/core/shared/inversify"; +import { CommandContribution } from "@theia/core/lib/common"; +import { ServiceConnectionProvider } from "@theia/core/lib/browser/messaging/service-connection-provider"; +import { PythonSetupContribution } from "./python-contribution"; +import { PythonService, PythonServicePath } from "../common/python-protocol"; +import { + FrontendApplicationContribution, + WidgetFactory, +} from "@theia/core/lib/browser"; +import { + ChecksWidget, + ChecksWidgetContribution, +} from "./widgets/checks-widget"; +import { bindViewContribution } from "@theia/core/lib/browser"; + +import "../../lib/browser/output-tailwind.css"; + +export default new ContainerModule((bind) => { + bind(CommandContribution).to(PythonSetupContribution); + + bind(PythonService) + .toDynamicValue((ctx) => { + const connection = ctx.container.get( + ServiceConnectionProvider + ); + return connection.createProxy(PythonServicePath); + }) + .inSingletonScope(); + + bindViewContribution(bind, ChecksWidgetContribution); + bind(FrontendApplicationContribution).toService(ChecksWidgetContribution); + bind(ChecksWidget).toSelf(); + bind(WidgetFactory) + .toDynamicValue((ctx) => ({ + id: ChecksWidget.ID, + createWidget: () => ctx.container.get(ChecksWidget), + })) + .inSingletonScope(); +}); diff --git a/packages/python/src/browser/styles/globals.css b/packages/python/src/browser/styles/globals.css new file mode 100644 index 00000000..b5c61c95 --- /dev/null +++ b/packages/python/src/browser/styles/globals.css @@ -0,0 +1,3 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; diff --git a/packages/python/src/browser/widgets/checks-widget.tsx b/packages/python/src/browser/widgets/checks-widget.tsx new file mode 100644 index 00000000..82117ec8 --- /dev/null +++ b/packages/python/src/browser/widgets/checks-widget.tsx @@ -0,0 +1,99 @@ +import * as React from "@theia/core/shared/react"; +import { + inject, + injectable, + postConstruct, +} from "@theia/core/shared/inversify"; +import { ReactWidget } from "@theia/core/lib/browser/widgets/react-widget"; +import { + AbstractViewContribution, + FrontendApplicationContribution, + FrontendApplication, + codicon, +} from "@theia/core/lib/browser"; +import { FrontendApplicationStateService } from "@theia/core/lib/browser/frontend-application-state"; +import { WorkspaceService } from "@theia/workspace/lib/browser"; +import { AnalysisData, TextAnalysis } from "../components/TextAnalysis"; +import { PythonService } from "../../common/python-protocol"; + +@injectable() +export class ChecksWidget extends ReactWidget { + static readonly ID = "python-checks-widget"; + static readonly LABEL = "Checks"; + + private analysisData: AnalysisData | null = null; + + @inject(PythonService) + private pythonService: PythonService; + + @postConstruct() + protected init(): void { + this.doInit(); + } + + protected async doInit(): Promise { + this.id = ChecksWidget.ID; + this.title.label = ChecksWidget.LABEL; + this.title.caption = ChecksWidget.LABEL; + this.title.closable = true; + this.title.iconClass = codicon("checklist"); + this.update(); + + this.getAnalysisData().then((data) => { + this.analysisData = data; + this.update(); + }); + } + + protected async getAnalysisData(): Promise { + const data = await this.pythonService.executeWildebeest(` + This is a problematic text file designed to contain multiple issues for testing purposes: +1. UTF-8 encoding violations: (these should not appear properly). +2. Control characters:  embedded within text. +3. Zero-width characters: word​separator and ‍joiner. +4. Mixed letters/numbers/punctuation/letter-modifiers from various scripts: + - Arabic: العربية. + - Greek: αβγ. + `); + return JSON.parse(data); + } + + render(): React.ReactNode { + return ( +
+ {this.analysisData && } +
+ ); + } +} + +@injectable() +export class ChecksWidgetContribution + extends AbstractViewContribution + implements FrontendApplicationContribution +{ + @inject(FrontendApplicationStateService) + protected readonly stateService: FrontendApplicationStateService; + + @inject(WorkspaceService) + protected readonly workspaceService: WorkspaceService; + + constructor() { + super({ + widgetId: ChecksWidget.ID, + widgetName: ChecksWidget.LABEL, + defaultWidgetOptions: { + area: "right", + }, + }); + } + + async onStart(app: FrontendApplication): Promise { + this.stateService.reachedState("ready").then(() => { + this.openView({ + activate: true, + reveal: true, + }); + }); + } +} diff --git a/packages/python/src/common/python-protocol.ts b/packages/python/src/common/python-protocol.ts new file mode 100644 index 00000000..e054dd64 --- /dev/null +++ b/packages/python/src/common/python-protocol.ts @@ -0,0 +1,9 @@ +export const PythonServicePath = "/services/python"; + +export const PythonService = Symbol("PythonService"); + +export interface PythonService { + setupEnvironment(): Promise; + setupWildebeest(): Promise; + executeWildebeest(text: string): Promise; +} diff --git a/packages/python/src/node/python-backend-module.ts b/packages/python/src/node/python-backend-module.ts new file mode 100644 index 00000000..3c006a3c --- /dev/null +++ b/packages/python/src/node/python-backend-module.ts @@ -0,0 +1,20 @@ +import { ContainerModule } from "@theia/core/shared/inversify"; +import { + ConnectionHandler, + RpcConnectionHandler, +} from "@theia/core/lib/common/messaging"; +import { PythonService, PythonServicePath } from "../common/python-protocol"; +import { PythonServiceImpl } from "./python-service"; + +export default new ContainerModule((bind) => { + bind(PythonService).to(PythonServiceImpl).inSingletonScope(); + + bind(ConnectionHandler) + .toDynamicValue( + (ctx) => + new RpcConnectionHandler(PythonServicePath, () => + ctx.container.get(PythonService) + ) + ) + .inSingletonScope(); +}); diff --git a/packages/python/src/node/python-service.ts b/packages/python/src/node/python-service.ts new file mode 100644 index 00000000..02e0deae --- /dev/null +++ b/packages/python/src/node/python-service.ts @@ -0,0 +1,476 @@ +import { + injectable, + inject, + postConstruct, +} from "@theia/core/shared/inversify"; +import { EnvVariablesServer } from "@theia/core/lib/common/env-variables"; +import { PythonService } from "../common/python-protocol"; +import { DiskFileSystemProvider } from "@theia/filesystem/lib/node/disk-file-system-provider"; +import { FileSystemProviderErrorCode } from "@theia/filesystem/lib/common/files"; +import { URI } from "@theia/core/lib/common/uri"; +import axios from "axios"; +import { platform, machine } from "os"; +import * as tar from "tar"; +import { spawn } from "child_process"; +@injectable() +export class PythonServiceImpl implements PythonService { + // Static path components + private static readonly SCRIBE_DIR_NAME = ".scribe"; + private static readonly PYTHON_DIR_NAME = "python"; + private static readonly APP_VENV_DIR_NAME = "app-venv"; + private static readonly PYTHON_BIN_NAME = "python3.13"; + private static readonly PYTHON_GENERIC_BIN_NAME = "python"; + + // Add new static property for executable directory + private static readonly EXEC_DIR_NAME = + platform() === "win32" ? "Scripts" : "bin"; + + // Static URIs - these will be initialized in initializeStaticUris + private static scribeDir: URI; + private static pythonDir: URI; + private static pythonBinPath: URI; + private static pythonGenericBinPath: URI; + private static venvDir: URI; + + @inject(EnvVariablesServer) + private envServer: EnvVariablesServer; + + @inject(DiskFileSystemProvider) + private fileService: DiskFileSystemProvider; + + @postConstruct() + protected async init(): Promise { + await this.initializeStaticUris(); + } + + private async initializeStaticUris(): Promise { + const homeDir = new URI(await this.envServer.getHomeDirUri()); + + // Initialize scribeDir + PythonServiceImpl.scribeDir = homeDir.resolve( + PythonServiceImpl.SCRIBE_DIR_NAME + ); + + // Initialize pythonDir + PythonServiceImpl.pythonDir = PythonServiceImpl.scribeDir.withPath( + PythonServiceImpl.scribeDir.path.join(PythonServiceImpl.PYTHON_DIR_NAME) + ); + + // Initialize venvDir + PythonServiceImpl.venvDir = PythonServiceImpl.scribeDir.withPath( + PythonServiceImpl.scribeDir.path.join(PythonServiceImpl.APP_VENV_DIR_NAME) + ); + + // Check if venv exists and use its binaries if it does + const venvExists = await this.fileService + .stat(PythonServiceImpl.venvDir) + .catch(() => { + return false; + }); + + if (venvExists) { + // Use venv binaries + PythonServiceImpl.pythonBinPath = PythonServiceImpl.venvDir.withPath( + PythonServiceImpl.venvDir.path.join( + PythonServiceImpl.EXEC_DIR_NAME, + PythonServiceImpl.PYTHON_BIN_NAME + ) + ); + + PythonServiceImpl.pythonGenericBinPath = + PythonServiceImpl.venvDir.withPath( + PythonServiceImpl.venvDir.path.join( + PythonServiceImpl.EXEC_DIR_NAME, + PythonServiceImpl.PYTHON_GENERIC_BIN_NAME + ) + ); + } else { + // Use base Python installation binaries + PythonServiceImpl.pythonBinPath = PythonServiceImpl.pythonDir.withPath( + PythonServiceImpl.pythonDir.path.join( + PythonServiceImpl.EXEC_DIR_NAME, + PythonServiceImpl.PYTHON_BIN_NAME + ) + ); + + PythonServiceImpl.pythonGenericBinPath = + PythonServiceImpl.pythonDir.withPath( + PythonServiceImpl.pythonDir.path.join( + PythonServiceImpl.EXEC_DIR_NAME, + PythonServiceImpl.PYTHON_GENERIC_BIN_NAME + ) + ); + } + } + + dispose(): void { + // Clean up resources if needed + } + + async setupEnvironment(): Promise { + const scribeDir = await this.getAppDir(); + const pythonDir = await this.downloadPython(scribeDir); + await this.createVirtualEnv(scribeDir, pythonDir); + } + + private async getAppDir(): Promise { + const exists = await this.fileService + .stat(PythonServiceImpl.scribeDir) + .catch((err) => { + if (err.code === FileSystemProviderErrorCode.FileNotFound) { + return false; + } + throw err; + }); + if (!exists) { + await this.fileService.mkdir(PythonServiceImpl.scribeDir); + } + return PythonServiceImpl.scribeDir; + } + + private async downloadPython(targetDir: URI): Promise { + // Check if Python directory exists + const pythonExists = await this.fileService + .readdir(PythonServiceImpl.pythonDir) + .catch(() => false); + + if (pythonExists) { + // Verify Python version by running python --version + try { + const versionProcess = spawn( + PythonServiceImpl.pythonBinPath.path.toString(), + ["--version"] + ); + + const versionPromise = new Promise((resolve, reject) => { + let output = ""; + + versionProcess.stdout.on("data", (data) => { + output += data.toString(); + }); + + versionProcess.on("close", (code) => { + if (code === 0) { + resolve(output.trim()); + } else { + reject( + new Error(`Python version check failed with code ${code}`) + ); + } + }); + + versionProcess.on("error", (err) => { + reject(err); + }); + }); + + const version = await versionPromise; + if (version.includes("Python 3.13")) { + console.log("Found existing Python 3.13 installation"); + return PythonServiceImpl.pythonDir; + } + } catch (err) { + console.log( + "Failed to verify Python version, will download fresh copy:", + err + ); + } + } + + // Existing code for downloading Python + console.log("Starting Python download..."); + const pythonDownloadUrl = this.getPythonDownloadUrl(); + + const fileName = pythonDownloadUrl.split("/").pop(); + if (!fileName) { + throw new Error("Failed to determine file name"); + } + + const downloadPath = targetDir.resolve(fileName); + + // Download and write file + const response = await axios({ + url: pythonDownloadUrl, + method: "GET", + responseType: "arraybuffer", + }); + + await this.fileService.writeFile(downloadPath, response.data, { + overwrite: true, + create: true, + }); + + // Extract the tar content + await tar.x({ + cwd: targetDir.path.toString(), + file: downloadPath.path.toString(), + gzip: true, + }); + + // List contents for debugging + const targetContents = await this.fileService.readdir(targetDir); + console.log("Contents of targetDir:", targetContents); + + const pythonContents = await this.fileService.readdir( + PythonServiceImpl.pythonDir + ); + console.log("Contents of pythonDir:", pythonContents); + + // delete the download file + await this.fileService.delete( + URI.fromFilePath(downloadPath.path.toString()), + { + recursive: true, + useTrash: false, + } + ); + console.log("Python setup completed successfully"); + + return PythonServiceImpl.pythonDir; + } + + private getPythonDownloadUrl(): string { + const architecture = machine(); + const currentPlatform = platform(); + console.log( + `Detected platform: ${currentPlatform}, architecture: ${architecture}` + ); + + const key = `${currentPlatform}-${ + architecture === "x86_64" ? "x64" : "arm64" + }` as keyof typeof PYTHON_DOWNLOADS; + const url = PYTHON_DOWNLOADS[key]; + + if (!url) { + throw new Error(`Unsupported platform/architecture combination: ${key}`); + } + + return url; + } + + private async createVirtualEnv( + scribeDir: URI, + pythonDir: URI + ): Promise { + // Check if venv already exists + const venvExists = await this.fileService + .stat(PythonServiceImpl.venvDir) + .catch(() => { + return false; + }); + + if (venvExists) { + console.log("Virtual environment already exists, updating Python paths"); + // Update Python paths to use venv binaries + PythonServiceImpl.pythonBinPath = PythonServiceImpl.venvDir.withPath( + PythonServiceImpl.venvDir.path.join( + PythonServiceImpl.EXEC_DIR_NAME, + PythonServiceImpl.PYTHON_BIN_NAME + ) + ); + + PythonServiceImpl.pythonGenericBinPath = + PythonServiceImpl.venvDir.withPath( + PythonServiceImpl.venvDir.path.join( + PythonServiceImpl.EXEC_DIR_NAME, + PythonServiceImpl.PYTHON_GENERIC_BIN_NAME + ) + ); + return; + } + + // Create venv directory and set up the environment + await this.fileService.mkdir(PythonServiceImpl.venvDir); + + const venvProcess = spawn( + PythonServiceImpl.pythonGenericBinPath.path.toString(), + ["-m", "venv", PythonServiceImpl.venvDir.path.toString()] + ); + + await new Promise((resolve, reject) => { + venvProcess.on("close", (code) => { + if (code !== 0) { + reject(new Error(`Failed to create virtual environment: ${code}`)); + } else { + // Update Python paths to use venv binaries after successful creation + PythonServiceImpl.pythonBinPath = PythonServiceImpl.venvDir.withPath( + PythonServiceImpl.venvDir.path.join( + PythonServiceImpl.EXEC_DIR_NAME, + PythonServiceImpl.PYTHON_BIN_NAME + ) + ); + + PythonServiceImpl.pythonGenericBinPath = + PythonServiceImpl.venvDir.withPath( + PythonServiceImpl.venvDir.path.join( + PythonServiceImpl.EXEC_DIR_NAME, + PythonServiceImpl.PYTHON_GENERIC_BIN_NAME + ) + ); + resolve(); + } + }); + + venvProcess.on("error", (err) => { + reject(new Error(`Failed to create virtual environment: ${err}`)); + }); + }); + } + + async setupWildebeest(): Promise { + let stdout = ""; + let stderr = ""; + + try { + const pipProcess = spawn( + PythonServiceImpl.pythonGenericBinPath.path.toString(), + ["-m", "pip", "install", "wildebeest-nlp"] + ); + + // Create a promise to handle the process events + await new Promise((resolve, reject) => { + pipProcess.stdout.on("data", (data) => { + stdout += data.toString(); + }); + + pipProcess.stderr.on("data", (data) => { + stderr += data.toString(); + }); + + pipProcess.on("close", (code) => { + if (code !== 0) { + reject( + new Error(`Failed to install wildebeest-nlp (${code}): ${stderr}`) + ); + } else { + resolve(); + } + }); + + pipProcess.on("error", (err) => { + reject(new Error(`Failed to install wildebeest-nlp: ${err}`)); + }); + }); + + console.log("OUTPUT OF THE SPAWN", stdout); + } catch (error) { + throw error; + } + } + + async executeWildebeest(text: string): Promise { + const pythonBinPath = PythonServiceImpl.venvDir.withPath( + PythonServiceImpl.venvDir.path.join(PythonServiceImpl.EXEC_DIR_NAME) + ); + + // Create temporary input and output files + const inputFile = PythonServiceImpl.venvDir.withPath( + PythonServiceImpl.venvDir.path.join("input.txt") + ); + const outputFile = PythonServiceImpl.venvDir.withPath( + PythonServiceImpl.venvDir.path.join("output.json") + ); + + try { + console.log("Writing input text to file:", inputFile.path.toString()); + // Write the input text to a file + await this.fileService.writeFile(inputFile, Buffer.from(text, "utf-8"), { + create: true, + overwrite: true, + }); + + console.log("Executing wb-ana command..."); + // Execute wb-ana with input and json output files + await new Promise((resolve, reject) => { + const wildebeestProcess = spawn( + "wb-ana", + [ + "-i", + inputFile.path.toString(), + "-j", + outputFile.path.toString(), + "--verbose", + ], + { + env: { ...process.env, PYTHONIOENCODING: "utf-8" }, + cwd: pythonBinPath.path.toString(), + } + ); + + wildebeestProcess.stdout.setEncoding("utf-8"); + wildebeestProcess.stderr.setEncoding("utf-8"); + + wildebeestProcess.stdout.on("data", (data) => { + console.log("wb-ana stdout:", data); + }); + + wildebeestProcess.stderr.on("data", (data) => { + console.log("wb-ana stderr:", data); + }); + + wildebeestProcess.on("close", (code) => { + if (code !== 0) { + reject(new Error(`Wildebeest analysis failed with code ${code}`)); + } else { + resolve(); + } + }); + + wildebeestProcess.on("error", (err) => { + reject(new Error(`Failed to execute Wildebeest: ${err}`)); + }); + }); + + console.log("Reading output file:", outputFile.path.toString()); + // Read the output file + const outputContent = await this.fileService.readFile(outputFile); + const result = outputContent.toString(); + console.log("Wildebeest analysis result:", result); + + // Clean up temporary files + await Promise.all([ + this.fileService.delete(inputFile, { + recursive: true, + useTrash: false, + }), + this.fileService.delete(outputFile, { + recursive: true, + useTrash: false, + }), + ]); + + return result; + } catch (error) { + console.error("Error in executeWildebeest:", error); + // Clean up files in case of error + try { + await Promise.all([ + this.fileService.delete(inputFile, { + recursive: true, + useTrash: false, + }), + this.fileService.delete(outputFile, { + recursive: true, + useTrash: false, + }), + ]); + } catch (cleanupError) { + console.error("Error cleaning up temporary files:", cleanupError); + } + throw error; + } + } +} + +const PYTHON_DOWNLOADS = { + "win32-x64": + "https://github.com/astral-sh/python-build-standalone/releases/download/20250212/cpython-3.13.2+20250212-x86_64-pc-windows-msvc-install_only.tar.gz", + "darwin-x64": + "https://github.com/astral-sh/python-build-standalone/releases/download/20250212/cpython-3.13.2+20250212-x86_64-apple-darwin-install_only.tar.gz", + "darwin-arm64": + "https://github.com/astral-sh/python-build-standalone/releases/download/20250212/cpython-3.13.2+20250212-aarch64-apple-darwin-install_only.tar.gz", + "linux-x64": + "https://github.com/astral-sh/python-build-standalone/releases/download/20250212/cpython-3.13.2+20250212-x86_64-unknown-linux-gnu-install_only.tar.gz", + "linux-arm64": + "https://github.com/astral-sh/python-build-standalone/releases/download/20250212/cpython-3.13.2+20250212-aarch64-unknown-linux-gnu-install_only.tar.gz", +} as const; diff --git a/packages/python/tailwind.config.js b/packages/python/tailwind.config.js new file mode 100644 index 00000000..f1e50268 --- /dev/null +++ b/packages/python/tailwind.config.js @@ -0,0 +1,469 @@ +export const darkMode = "class"; + +/** @type {import('tailwindcss').Config} */ +const config = { + content: ["src/**/*.{js,ts,jsx,tsx,mdx}"], + theme: { + extend: { + backgroundImage: { + "gradient-radial": "radial-gradient(var(--tw-gradient-stops))", + "gradient-conic": + "conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))", + }, + fontSize: { + custom: "8px", + }, + colors: { + transparent: "transparent", + current: "currentColor", + primary: "var(--theia-button-background)", + "primary-50": "var(--theia-selection-background)", + secondary: "var(--theia-editor-foreground)", + success: "var(--theia-successBackground)", + error: "var(--theia-errorBackground)", + validation: "var(--theia-inputValidation-errorBackground)", + light: "var(--theia-editor-background)", + dark: "var(--theia-editor-foreground)", + border: "var(--theia-editorWidget-border)", + input: "var(--theia-input-background)", + ring: "var(--theia-focusBorder)", + background: "var(--theia-editor-background)", + foreground: "var(--theia-editor-foreground)", + destructive: { + DEFAULT: "var(--theia-errorBackground)", + foreground: "var(--theia-statusBarItem-errorForeground)", + }, + muted: { + DEFAULT: "var(--theia-descriptionForeground)", + foreground: "var(--theia-disabledForeground)", + }, + accent: { + DEFAULT: "var(--theia-textLink-foreground)", + foreground: "var(--theia-textLink-activeForeground)", + }, + popover: { + DEFAULT: "var(--theia-editorWidget-background)", + foreground: "var(--theia-editorWidget-foreground)", + }, + card: { + DEFAULT: "hsl(var(--card))", + foreground: "hsl(var(--card-foreground))", + }, + table: { + header: "var(--theia-editorWidget-background)", + row: "var(--theia-list-hoverBackground)", + border: "var(--theia-list-inactiveSelectionBackground)", + }, + dropdown: { + background: "var(--theia-dropdown-background)", + border: "var(--theia-dropdown-border)", + text: "var(--theia-dropdown-foreground)", + }, + "secondary-foreground": "var(--theia-button-secondaryForeground)", + "destructive-foreground": "var(--theia-statusBarItem-errorForeground)", + "disabled-foreground": "var(--theia-disabledForeground)", + "error-foreground": "var(--theia-errorForeground)", + "description-foreground": "var(--theia-descriptionForeground)", + "icon-foreground": "var(--theia-icon-foreground)", + "focus-border": "var(--theia-focusBorder)", + "selection-background": "var(--theia-selection-background)", + "text-separator": "var(--theia-textSeparator-foreground)", + "text-link": { + DEFAULT: "var(--theia-textLink-foreground)", + active: "var(--theia-textLink-activeForeground)", + }, + "text-preformat": "var(--theia-textPreformat-foreground)", + "text-blockquote": { + background: "var(--theia-textBlockQuote-background)", + border: "var(--theia-textBlockQuote-border)", + }, + "text-codeblock": { + background: "var(--theia-textCodeBlock-background)", + }, + widget: { + shadow: "var(--theia-widget-shadow)", + }, + input: { + DEFAULT: "var(--theia-input-background)", + foreground: "var(--theia-input-foreground)", + placeholder: "var(--theia-input-placeholderForeground)", + option: { + active: { + border: "var(--theia-inputOption-activeBorder)", + background: "var(--theia-inputOption-activeBackground)", + foreground: "var(--theia-inputOption-activeForeground)", + }, + hover: { + background: "var(--theia-inputOption-hoverBackground)", + }, + }, + validation: { + info: { + background: "var(--theia-inputValidation-infoBackground)", + border: "var(--theia-inputValidation-infoBorder)", + }, + warning: { + background: "var(--theia-inputValidation-warningBackground)", + border: "var(--theia-inputValidation-warningBorder)", + }, + error: { + background: "var(--theia-inputValidation-errorBackground)", + border: "var(--theia-inputValidation-errorBorder)", + }, + }, + }, + button: { + DEFAULT: "var(--theia-button-background)", + foreground: "var(--theia-button-foreground)", + separator: "var(--theia-button-separator)", + hover: "var(--theia-button-hoverBackground)", + secondary: { + DEFAULT: "var(--theia-button-secondaryBackground)", + foreground: "var(--theia-button-secondaryForeground)", + hover: "var(--theia-button-secondaryHoverBackground)", + }, + }, + badge: { + DEFAULT: "var(--theia-badge-background)", + foreground: "var(--theia-badge-foreground)", + }, + scrollbar: { + shadow: "var(--theia-scrollbar-shadow)", + slider: { + DEFAULT: "var(--theia-scrollbarSlider-background)", + hover: "var(--theia-scrollbarSlider-hoverBackground)", + active: "var(--theia-scrollbarSlider-activeBackground)", + }, + }, + "progress-bar": "var(--theia-progressBar-background)", + editor: { + error: "var(--theia-editorError-foreground)", + warning: "var(--theia-editorWarning-foreground)", + info: "var(--theia-editorInfo-foreground)", + hint: "var(--theia-editorHint-foreground)", + }, + "editor-background": "var(--theia-editor-background)", + "editor-foreground": "var(--theia-editor-foreground)", + "editor-sticky-scroll": { + DEFAULT: "var(--theia-editorStickyScroll-background)", + hover: "var(--theia-editorStickyScrollHover-background)", + }, + "editor-widget": { + background: "var(--theia-editorWidget-background)", + foreground: "var(--theia-editorWidget-foreground)", + border: "var(--theia-editorWidget-border)", + }, + "quick-input": { + background: "var(--theia-quickInput-background)", + foreground: "var(--theia-quickInput-foreground)", + title: { + background: "var(--theia-quickInputTitle-background)", + }, + }, + "picker-group": { + foreground: "var(--theia-pickerGroup-foreground)", + border: "var(--theia-pickerGroup-border)", + }, + "keybinding-label": { + background: "var(--theia-keybindingLabel-background)", + foreground: "var(--theia-keybindingLabel-foreground)", + border: "var(--theia-keybindingLabel-border)", + "bottom-border": "var(--theia-keybindingLabel-bottomBorder)", + }, + "editor-selection": { + DEFAULT: "var(--theia-editor-selectionBackground)", + inactive: "var(--theia-editor-inactiveSelectionBackground)", + highlight: "var(--theia-editor-selectionHighlightBackground)", + }, + "editor-find": { + match: "var(--theia-editor-findMatchBackground)", + highlight: "var(--theia-editor-findMatchHighlightBackground)", + range: "var(--theia-editor-findRangeHighlightBackground)", + }, + "search-editor": { + match: "var(--theia-searchEditor-findMatchBackground)", + }, + "search-results-info": "var(--theia-search-resultsInfoForeground)", + "editor-hover": { + highlight: "var(--theia-editor-hoverHighlightBackground)", + widget: { + background: "var(--theia-editorHoverWidget-background)", + foreground: "var(--theia-editorHoverWidget-foreground)", + border: "var(--theia-editorHoverWidget-border)", + "status-bar": "var(--theia-editorHoverWidget-statusBarBackground)", + }, + }, + "editor-link": { + active: "var(--theia-editorLink-activeForeground)", + }, + "editor-inlay-hint": { + DEFAULT: { + foreground: "var(--theia-editorInlayHint-foreground)", + background: "var(--theia-editorInlayHint-background)", + }, + type: { + foreground: "var(--theia-editorInlayHint-typeForeground)", + background: "var(--theia-editorInlayHint-typeBackground)", + }, + parameter: { + foreground: "var(--theia-editorInlayHint-parameterForeground)", + background: "var(--theia-editorInlayHint-parameterBackground)", + }, + }, + "editor-lightbulb": { + DEFAULT: "var(--theia-editorLightBulb-foreground)", + autofix: "var(--theia-editorLightBulbAutoFix-foreground)", + }, + "diff-editor": { + "inserted-text": "var(--theia-diffEditor-insertedTextBackground)", + "removed-text": "var(--theia-diffEditor-removedTextBackground)", + "inserted-line": "var(--theia-diffEditor-insertedLineBackground)", + "removed-line": "var(--theia-diffEditor-removedLineBackground)", + "diagonal-fill": "var(--theia-diffEditor-diagonalFill)", + "unchanged-region": { + background: "var(--theia-diffEditor-unchangedRegionBackground)", + foreground: "var(--theia-diffEditor-unchangedRegionForeground)", + }, + "unchanged-code": "var(--theia-diffEditor-unchangedCodeBackground)", + }, + list: { + "focus-outline": "var(--theia-list-focusOutline)", + "active-selection": { + background: "var(--theia-list-activeSelectionBackground)", + foreground: "var(--theia-list-activeSelectionForeground)", + icon: "var(--theia-list-activeSelectionIconForeground)", + }, + "inactive-selection": "var(--theia-list-inactiveSelectionBackground)", + hover: "var(--theia-list-hoverBackground)", + drop: "var(--theia-list-dropBackground)", + highlight: "var(--theia-list-highlightForeground)", + "focus-highlight": "var(--theia-list-focusHighlightForeground)", + "invalid-item": "var(--theia-list-invalidItemForeground)", + error: "var(--theia-list-errorForeground)", + warning: "var(--theia-list-warningForeground)", + }, + "list-filter-widget": { + background: "var(--theia-listFilterWidget-background)", + outline: "var(--theia-listFilterWidget-outline)", + "no-matches": "var(--theia-listFilterWidget-noMatchesOutline)", + shadow: "var(--theia-listFilterWidget-shadow)", + "filter-match": "var(--theia-list-filterMatchBackground)", + }, + tree: { + "indent-guides": "var(--theia-tree-indentGuidesStroke)", + "inactive-indent-guides": + "var(--theia-tree-inactiveIndentGuidesStroke)", + "table-columns-border": "var(--theia-tree-tableColumnsBorder)", + "table-odd-rows": "var(--theia-tree-tableOddRowsBackground)", + }, + "list-deemphasized": "var(--theia-list-deemphasizedForeground)", + checkbox: { + DEFAULT: "var(--theia-checkbox-background)", + select: { + background: "var(--theia-checkbox-selectBackground)", + border: "var(--theia-checkbox-selectBorder)", + }, + foreground: "var(--theia-checkbox-foreground)", + border: "var(--theia-checkbox-border)", + }, + menu: { + border: "var(--theia-menu-border)", + foreground: "var(--theia-menu-foreground)", + background: "var(--theia-menu-background)", + "selection-foreground": "var(--theia-menu-selectionForeground)", + "selection-background": "var(--theia-menu-selectionBackground)", + "separator-background": "var(--theia-menu-separatorBackground)", + }, + toolbar: { + hover: "var(--theia-toolbar-hoverBackground)", + active: "var(--theia-toolbar-activeBackground)", + }, + "editor-snippet": { + "tabstop-highlight": + "var(--theia-editor-snippetTabstopHighlightBackground)", + "final-tabstop-border": + "var(--theia-editor-snippetFinalTabstopHighlightBorder)", + }, + breadcrumb: { + foreground: "var(--theia-breadcrumb-foreground)", + background: "var(--theia-breadcrumb-background)", + "focus-foreground": "var(--theia-breadcrumb-focusForeground)", + "active-selection": + "var(--theia-breadcrumb-activeSelectionForeground)", + picker: { + background: "var(--theia-breadcrumbPicker-background)", + }, + }, + merge: { + "current-header": "var(--theia-merge-currentHeaderBackground)", + "current-content": "var(--theia-merge-currentContentBackground)", + "incoming-header": "var(--theia-merge-incomingHeaderBackground)", + "incoming-content": "var(--theia-merge-incomingContentBackground)", + "common-header": "var(--theia-merge-commonHeaderBackground)", + "common-content": "var(--theia-merge-commonContentBackground)", + }, + "overview-ruler": { + "current-content": + "var(--theia-editorOverviewRuler-currentContentForeground)", + "incoming-content": + "var(--theia-editorOverviewRuler-incomingContentForeground)", + "common-content": + "var(--theia-editorOverviewRuler-commonContentForeground)", + "find-match": "var(--theia-editorOverviewRuler-findMatchForeground)", + "selection-highlight": + "var(--theia-editorOverviewRuler-selectionHighlightForeground)", + }, + minimap: { + "find-match": "var(--theia-minimap-findMatchHighlight)", + "selection-occurrence": + "var(--theia-minimap-selectionOccurrenceHighlight)", + selection: "var(--theia-minimap-selectionHighlight)", + info: "var(--theia-minimap-infoHighlight)", + warning: "var(--theia-minimap-warningHighlight)", + error: "var(--theia-minimap-errorHighlight)", + "foreground-opacity": "var(--theia-minimap-foregroundOpacity)", + slider: { + background: "var(--theia-minimapSlider-background)", + hover: "var(--theia-minimapSlider-hoverBackground)", + active: "var(--theia-minimapSlider-activeBackground)", + }, + }, + problems: { + error: "var(--theia-problemsErrorIcon-foreground)", + warning: "var(--theia-problemsWarningIcon-foreground)", + info: "var(--theia-problemsInfoIcon-foreground)", + }, + charts: { + foreground: "var(--theia-charts-foreground)", + lines: "var(--theia-charts-lines)", + red: "var(--theia-charts-red)", + blue: "var(--theia-charts-blue)", + yellow: "var(--theia-charts-yellow)", + orange: "var(--theia-charts-orange)", + green: "var(--theia-charts-green)", + purple: "var(--theia-charts-purple)", + }, + terminal: { + background: "var(--theia-terminal-background)", + foreground: "var(--theia-terminal-foreground)", + "selection-background": "var(--theia-terminal-selectionBackground)", + "inactive-selection": + "var(--theia-terminal-inactiveSelectionBackground)", + border: "var(--theia-terminal-border)", + ansi: { + black: "var(--theia-terminal-ansiBlack)", + red: "var(--theia-terminal-ansiRed)", + green: "var(--theia-terminal-ansiGreen)", + yellow: "var(--theia-terminal-ansiYellow)", + blue: "var(--theia-terminal-ansiBlue)", + magenta: "var(--theia-terminal-ansiMagenta)", + cyan: "var(--theia-terminal-ansiCyan)", + white: "var(--theia-terminal-ansiWhite)", + "bright-black": "var(--theia-terminal-ansiBrightBlack)", + "bright-red": "var(--theia-terminal-ansiBrightRed)", + "bright-green": "var(--theia-terminal-ansiBrightGreen)", + "bright-yellow": "var(--theia-terminal-ansiBrightYellow)", + "bright-blue": "var(--theia-terminal-ansiBrightBlue)", + "bright-magenta": "var(--theia-terminal-ansiBrightMagenta)", + "bright-cyan": "var(--theia-terminal-ansiBrightCyan)", + "bright-white": "var(--theia-terminal-ansiBrightWhite)", + }, + }, + debug: { + "stack-frame-highlight": + "var(--theia-editor-stackFrameHighlightBackground)", + "focused-stack-frame-highlight": + "var(--theia-editor-focusedStackFrameHighlightBackground)", + }, + "status-bar-debugging": { + background: "var(--theia-statusBar-debuggingBackground)", + foreground: "var(--theia-statusBar-debuggingForeground)", + }, + "debug-exception": { + border: "var(--theia-debugExceptionWidget-border)", + background: "var(--theia-debugExceptionWidget-background)", + }, + "debug-icon": { + breakpoint: "var(--theia-debugIcon-breakpointForeground)", + "breakpoint-disabled": + "var(--theia-debugIcon-breakpointDisabledForeground)", + "breakpoint-unverified": + "var(--theia-debugIcon-breakpointUnverifiedForeground)", + "breakpoint-current": + "var(--theia-debugIcon-breakpointCurrentStackframeForeground)", + "breakpoint-stack": + "var(--theia-debugIcon-breakpointStackframeForeground)", + start: "var(--theia-debugIcon-startForeground)", + pause: "var(--theia-debugIcon-pauseForeground)", + stop: "var(--theia-debugIcon-stopForeground)", + disconnect: "var(--theia-debugIcon-disconnectForeground)", + restart: "var(--theia-debugIcon-restartForeground)", + "step-over": "var(--theia-debugIcon-stepOverForeground)", + "step-into": "var(--theia-debugIcon-stepIntoForeground)", + "step-out": "var(--theia-debugIcon-stepOutForeground)", + continue: "var(--theia-debugIcon-continueForeground)", + "step-back": "var(--theia-debugIcon-stepBackForeground)", + }, + "debug-console": { + info: "var(--theia-debugConsole-infoForeground)", + warning: "var(--theia-debugConsole-warningForeground)", + error: "var(--theia-debugConsole-errorForeground)", + source: "var(--theia-debugConsole-sourceForeground)", + "input-icon": "var(--theia-debugConsoleInputIcon-foreground)", + }, + notebook: { + "cell-border": "var(--theia-notebook-cellBorderColor)", + "focused-editor": "var(--theia-notebook-focusedEditorBorder)", + "status-success": "var(--theia-notebookStatusSuccessIcon-foreground)", + "status-error": "var(--theia-notebookStatusErrorIcon-foreground)", + "status-running": "var(--theia-notebookStatusRunningIcon-foreground)", + "cell-toolbar-separator": + "var(--theia-notebook-cellToolbarSeparator)", + "selected-cell": { + background: "var(--theia-notebook-selectedCellBackground)", + border: "var(--theia-notebook-selectedCellBorder)", + }, + "focused-cell": { + border: "var(--theia-notebook-focusedCellBorder)", + "inactive-border": + "var(--theia-notebook-inactiveFocusedCellBorder)", + }, + "cell-statusbar-item": { + hover: "var(--theia-notebook-cellStatusBarItemHoverBackground)", + }, + "cell-insertion-indicator": + "var(--theia-notebook-cellInsertionIndicator)", + scrollbar: { + DEFAULT: "var(--theia-notebookScrollbarSlider-background)", + hover: "var(--theia-notebookScrollbarSlider-hoverBackground)", + active: "var(--theia-notebookScrollbarSlider-activeBackground)", + }, + "symbol-highlight": "var(--theia-notebook-symbolHighlightBackground)", + "cell-editor": { + background: "var(--theia-notebook-cellEditorBackground)", + }, + }, + "git-decoration": { + added: "var(--theia-gitDecoration-addedResourceForeground)", + modified: "var(--theia-gitDecoration-modifiedResourceForeground)", + deleted: "var(--theia-gitDecoration-deletedResourceForeground)", + untracked: "var(--theia-gitDecoration-untrackedResourceForeground)", + conflicting: + "var(--theia-gitDecoration-conflictingResourceForeground)", + }, + gitlens: { + "gutter-background": "var(--theia-gitlens-gutterBackgroundColor)", + "gutter-foreground": "var(--theia-gitlens-gutterForegroundColor)", + "line-highlight": "var(--theia-gitlens-lineHighlightBackgroundColor)", + }, + }, + borderRadius: { + lg: `var(--radius)`, + md: `calc(var(--radius) - 2px)`, + sm: "calc(var(--radius) - 4px)", + }, + }, + }, + plugins: [require("tailwindcss-animate")], +}; +export default config; diff --git a/packages/python/tsconfig.json b/packages/python/tsconfig.json new file mode 100644 index 00000000..dd2488ce --- /dev/null +++ b/packages/python/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../../configs/base.tsconfig", + "compilerOptions": { + "rootDir": "src", + "outDir": "lib", + "baseUrl": ".", + "esModuleInterop": true + }, + "include": ["src", "svg.d.ts"] +} diff --git a/yarn.lock b/yarn.lock index bb70f963..ee876f53 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1200,6 +1200,13 @@ wrap-ansi "^8.1.0" wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" +"@isaacs/fs-minipass@^4.0.0": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz#2d59ae3ab4b38fb4270bfa23d30f8e2e86c7fe32" + integrity sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w== + dependencies: + minipass "^7.0.4" + "@istanbuljs/load-nyc-config@^1.0.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" @@ -5060,11 +5067,32 @@ atomically@^1.7.0: resolved "https://registry.yarnpkg.com/atomically/-/atomically-1.7.0.tgz#c07a0458432ea6dbc9a3506fffa424b48bccaafe" integrity sha512-Xcz9l0z7y9yQ9rdDaxlmaI4uJHf/T8g9hOEzJcsEqX2SjCj4J20uK7+ldkDHMbpJDK76wF7xEIgxc/vSlsfw5w== +autoprefixer@^10.4.17: + version "10.4.20" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.20.tgz#5caec14d43976ef42e32dcb4bd62878e96be5b3b" + integrity sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g== + dependencies: + browserslist "^4.23.3" + caniuse-lite "^1.0.30001646" + fraction.js "^4.3.7" + normalize-range "^0.1.2" + picocolors "^1.0.1" + postcss-value-parser "^4.2.0" + autosize@^4.0.2: version "4.0.4" resolved "https://registry.yarnpkg.com/autosize/-/autosize-4.0.4.tgz#924f13853a466b633b9309330833936d8bccce03" integrity sha512-5yxLQ22O0fCRGoxGfeLSNt3J8LB1v+umtpMnPW6XjkTWXKoN0AmXAIhelJcDtFT/Y/wYWmfE+oqU10Q0b8FhaQ== +axios@^1.6.2: + version "1.8.1" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.8.1.tgz#7c118d2146e9ebac512b7d1128771cdd738d11e3" + integrity sha512-NN+fvwH/kV01dYUQ3PTOZns4LWtWhOFCAhQ/pHb88WQ1hNe5V/dvFwc4VJcDL11LT9xSX0QtsR8sWUuyOuOq7g== + dependencies: + follow-redirects "^1.15.6" + form-data "^4.0.0" + proxy-from-env "^1.1.0" + axios@^1.7.4: version "1.7.9" resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.9.tgz#d7d071380c132a24accda1b2cfc1535b79ec650a" @@ -5389,7 +5417,7 @@ browserfs@^1.4.3: async "^2.1.4" pako "^1.0.4" -browserslist@^4.24.0, browserslist@^4.24.3: +browserslist@^4.23.3, browserslist@^4.24.3: version "4.24.4" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.24.4.tgz#c6b2865a3f08bcb860a0e827389003b9fe686e4b" integrity sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A== @@ -5399,6 +5427,16 @@ browserslist@^4.24.0, browserslist@^4.24.3: node-releases "^2.0.19" update-browserslist-db "^1.1.1" +browserslist@^4.24.0: + version "4.24.2" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.24.2.tgz#f5845bc91069dbd55ee89faf9822e1d885d16580" + integrity sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg== + dependencies: + caniuse-lite "^1.0.30001669" + electron-to-chromium "^1.5.41" + node-releases "^2.0.18" + update-browserslist-db "^1.1.1" + bs-logger@0.x: version "0.2.6" resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8" @@ -5690,11 +5728,16 @@ camelcase@^6.0.0, camelcase@^6.2.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== -caniuse-lite@^1.0.30001688: +caniuse-lite@^1.0.30001646, caniuse-lite@^1.0.30001688: version "1.0.30001700" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001700.tgz#26cd429cf09b4fd4e745daf4916039c794d720f6" integrity sha512-2S6XIXwaE7K7erT8dY+kLQcpa5ms63XlRkMkReXjle+kf6c5g38vyMl+Z5y8dSxOFDhcFe+nxnn261PLxBSQsQ== +caniuse-lite@^1.0.30001669: + version "1.0.30001679" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001679.tgz#18c573b72f72ba70822194f6c39e7888597f9e32" + integrity sha512-j2YqID/YwpLnKzCmBOS4tlZdWprXm3ZmQLBH9ZBXFOhoxLA46fwyBvx6toCBWBmnuwUY/qB3kEU6gFx8qgCroA== + capture-exit@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-2.0.0.tgz#fb953bfaebeb781f62898239dabb426d08a509a4" @@ -5840,6 +5883,11 @@ chownr@^2.0.0: resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== +chownr@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-3.0.0.tgz#9855e64ecd240a9cc4267ce8a4aa5d24a1da15e4" + integrity sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g== + chrome-launcher@^0.13.1: version "0.13.4" resolved "https://registry.yarnpkg.com/chrome-launcher/-/chrome-launcher-0.13.4.tgz#4c7d81333c98282899c4e38256da23e00ed32f73" @@ -7436,10 +7484,15 @@ electron-store@^8.0.0: conf "^10.2.0" type-fest "^2.17.0" +electron-to-chromium@^1.5.41: + version "1.5.107" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.107.tgz#0a12a0b50e6f925cde8bf9c16c13d514c54c694b" + integrity sha512-dJr1o6yCntRkXElnhsHh1bAV19bo/hKyFf7tCcWgpXbuFIF0Lakjgqv5LRfSDaNzAII8Fnxg2tqgHkgCvxdbxw== + electron-to-chromium@^1.5.73: - version "1.5.102" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.102.tgz#81a452ace8e2c3fa7fba904ea4fed25052c53d3f" - integrity sha512-eHhqaja8tE/FNpIiBrvBjFV/SSKpyWHLvxuR9dPTdo+3V9ppdLmFB7ZZQ98qNovcngPLYIz0oOBF9P0FfZef5Q== + version "1.5.103" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.103.tgz#3d02025bc16e96e5edb3ed3ffa2538a11ae682dc" + integrity sha512-P6+XzIkfndgsrjROJWfSvVEgNHtPgbhVyTkwLjUM2HU/h7pZRORgaTlHqfAikqxKmdJMLW8fftrdGWbd/Ds0FA== electron-window@^0.8.0: version "0.8.1" @@ -8276,6 +8329,11 @@ forwarded@0.2.0: resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== +fraction.js@^4.3.7: + version "4.3.7" + resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.3.7.tgz#06ca0085157e42fda7f9e726e79fefc4068840f7" + integrity sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew== + fragment-cache@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" @@ -8307,6 +8365,15 @@ fs-extra@^10.0.0, fs-extra@^10.1.0: jsonfile "^6.0.1" universalify "^2.0.0" +fs-extra@^11.2.0: + version "11.3.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.3.0.tgz#0daced136bbaf65a555a326719af931adc7a314d" + integrity sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + fs-extra@^4.0.1, fs-extra@^4.0.2: version "4.0.3" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94" @@ -8613,7 +8680,7 @@ glob@8.1.0, glob@^8.0.1, glob@^8.0.3, glob@^8.1.0: minimatch "^5.0.1" once "^1.3.0" -glob@^10.3.10: +glob@^10.3.10, glob@^10.3.7: version "10.4.5" resolved "https://registry.yarnpkg.com/glob/-/glob-10.4.5.tgz#f4d9f0b90ffdbab09c9d77f5f29b4262517b0956" integrity sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg== @@ -10943,7 +11010,15 @@ micromatch@^3.1.4: snapdragon "^0.8.1" to-regex "^3.0.2" -micromatch@^4.0.2, micromatch@^4.0.8: +micromatch@^4.0.2: + version "4.0.7" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.7.tgz#33e8190d9fe474a9895525f5618eee136d46c2e5" + integrity sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q== + dependencies: + braces "^3.0.3" + picomatch "^2.3.1" + +micromatch@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== @@ -11129,7 +11204,7 @@ minipass@^5.0.0: resolved "https://registry.yarnpkg.com/minipass/-/minipass-5.0.0.tgz#3e9788ffb90b694a5d0ec94479a45b5d8738133d" integrity sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ== -"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.1.2: +"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.0.4, minipass@^7.1.2: version "7.1.2" resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.2.tgz#93a9626ce5e5e66bd4db86849e7515e92340a707" integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== @@ -11142,6 +11217,14 @@ minizlib@^2.1.1, minizlib@^2.1.2: minipass "^3.0.0" yallist "^4.0.0" +minizlib@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-3.0.1.tgz#46d5329d1eb3c83924eff1d3b858ca0a31581012" + integrity sha512-umcy022ILvb5/3Djuu8LWeqUa8D68JaBzlttKeMWen48SjabqS3iY5w/vzeMzMUNhLDifyhbOwKDSznB1vvrwg== + dependencies: + minipass "^7.0.4" + rimraf "^5.0.5" + mitt@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/mitt/-/mitt-3.0.0.tgz#69ef9bd5c80ff6f57473e8d89326d01c414be0bd" @@ -11172,6 +11255,11 @@ mkdirp@1.x, mkdirp@^1.0.3, mkdirp@^1.0.4: dependencies: minimist "^1.2.6" +mkdirp@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-3.0.1.tgz#e44e4c5607fb279c168241713cc6e0fea9adcb50" + integrity sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg== + mocha@=10.4.0: version "10.4.0" resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.4.0.tgz#ed03db96ee9cfc6d20c56f8e2af07b961dbae261" @@ -11368,7 +11456,7 @@ nanoid@3.1.20: resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.20.tgz#badc263c6b1dcf14b71efaa85f6ab4c1d6cfc788" integrity sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw== -nanoid@^3.3.8: +nanoid@^3.3.7, nanoid@^3.3.8: version "3.3.8" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.8.tgz#b1be3030bee36aaff18bacb375e5cce521684baf" integrity sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w== @@ -11553,7 +11641,7 @@ node-pty@0.11.0-beta24: dependencies: nan "^2.17.0" -node-releases@^2.0.19: +node-releases@^2.0.18, node-releases@^2.0.19: version "2.0.19" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.19.tgz#9e445a52950951ec4d177d843af370b411caf314" integrity sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw== @@ -11620,6 +11708,11 @@ normalize-path@^3.0.0, normalize-path@~3.0.0: resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== +normalize-range@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" + integrity sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA== + normalize-url@^6.0.1: version "6.1.0" resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a" @@ -12149,7 +12242,7 @@ perfect-scrollbar@^1.3.0, perfect-scrollbar@^1.5.0: resolved "https://registry.yarnpkg.com/perfect-scrollbar/-/perfect-scrollbar-1.5.6.tgz#f1aead2588ba896435ee41b246812b2080573b7c" integrity sha512-rixgxw3SxyJbCaSpo1n35A/fwI1r2rdwMKOTCg/AcG+xOEyZcE8UHVjpZMFCVImzsFoCZeJTT+M/rdEIQYO2nw== -picocolors@^1.0.0, picocolors@^1.1.1: +picocolors@^1.0.0, picocolors@^1.0.1, picocolors@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== @@ -12316,7 +12409,16 @@ postcss-value-parser@^4.0.0, postcss-value-parser@^4.1.0, postcss-value-parser@^ resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== -postcss@^8.4.33, postcss@^8.4.47: +postcss@^8.4.33: + version "8.4.40" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.40.tgz#eb81f2a4dd7668ed869a6db25999e02e9ad909d8" + integrity sha512-YF2kKIUzAofPMpfH6hOi2cGnv/HrUlfucspc7pDyvv7kGdqXrfj8SCl/t8owkEgKEuu8ZcRjSOxFxVLqwChZ2Q== + dependencies: + nanoid "^3.3.7" + picocolors "^1.0.1" + source-map-js "^1.2.0" + +postcss@^8.4.35, postcss@^8.4.47: version "8.5.3" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.3.tgz#1463b6f1c7fb16fe258736cba29a2de35237eafb" integrity sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A== @@ -13166,6 +13268,13 @@ rimraf@3.0.2, rimraf@^3.0.0, rimraf@^3.0.2: dependencies: glob "^7.1.3" +rimraf@^5.0.5: + version "5.0.10" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-5.0.10.tgz#23b9843d3dc92db71f96e1a2ce92e39fd2a8221c" + integrity sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ== + dependencies: + glob "^10.3.7" + rimraf@^6.0.1, rimraf@latest: version "6.0.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-6.0.1.tgz#ffb8ad8844dd60332ab15f52bc104bc3ed71ea4e" @@ -13778,7 +13887,7 @@ source-map-js@^0.6.2: resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-0.6.2.tgz#0bb5de631b41cfbda6cfba8bd05a80efdfd2385e" integrity sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug== -source-map-js@^1.0.1, source-map-js@^1.2.1: +source-map-js@^1.0.1, source-map-js@^1.2.0, source-map-js@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46" integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA== @@ -14271,7 +14380,7 @@ tailwindcss-animate@^1.0.7: resolved "https://registry.yarnpkg.com/tailwindcss-animate/-/tailwindcss-animate-1.0.7.tgz#318b692c4c42676cc9e67b19b78775742388bef4" integrity sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA== -tailwindcss@^3.4.14, tailwindcss@^3.4.4: +tailwindcss@^3.4.1, tailwindcss@^3.4.4: version "3.4.17" resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.4.17.tgz#ae8406c0f96696a631c790768ff319d46d5e5a63" integrity sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og== @@ -14299,6 +14408,34 @@ tailwindcss@^3.4.14, tailwindcss@^3.4.4: resolve "^1.22.8" sucrase "^3.35.0" +tailwindcss@^3.4.14: + version "3.4.14" + resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.4.14.tgz#6dd23a7f54ec197b19159e91e3bb1e55e7aa73ac" + integrity sha512-IcSvOcTRcUtQQ7ILQL5quRDg7Xs93PdJEk1ZLbhhvJc7uj/OAhYOnruEiwnGgBvUtaUAJ8/mhSw1o8L2jCiENA== + dependencies: + "@alloc/quick-lru" "^5.2.0" + arg "^5.0.2" + chokidar "^3.5.3" + didyoumean "^1.2.2" + dlv "^1.1.3" + fast-glob "^3.3.0" + glob-parent "^6.0.2" + is-glob "^4.0.3" + jiti "^1.21.0" + lilconfig "^2.1.0" + micromatch "^4.0.5" + normalize-path "^3.0.0" + object-hash "^3.0.0" + picocolors "^1.0.0" + postcss "^8.4.23" + postcss-import "^15.1.0" + postcss-js "^4.0.1" + postcss-load-config "^4.0.1" + postcss-nested "^6.0.1" + postcss-selector-parser "^6.0.11" + resolve "^1.22.2" + sucrase "^3.32.0" + tapable@^2.1.1, tapable@^2.2.0, tapable@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" @@ -14380,6 +14517,18 @@ tar@^6.0.5, tar@^6.1.11, tar@^6.1.12, tar@^6.1.2: mkdirp "^1.0.3" yallist "^4.0.0" +tar@^7.4.3: + version "7.4.3" + resolved "https://registry.yarnpkg.com/tar/-/tar-7.4.3.tgz#88bbe9286a3fcd900e94592cda7a22b192e80571" + integrity sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw== + dependencies: + "@isaacs/fs-minipass" "^4.0.0" + chownr "^3.0.0" + minipass "^7.1.2" + minizlib "^3.0.1" + mkdirp "^3.0.1" + yallist "^5.0.0" + tdigest@^0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/tdigest/-/tdigest-0.1.2.tgz#96c64bac4ff10746b910b0e23b515794e12faced" @@ -15704,10 +15853,20 @@ yallist@^4.0.0: resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== -yaml@^2.2.2, yaml@^2.3.4: - version "2.7.0" - resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.7.0.tgz#aef9bb617a64c937a9a748803786ad8d3ffe1e98" - integrity sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA== +yallist@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-5.0.0.tgz#00e2de443639ed0d78fd87de0d27469fbcffb533" + integrity sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw== + +yaml@^2.2.2: + version "2.5.0" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.5.0.tgz#c6165a721cf8000e91c36490a41d7be25176cf5d" + integrity sha512-2wWLbGbYDiSqqIKoPjar3MPgB94ErzCtrNE1FdqGuaO0pi2JGjmE8aW8TDZwzU7vuxcGRdL/4gPQwQ7hD5AMSw== + +yaml@^2.3.4: + version "2.5.1" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.5.1.tgz#c9772aacf62cb7494a95b0c4f1fb065b563db130" + integrity sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q== yargs-parser@20.2.4: version "20.2.4" From c25cd8e4084c3bdfea76e4ae631a7b0779347733 Mon Sep 17 00:00:00 2001 From: Brian Ineza Date: Thu, 27 Feb 2025 09:34:14 +0100 Subject: [PATCH 2/5] ch: widget editable for checks --- .../src/browser/widgets/checks-widget.tsx | 62 +- yarn.lock | 623 ++++++++---------- 2 files changed, 331 insertions(+), 354 deletions(-) diff --git a/packages/python/src/browser/widgets/checks-widget.tsx b/packages/python/src/browser/widgets/checks-widget.tsx index 82117ec8..9251afa3 100644 --- a/packages/python/src/browser/widgets/checks-widget.tsx +++ b/packages/python/src/browser/widgets/checks-widget.tsx @@ -39,10 +39,10 @@ export class ChecksWidget extends ReactWidget { this.title.iconClass = codicon("checklist"); this.update(); - this.getAnalysisData().then((data) => { - this.analysisData = data; - this.update(); - }); + // this.getAnalysisData().then((data) => { + // this.analysisData = data; + // this.update(); + // }); } protected async getAnalysisData(): Promise { @@ -61,6 +61,14 @@ export class ChecksWidget extends ReactWidget { render(): React.ReactNode { return (
+ { + this.pythonService.executeWildebeest(text).then((data) => { + this.analysisData = JSON.parse(data); + this.update(); + }); + }} + /> {this.analysisData && }
); @@ -97,3 +105,49 @@ export class ChecksWidgetContribution }); } } + +interface CheckInputFormProps { + onSubmit?: (text: string) => void; + placeholder?: string; + className?: string; +} + +const CheckInputForm: React.FC = ({ + onSubmit, + placeholder = "Enter text to analyze...", + className, +}) => { + const [inputText, setInputText] = React.useState(""); + + const handleSubmit = (e: React.FormEvent) => { + e.preventDefault(); + if (inputText.trim() && onSubmit) { + onSubmit(inputText); + } + }; + + return ( +
+ +