57 Commits

Author SHA1 Message Date
Ezekiel Wotring
f3b7d2048e Clarify build steps 2023-07-29 19:28:47 -08:00
Ezekiel Wotring
4469313106 TODO 2023-07-28 14:31:49 -08:00
kaj
d842066f51 inline comfy output display 2023-07-24 19:41:16 -08:00
kaj
e9657bb20f workflows 2023-07-24 17:01:14 -08:00
kaj
0a92760725 make sidebars layout effects 2023-07-23 14:15:04 -08:00
kaj
753eb570b7 generation ETA 2023-07-23 14:12:31 -08:00
kaj
44aac3087d Update Cargo.toml 2023-07-23 13:40:14 -08:00
kaj
3317206d3e fix linux builds 2023-07-23 13:35:37 -08:00
kaj
0065f05d3b progress, handle cached nodes 2023-07-23 13:29:07 -08:00
kaj
d44d5d1d8f remove unused crate 2023-07-22 12:59:17 -08:00
kaj
b867894c19 settings system & movable comfy path 2023-07-22 12:57:43 -08:00
kaj
f7fdd8202d Update comfy_windows.yml 2023-07-22 03:45:56 -08:00
kaj
12a086302c fix link 2023-07-22 03:40:29 -08:00
kaj
47b4fa31e0 switch to fork of comfyui 2023-07-22 03:34:10 -08:00
kaj
61d872b37f fix inputs (assume forked comfyui) 2023-07-22 02:26:07 -08:00
kaj
5ed8642175 dont remove git files 2023-07-22 01:50:01 -08:00
kaj
8bb42328d6 fix stylesheets 2023-07-21 17:16:23 -08:00
kaj
110c8dcf08 convert to single custom node & bug fixes 2023-07-21 16:49:10 -08:00
kaj
69d381aef6 versions in settings & bug fixes 2023-07-21 10:40:36 -08:00
kaj
d710f32f70 working inference by default 2023-07-20 16:42:40 -08:00
kaj
ecaf1a9ae3 Update README.md 2023-07-20 14:03:08 -08:00
kaj
2dadc6f5ec banner 2023-07-20 13:55:42 -08:00
kaj
fbf24d80b4 readme changes and history passthrough 2023-07-20 13:54:00 -08:00
kaj
c359a44be6 correct running checks 2023-07-20 11:44:11 -08:00
kaj
e7089b8a7b generation requests return images 2023-07-20 11:39:21 -08:00
kaj
4d435a4d6d better stdout, model and sampler options 2023-07-19 18:03:59 -08:00
kaj
f4a9d4e4af capture comfyui stdout/stderr 2023-07-19 16:08:34 -08:00
kaj
bef5fe60f3 handle more cases 2023-07-19 14:15:53 -08:00
kaj
4881e96a22 disable draft 2023-07-19 13:04:14 -08:00
kaj
2b9e34dcda Update build.yml 2023-07-19 12:44:40 -08:00
kaj
1dc1fad664 tauri build 2023-07-19 12:40:06 -08:00
kaj
896e91818f fix fetching comfyui assets in builds 2023-07-18 16:41:36 -08:00
kaj
8d363baa58 temp download link 2023-07-14 22:46:28 -08:00
kaj
54d703c38e Update comfy_windows.yml 2023-07-14 22:10:28 -08:00
kaj
f8adbd1e60 Update comfy_windows.yml 2023-07-14 22:09:43 -08:00
kaj
e111ca023c test s3 2023-07-14 20:57:52 -08:00
kaj
7174ae2ab3 Update comfy_windows.yml 2023-07-14 16:45:53 -08:00
kaj
e35446e9ef PoC comfyui plugin backend 2023-07-14 14:13:46 -08:00
kaj
1fd566802d dont launch browser 2023-07-13 18:59:07 -08:00
kaj
508173cbb3 launch comfy with tab in UI 2023-07-13 18:51:55 -08:00
kaj
5646d76c3e Update comfy_windows.yml 2023-07-13 16:33:22 -08:00
kaj
f07733c227 compress better 2023-07-13 16:31:32 -08:00
kaj
6fcdee3da0 Update comfy_windows.yml 2023-07-13 16:23:15 -08:00
kaj
fad621417d needs ref 2023-07-13 15:33:45 -08:00
kaj
3800549123 check file size 2023-07-13 15:25:06 -08:00
kaj
d10af830f0 try this (github tags & releases are confusing) 2023-07-13 15:23:05 -08:00
kaj
8c704abcb6 Update comfy_windows.yml 2023-07-13 15:10:36 -08:00
kaj
0785bc4751 Update comfy_windows.yml 2023-07-13 14:56:27 -08:00
kaj
75c7b7e51e Update comfy_windows.yml 2023-07-13 14:45:19 -08:00
kaj
14dc64e8b1 Update comfy_windows.yml 2023-07-13 14:38:14 -08:00
kaj
bfd60288d3 Update comfy_windows.yml 2023-07-13 14:37:28 -08:00
kaj
39da8e3bb5 Create comfy_windows.yml 2023-07-13 14:33:10 -08:00
kaj
58075b422e spike out setup flow logic 2023-07-12 14:36:01 -08:00
kaj
e0f787c4d7 attempt to package comfyui 2023-07-12 10:56:31 -08:00
kaj
158ccf298b integrate tauri
`yarn dev` will launch tauri, `yarn dev:vite` will launch vite.
2023-07-10 10:28:44 -08:00
Ezekiel Wotring
76772d7b9a Merge pull request #76 from jtydhr88/webui-plugin-bug-fix
webui plugin bug fix - check empty str
2023-05-31 18:30:05 -08:00
jtydhr88
4ae2e1766e webui plugin: check empty str 2023-05-31 13:55:51 -04:00
143 changed files with 8903 additions and 16425 deletions

47
.github/workflows/build.yml vendored Normal file
View File

@@ -0,0 +1,47 @@
name: "Build Tauri App"
on:
workflow_dispatch:
push:
branches:
- tauri
concurrency:
group: tauri-build
cancel-in-progress: true
jobs:
build:
strategy:
fail-fast: false
matrix:
platform: [macos-latest, ubuntu-20.04, windows-latest]
permissions:
contents: "write"
packages: "write"
pull-requests: "read"
runs-on: ${{ matrix.platform }}
steps:
- uses: actions/checkout@v2
- name: Setup Node.js
uses: actions/setup-node@v2
with:
node-version: 16
- name: install Rust stable
uses: dtolnay/rust-toolchain@stable
- name: install dependencies (ubuntu only)
if: matrix.platform == 'ubuntu-20.04'
run: |
sudo apt-get update
sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libappindicator3-dev librsvg2-dev patchelf
- name: install frontend dependencies
run: yarn install
- uses: tauri-apps/tauri-action@v0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tagName: stablestudio-v__VERSION__
releaseName: "StableStudio v__VERSION__"
releaseBody: "See the assets to download this version and install."
releaseDraft: false
prerelease: true

53
.github/workflows/comfy_windows.yml vendored Normal file
View File

@@ -0,0 +1,53 @@
name: "Windows Release Repackaging with ZIP"
on:
workflow_dispatch:
push:
branches:
- tauri
concurrency:
group: comfyui_windows
jobs:
repackage_comfyui:
permissions:
contents: "write"
packages: "write"
pull-requests: "read"
runs-on: ubuntu-latest
steps:
- shell: bash
run: |
sudo apt-get update
sudo apt-get install -y p7zip-full
sudo apt-get install -y zip
wget -nv https://github.com/KAJdev/ComfyUI/releases/download/latest/new_ComfyUI_windows_portable_nvidia_cu118_or_cpu.7z -O ComfyUI_windows_portable_nvidia_cu118_or_cpu.7z
7z x ComfyUI_windows_portable_nvidia_cu118_or_cpu.7z
rm ComfyUI_windows_portable_nvidia_cu118_or_cpu.7z
mv ComfyUI_windows_portable ComfyUI
# remove ALL cache files recursively (.pyc, .pyo, __pycache__, etc.)
find ComfyUI -type f -name '*.pyc' -delete
find ComfyUI -type f -name '*.pyo' -delete
find ComfyUI -type d -name '__pycache__' -delete
zip -r -9 -q ComfyUI_windows_portable.zip ComfyUI -x "*.DS_Store" -x "__MACOSX" -x "*.pyc" -x "*.pyo" -x "__pycache__"
du -sh ComfyUI_windows_portable.zip
mkdir ComfyUI_bundle
mv ComfyUI_windows_portable.zip ComfyUI_bundle/ComfyUI_windows_portable.zip
- name: Upload binaries to S3
uses: shallwefootball/s3-upload-action@master
with:
aws_key_id: ${{ secrets.AWS_KEY_ID }}
aws_secret_access_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws_bucket: ${{ secrets.AWS_BUCKET }}
source_dir: ComfyUI_bundle
destination_dir: ComfyUI
endpoint: https://4f71c105ddc191f1fdc56ad4be97f44f.r2.cloudflarestorage.com/stability-downloads

2
.gitignore vendored
View File

@@ -11,3 +11,5 @@ node_modules
!.yarn/releases
!.yarn/sdks
!.yarn/versions
**/src-tauri/comfyui/*

View File

@@ -1,4 +1,7 @@
{
"typescript.tsdk": "node_modules/typescript/lib",
"typescript.enablePromptUseWorkspaceTsdk": true
"typescript.enablePromptUseWorkspaceTsdk": true,
"rust-analyzer.linkedProjects": [
".\\packages\\stablestudio-ui\\src-tauri\\Cargo.toml"
]
}

807
.yarn/releases/yarn-3.3.0.cjs vendored Executable file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -4,4 +4,4 @@ plugins:
- path: .yarn/plugins/@yarnpkg/plugin-workspace-tools.cjs
spec: "@yarnpkg/plugin-workspace-tools"
yarnPath: .yarn/releases/yarn-3.5.1.cjs
yarnPath: .yarn/releases/yarn-3.3.0.cjs

105
README.md
View File

@@ -1,57 +1,32 @@
<div align="center" style="display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: 1em; margin: 4em 0;">
<img src="./misc/Banner.png" />
<img src="./misc/GenerateScreenshot.png" style="width: 400px; max-width: 600px; flex-grow: 1;" />
<img src="./misc/EditScreenshot.png" style="width: 400px; max-width: 600px; flex-grow: 1;" />
<h3>👋 Welcome to StableStudio, the open-source version of <a href="https://dreamstudio.ai" target="_blank">DreamStudio</a>!</h3>
**🗺 Contents [🚀 Quick Start](#quick-start) · [ About](#about) · [🙋 FAQ](#faq) · [🧑‍💻 Contributing](#contributing)**
**📚 Documentation [🎨 UI](./packages/stablestudio-ui/README.md) · [🔌 Plugins](./packages/stablestudio-plugin/README.md) · <a href="https://platform.stability.ai" target="_blank">⚡️ platform.stability.ai</a>**
**📚 Documentation [🎨 UI](./packages/stablestudio-ui/README.md) · <a href="https://platform.stability.ai" target="_blank">⚡️ platform.stability.ai</a>**
**🔗 Links <a href="https://discord.com/channels/1002292111942635562/1108055793674227782" target="_blank">🎮 Discord</a> · <a href="https://dreamstudio.ai" target="_blank">🌈 DreamStudio</a> · <a href="https://github.com/Stability-AI/StableStudio/issues">🛟 Bugs & Support</a> · <a href="https://github.com/Stability-AI/StableStudio/discussions">💬 Discussion</a>**
<br />
<br />
</div>
# <a id="quick-start" href="#quick-start">🚀 Quick Start</a>
# 🚀 Installation
You'll need to have [Node.js](https://nodejs.org/en/) and [Yarn](https://yarnpkg.com/) installed. Then run the following commands to install dependencies and launch StableStudio.
```bash
git clone https://github.com/Stability-AI/StableStudio.git
```
```bash
cd StableStudio
```
```bash
yarn
```
```bash
yarn dev
```
You'll need to head over to the [Releases](https://github.com/Stability-AI/StableStudio/releases) page to download StableStudio for your operating system. StableStudio will download and install its own managed copy of [ComfyUI](https://github.com/comfyanonymous/ComfyUI) and the Stable Diffusion weights.
_**That's it! 🎉**_
StableStudio will be running at [localhost:3000](http://localhost:3000) by default.
> If you are using the default Stability API plugin, You'll need to have your [API key](https://platform.stability.ai/docs/getting-started/authentication) handy. Otherwise, you should be good to go!
# <a id="about" href="#about">About</a>
# About
<div style="display: flex; justify-content: center; align-items: center; gap: 1em; margin: 0 0 2em 0;">
<img src="./misc/PainterWithRobot.png" style="flex-grow: 1; flex-shrink: 1;" />
<img src="./misc/aboutReadmeImage.png" style="flex-grow: 1; flex-shrink: 1;" />
</div>
StableStudio is [Stability AI](https://stability.ai)'s official open-source variant of [DreamStudio](https://www.dreamstudio.ai), our user interface for generative AI. It is a web-based application that allows users to create and edit generated images. We're not entirely sure where this project is going just yet, but we're excited to see what the community does with it!
StableStudio is [Stability AI](https://stability.ai)'s official open-source variant of [DreamStudio](https://www.dreamstudio.ai), our user interface for generative AI. It is a desktop application for local inference of Stable Diffusion that allows users to create and edit generated images. We're excited to see what the community does with it!
# <a id="faq" href="#faq">FAQ</a>
# FAQ
### What's the difference between StableStudio and [DreamStudio](https://dreamstudio.ai)?
@@ -59,9 +34,9 @@ _Not much!_ There are a few tweaks we made to make the project more community-fr
- We removed [DreamStudio](https://dreamstudio.ai)-specific branding.
- All "over-the-wire" API calls have been replaced by a [plugin system](./packages/stablestudio-plugin/README.md) which allows you to easily swap out the back-end.
- StableStudio is now packaged as a tauri application
- With a little bit of TypeScript, you can [create your own plugin](./packages/stablestudio-plugin/README.md) and use StableStudio with any back-end you want!
- All "over-the-wire" API calls have been replaced by a [ComfyUI](https://github.com/comfyanonymous/ComfyUI) backend.
- We removed Stability-specific account features such as billing, API key management, etc.
@@ -69,12 +44,45 @@ _Not much!_ There are a few tweaks we made to make the project more community-fr
### Will [DreamStudio](https://dreamstudio.ai) still be supported?
_Yes!_ Stability's hosted deployment of StableStudio will remain [DreamStudio](https://dreamstudio.ai). It will continue to get updates and stay up-to-date with StableStudio whenever possible.
_Yes!_ Stability's hosted deployment of StableStudio will remain [DreamStudio](https://dreamstudio.ai).
# <a id="contributing" href="#contributing">🧑‍💻 Contributing</a>
# Building From Source
> Make sure you have the rust toolchain, nodejs, and yarn installed
1. Clone the repo
```
git clone https://github.com/Stability-AI/StableStudio
```
2. Install dependencies
```
yarn install
```
```
cargo install tauri-cli
```
3. Build
```
cargo tauri build
```
> Or for development
```
cargo tauri dev
```
Installers/executables should be located in `packages/stablestudio-ui/src-tauri/target/release/bundle`
# Contributing
<div style="display: flex; justify-content: center; align-items: center; gap: 1em; margin: 0 0 2em 0;">
<img src="./misc/ProgrammingRobots.png" style="flex-grow: 1; flex-shrink: 1;" />
<img src="./misc/contributingReadmeImage.png" style="flex-grow: 1; flex-shrink: 1;" />
</div>
_**Community contributions are encouraged!**_
@@ -87,3 +95,26 @@ Here are some useful links...
- [Open Issues](https://github.com/Stability-AI/StableStudio/issues)
- [Open Pull Requests](https://github.com/Stability-AI/StableStudio/pulls)
- [Code of Conduct](./CODE_OF_CONDUCT.md)
## TODO
### Model download
- [ ] Design & implement a community model browser w/ download flow
- [ ] A way to parse URLs into a URL that downloads a model (from say an input)
- [ ] A universal way to download models from URLs
- [ ] BONUS: A way to pick up model downloads if app is closed suddenly
### ComfyUI/SD install config
- [ ] Ability to change comfy location in settings (file choose dialog w/ tauri & write to settings.json)
- [ ] Ability to change comfy install location when/before downloading during first setup
- [ ] Ability to change the particular SD model & location when/before downloading during first setup
- [ ] Ability to change comfyui url in settings
- [ ] Ability to change comfyui cli flags in settings
### Custom inputs
- [ ] define & implement a strategy for arbitrary inputs in stablestudio UI
### Global job UI
- [ ] List model downloads
- [ ] List current/pending gens
- [ ] Ability to cancel jobs (global job API?)
- [ ] Floating UI for jobs - minimalistic

Binary file not shown.

Before

Width:  |  Height:  |  Size: 352 KiB

After

Width:  |  Height:  |  Size: 1.7 MiB

BIN
misc/BannerOld.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 352 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 356 KiB

After

Width:  |  Height:  |  Size: 1.7 MiB

BIN
misc/ProjectCardOld.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 356 KiB

BIN
misc/aboutReadmeImage.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 MiB

View File

@@ -1,6 +1,6 @@
{
"license": "MIT",
"packageManager": "yarn@3.5.1",
"packageManager": "yarn@3.3.0",
"workspaces": {
"packages": [
"packages/*"
@@ -9,9 +9,7 @@
"scripts": {
"postinstall": "node -e \"try { require('husky').install() } catch (e) {if (e.code !== 'MODULE_NOT_FOUND') throw e}\" && yarn build",
"stablestudio-plugin": "yarn workspace @stability/stablestudio-plugin",
"stablestudio-plugin-stability": "yarn workspace @stability/stablestudio-plugin-stability",
"stablestudio-plugin-webgpu": "yarn workspace @stability/stablestudio-plugin-webgpu",
"stablestudio-plugin-webui": "yarn workspace @stability/stablestudio-plugin-webui",
"stablestudio-plugin-comfy": "yarn workspace @stability/stablestudio-plugin-comfy",
"stablestudio-ui": "yarn workspace @stability/stablestudio-ui",
"dev": "yarn workspaces foreach --all --interlaced --verbose --parallel --jobs unlimited run dev",
"build": "yarn workspaces foreach --all --interlaced --verbose --jobs unlimited run build",
@@ -29,5 +27,8 @@
"prettier --write",
"eslint --fix"
]
},
"dependencies": {
"@types/node": "^20.4.2"
}
}

View File

@@ -1 +0,0 @@
dist

View File

@@ -1 +0,0 @@
# create-stablestudio-plugin

View File

@@ -1,64 +0,0 @@
/* eslint-disable import/no-extraneous-dependencies */
import path from "path";
import chalk from "chalk";
import type { PackageManager } from "./helpers/get-pkg-manager";
import { tryGitInit } from "./helpers/git";
import { isFolderEmpty } from "./helpers/is-folder-empty";
import { isWriteable } from "./helpers/is-writeable";
import { makeDir } from "./helpers/make-dir";
import { installTemplate, TemplateType } from "./templates";
export async function createPlugin({
pluginName,
pluginPath,
packageManager,
template = "default",
}: {
pluginName: string;
pluginPath: string;
packageManager: PackageManager;
example?: string;
examplePath?: string;
template?: TemplateType;
}): Promise<void> {
const root = path.resolve(pluginPath);
if (!(await isWriteable(path.dirname(root)))) {
console.error(
"The plugin path is not writable, please check folder permissions and try again."
);
console.error(
"It is likely you do not have write permissions for this folder."
);
process.exit(1);
}
const appName = path.basename(root);
await makeDir(root);
if (!isFolderEmpty(root, appName)) {
process.exit(1);
}
console.log(`Creating a new StableStudio plugin in ${chalk.green(root)}.`);
console.log();
process.chdir(root);
await installTemplate({
pluginName,
root,
packageManager,
template,
});
if (tryGitInit(root)) {
console.log("Initialized a git repository.");
console.log();
}
console.log();
}

View File

@@ -1,17 +0,0 @@
export type PackageManager = "npm" | "pnpm" | "yarn";
export function getPkgManager(): PackageManager {
const userAgent = process.env.npm_config_user_agent;
if (userAgent) {
if (userAgent.startsWith("yarn")) {
return "yarn";
} else if (userAgent.startsWith("pnpm")) {
return "pnpm";
} else {
return "npm";
}
} else {
return "npm";
}
}

View File

@@ -1,48 +0,0 @@
/* eslint-disable import/no-extraneous-dependencies */
import { execSync } from "child_process";
import fs from "fs";
import path from "path";
function isInGitRepository(): boolean {
try {
execSync("git rev-parse --is-inside-work-tree", { stdio: "ignore" });
return true;
} catch (_) {}
return false;
}
function isInMercurialRepository(): boolean {
try {
execSync("hg --cwd . root", { stdio: "ignore" });
return true;
} catch (_) {}
return false;
}
export function tryGitInit(root: string): boolean {
let didInit = false;
try {
execSync("git --version", { stdio: "ignore" });
if (isInGitRepository() || isInMercurialRepository()) {
return false;
}
execSync("git init", { stdio: "ignore" });
didInit = true;
execSync("git checkout -b main", { stdio: "ignore" });
execSync("git add -A", { stdio: "ignore" });
execSync('git commit -m "Initial commit from Create StableStudio Plugin"', {
stdio: "ignore",
});
return true;
} catch (e) {
if (didInit) {
try {
fs.rmSync(path.join(root, ".git"), { recursive: true, force: true });
} catch (_) {}
}
return false;
}
}

View File

@@ -1,76 +0,0 @@
/* eslint-disable import/no-extraneous-dependencies */
import chalk from 'chalk'
import spawn from 'cross-spawn'
import type { PackageManager } from './get-pkg-manager'
interface InstallArgs {
/**
* Indicate whether to install packages using npm, pnpm or Yarn.
*/
packageManager: PackageManager
/**
* Indicate whether the given dependencies are devDependencies.
*/
devDependencies?: boolean
}
/**
* Spawn a package manager installation with either Yarn or NPM.
*
* @returns A Promise that resolves once the installation is finished.
*/
export function install(
root: string,
{ packageManager, devDependencies }: InstallArgs
): Promise<void> {
/**
* (p)npm-specific command-line flags.
*/
const npmFlags: string[] = []
/**
* Yarn-specific command-line flags.
*/
const yarnFlags: string[] = []
/**
* Return a Promise that resolves once the installation is finished.
*/
return new Promise((resolve, reject) => {
let args: string[]
let command = packageManager
const useYarn = packageManager === 'yarn'
args = ['install'];
/**
* Add any package manager-specific flags.
*/
if (useYarn) {
args.push(...yarnFlags)
} else {
args.push(...npmFlags)
}
/**
* Spawn the installation process.
*/
const child = spawn(command, args, {
stdio: 'inherit',
env: {
...process.env,
ADBLOCK: '1',
// we set NODE_ENV to development as pnpm skips dev
// dependencies when production
NODE_ENV: 'development',
DISABLE_OPENCOLLECTIVE: '1',
},
})
child.on('close', (code) => {
if (code !== 0) {
reject({ command: `${command} ${args.join(' ')}` })
return
}
resolve()
})
})
}

View File

@@ -1,63 +0,0 @@
/* eslint-disable import/no-extraneous-dependencies */
import fs from "fs";
import path from "path";
import chalk from "chalk";
export function isFolderEmpty(root: string, name: string): boolean {
const validFiles = [
".DS_Store",
".git",
".gitattributes",
".gitignore",
".gitlab-ci.yml",
".hg",
".hgcheck",
".hgignore",
".idea",
".npmignore",
".travis.yml",
"LICENSE",
"Thumbs.db",
"docs",
"mkdocs.yml",
"npm-debug.log",
"yarn-debug.log",
"yarn-error.log",
"yarnrc.yml",
".yarn",
];
const conflicts = fs
.readdirSync(root)
.filter((file) => !validFiles.includes(file))
// Support IntelliJ IDEA-based editors
.filter((file) => !/\.iml$/.test(file));
if (conflicts.length > 0) {
console.log(
`The directory ${chalk.green(name)} contains files that could conflict:`
);
console.log();
for (const file of conflicts) {
try {
const stats = fs.lstatSync(path.join(root, file));
if (stats.isDirectory()) {
console.log(` ${chalk.blue(file)}/`);
} else {
console.log(` ${file}`);
}
} catch {
console.log(` ${file}`);
}
}
console.log();
console.log(
"Either try using a new directory name, or remove the files listed above."
);
console.log();
return false;
}
return true;
}

View File

@@ -1,10 +0,0 @@
import fs from "fs";
export async function isWriteable(directory: string): Promise<boolean> {
try {
await fs.promises.access(directory, (fs.constants || fs).W_OK);
return true;
} catch (err) {
return false;
}
}

View File

@@ -1,8 +0,0 @@
import fs from "fs";
export function makeDir(
root: string,
options = { recursive: true }
): Promise<string | undefined> {
return fs.promises.mkdir(root, options);
}

View File

@@ -1,20 +0,0 @@
// eslint-disable-next-line import/no-extraneous-dependencies
import validateProjectName from "validate-npm-package-name";
export function validateNpmName(name: string): {
valid: boolean;
problems?: string[];
} {
const nameValidation = validateProjectName(name);
if (nameValidation.validForNewPackages) {
return { valid: true };
}
return {
valid: false,
problems: [
...(nameValidation.errors || []),
...(nameValidation.warnings || []),
],
};
}

View File

@@ -1,204 +0,0 @@
#!/usr/bin/env node
/* eslint-disable import/no-extraneous-dependencies */
import fs from "fs";
import path from "path";
import chalk from "chalk";
import Commander from "commander";
import Conf from "conf";
import prompts from "prompts";
import checkForUpdate from "update-check";
import { createPlugin } from "./create-plugin";
import { getPkgManager } from "./helpers/get-pkg-manager";
import { isFolderEmpty } from "./helpers/is-folder-empty";
import { validateNpmName } from "./helpers/validate-pkg";
import packageJson from "./package.json";
let projectPath = "";
const handleSigTerm = () => process.exit(0);
process.on("SIGINT", handleSigTerm);
process.on("SIGTERM", handleSigTerm);
const onPromptState = (state: any) => {
if (state.aborted) {
// If we don't re-enable the terminal cursor before exiting
// the program, the cursor will remain hidden
process.stdout.write("\x1B[?25h");
process.stdout.write("\n");
process.exit(1);
}
};
const program = new Commander.Command(packageJson.name)
.version(packageJson.version)
.arguments("<project-directory>")
.usage(`${chalk.green("<project-directory>")} [options]`)
.action((name) => {
projectPath = name;
})
.option(
"--use-npm",
`
Explicitly tell the CLI to bootstrap the application using npm
`
)
.option(
"--use-pnpm",
`
Explicitly tell the CLI to bootstrap the application using pnpm
`
)
.option(
"--use-yarn",
`
Explicitly tell the CLI to bootstrap the application using Yarn
`
)
.allowUnknownOption()
.parse(process.argv);
const packageManager = !!program.useNpm
? "npm"
: !!program.usePnpm
? "pnpm"
: !!program.useYarn
? "yarn"
: getPkgManager();
async function run(): Promise<void> {
const conf = new Conf({ projectName: "create-stablestudio-plugin" });
if (typeof projectPath === "string") {
projectPath = projectPath.trim();
}
if (!projectPath) {
const res = await prompts({
onState: onPromptState,
type: "text",
name: "path",
message: "What is your plugin called?",
initial: "my-plugin",
validate: (name) => {
const validation = validateNpmName(path.basename(path.resolve(name)));
if (validation.valid) {
return true;
}
return "Invalid plugin name: " + validation.problems?.[0];
},
});
if (typeof res.path === "string") {
projectPath = res.path.trim();
}
}
if (!projectPath) {
console.log(
"\nPlease specify the plugin directory:\n" +
` ${chalk.cyan(program.name())} ${chalk.green(
"<project-directory>"
)}\n` +
"For example:\n" +
` ${chalk.cyan(program.name())} ${chalk.green(
"my-stablestudio-plugin"
)}\n\n` +
`Run ${chalk.cyan(`${program.name()} --help`)} to see all options.`
);
process.exit(1);
}
const resolvedProjectPath = path.resolve(projectPath);
const projectName = path.basename(resolvedProjectPath);
const { valid, problems } = validateNpmName(projectName);
if (!valid) {
console.error(
`Could not create a plugin called ${chalk.red(
`"${projectName}"`
)} because of npm naming restrictions:`
);
problems?.forEach((p) => console.error(` ${chalk.red.bold("*")} ${p}`));
process.exit(1);
}
/**
* Verify the project dir is empty or doesn't exist
*/
const root = path.resolve(resolvedProjectPath);
const appName = path.basename(root);
const folderExists = fs.existsSync(root);
if (folderExists && !isFolderEmpty(root, appName)) {
process.exit(1);
}
const preferences = (conf.get("preferences") || {}) as Record<
string,
boolean | string
>;
await createPlugin({
pluginName: projectName,
pluginPath: resolvedProjectPath,
packageManager,
});
conf.set("preferences", preferences);
}
const update = checkForUpdate(packageJson).catch(() => null);
async function notifyUpdate(): Promise<void> {
try {
const res = await update;
if (res?.latest) {
const updateMessage =
packageManager === "yarn"
? "yarn global add create-stablestudio-plugin"
: packageManager === "pnpm"
? "pnpm add -g create-stablestudio-plugin"
: "npm i -g create-stablestudio-plugin";
console.log(
chalk.yellow.bold(
"A new version of `create-stablestudio-plugin` is available!"
) +
"\n" +
"You can update by running: " +
chalk.cyan(updateMessage) +
"\n"
);
}
process.exit();
} catch {
// ignore error
}
}
run()
.then(notifyUpdate)
.catch(async (reason) => {
console.log();
console.log("Aborting installation.");
if (reason.command) {
console.log(` ${chalk.cyan(reason.command)} has failed.`);
} else {
console.log(
chalk.red("Unexpected error. Please report it as a bug:") + "\n",
reason
);
}
console.log();
await notifyUpdate();
process.exit(1);
});

View File

@@ -1,53 +0,0 @@
{
"name": "@stability/create-stablestudio-plugin",
"version": "1.0.3",
"keywords": [
"stablestudio",
"react"
],
"description": "Create a StableStudio plugin",
"repository": {
"type": "git",
"url": "https://github.com/Stability-AI/stablestudio",
"directory": "packages/create-stablestudio-plugin"
},
"author": "Stability AI",
"license": "MIT",
"bin": "./dist/index.js",
"files": [
"dist"
],
"scripts": {
"clean": "rimraf lib && rimraf node_modules",
"release": "ncc build ./index.ts -o ./dist/ --minify --no-cache --no-source-map-register",
"prepublishOnly": "yarn release",
"start": "ts-node index.ts"
},
"devDependencies": {
"@types/async-retry": "1.4.2",
"@types/ci-info": "2.0.0",
"@types/cross-spawn": "6.0.0",
"@types/glob": "7.1.1",
"@types/node": "^16.8.0",
"@types/prompts": "2.0.1",
"@types/tar": "4.0.3",
"@types/validate-npm-package-name": "3.0.0",
"async-retry": "1.3.1",
"chalk": "2.4.2",
"ci-info": "watson/ci-info#f43f6a1cefff47fb361c88cf4b943fdbcaafe540",
"commander": "2.20.0",
"conf": "10.2.0",
"cpy": "7.3.0",
"cross-spawn": "6.0.5",
"glob": "8.0.3",
"got": "10.7.0",
"prompts": "2.1.0",
"tar": "4.4.10",
"ts-node": "10.9.1",
"update-check": "1.5.4",
"validate-npm-package-name": "3.0.0"
},
"engines": {
"node": ">=16.8.0"
}
}

View File

@@ -1,29 +0,0 @@
name: release
on:
push:
branches:
- main
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 16
- name: Install Dependencies
run: yarn install
- name: Build
run: yarn build
- name: Upload Release Asset
uses: svenstaro/upload-release-action@v2
with:
file: ./lib/index.js
asset_name: plugin.js
overwrite: true
release_name: "Release ${{ github.ref }}"

View File

@@ -1,26 +0,0 @@
This is a [StableStudio plugin](https://github.com/Stability-AI/StableStudio) bootstrapped with [`create-stablestudio-plugin`](https://github.com/stability-ai/stablestudio/tree/packages/create-stablestudio-plugin)
## Getting Started
- explain how to get a plugin built
```
yarn build
npm run build
```
- explain basic outline of functions
## Learn more
- link to possible reference docs
## Deploying
- explain pushing to github to make CI build and create artifacts stablestudio can import
> you have to grant "Read and write permissions" in the "workflow permissions" section in repository actions settings for the action to work.
```
git push
```

View File

@@ -1 +0,0 @@
{ "extends": ["../../.eslintrc.json"] }

View File

@@ -1,38 +0,0 @@
{
"version": "0.0.0",
"license": "MIT",
"main": "./lib/index.js",
"types": "./lib/index.d.ts",
"files": [
"lib"
],
"scripts": {
"clean": "rimraf lib && rimraf node_modules",
"build:types": "ttsc",
"build:javascript": "tsx scripts/Build.ts",
"build": "yarn build:types && yarn build:javascript",
"dev": "nodemon --watch src --ext ts,tsx,json --exec \"yarn build\""
},
"dependencies": {
"@stability/stablestudio-plugin": "^0.0.0"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^5.33.1",
"@typescript-eslint/parser": "^5.33.1",
"eslint": "8.22.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-markdown": "^3.0.0",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-react": "^7.30.1",
"eslint-plugin-react-hooks": "^4.6.0",
"nodemon": "^2.0.20",
"prettier": "^2.7.1",
"rimraf": "^3.0.2",
"ts-node": "^10.9.1",
"tsx": "^3.12.1",
"ttypescript": "^1.5.13",
"typescript": "4.8.4",
"typescript-transform-paths": "^3.4.4"
}
}

View File

@@ -1,82 +0,0 @@
import * as StableStudio from "@stability/stablestudio-plugin";
export const createPlugin = StableStudio.createPlugin<{
imagesGeneratedSoFar: number;
settings: {
exampleSetting: StableStudio.PluginSettingString;
};
}>(({ set, get }) => ({
imagesGeneratedSoFar: 0,
manifest: {
name: "Example Plugin",
author: "Bobby Joe",
link: "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
icon: `${window.location.origin}/DummyImage.png`,
version: "1.2.3",
license: "MIT",
description: "An example plugin for StableStudio",
},
createStableDiffusionImages: async () => {
const image = await fetch(`${window.location.origin}/DummyImage.png`);
const blob = await image.blob();
const createdAt = new Date();
set(({ imagesGeneratedSoFar }) => ({
imagesGeneratedSoFar: imagesGeneratedSoFar + 4,
}));
return {
id: `${Math.random() * 10000000}`,
images: [
{
id: `${Math.random() * 10000000}`,
createdAt,
blob,
},
{
id: `${Math.random() * 10000000}`,
createdAt,
blob,
},
{
id: `${Math.random() * 10000000}`,
createdAt,
blob,
},
{
id: `${Math.random() * 10000000}`,
createdAt,
blob,
},
],
};
},
getStatus: () => {
const { imagesGeneratedSoFar } = get();
return {
indicator: "success",
text:
imagesGeneratedSoFar > 0
? `${imagesGeneratedSoFar} images generated`
: "Ready",
};
},
settings: {
exampleSetting: {
type: "string" as const,
default: "Hello, World!",
placeholder: "Example setting",
},
},
setSetting: (key, value) =>
set(({ settings }) => ({
settings: {
[key]: { ...settings[key], value: value as string },
},
})),
}));

View File

@@ -1,29 +0,0 @@
{
"include": [
"src/**/*"
],
"exclude": [
"node_modules"
],
"compilerOptions": {
"emitDeclarationOnly": true,
"declaration": true,
"noUncheckedIndexedAccess": false,
"outDir": "./lib",
"baseUrl": "./",
"paths": {
"~/*": [
"./src/*"
]
},
"plugins": [
{
"transform": "typescript-transform-paths"
},
{
"transform": "typescript-transform-paths",
"afterDeclarations": true
}
]
}
}

View File

@@ -1,92 +0,0 @@
import fs from "fs";
import path from "path";
import chalk from "chalk";
import cpy from "cpy";
import { install } from "../helpers/install";
import { GetTemplateFileArgs, InstallTemplateArgs } from "./types";
/**
* Get the file path for a given file in a template, e.g. "next.config.js".
*/
export const getTemplateFile = ({
template,
file,
}: GetTemplateFileArgs): string => {
return path.join(__dirname, "tenplates", template, file);
};
/**
* Install a Next.js internal template to a given `root` directory.
*/
export const installTemplate = async ({
pluginName,
root,
packageManager,
template,
}: InstallTemplateArgs) => {
console.log(chalk.bold(`Using ${packageManager}.`));
/**
* Copy the template files to the target directory.
*/
console.log("\nInitializing plugin with template:", template, "\n");
const templatePath = path.join(__dirname, "templates", template);
const copySource = ["**"];
await cpy(copySource, root, {
parents: true,
cwd: templatePath,
rename: (name) => {
switch (name) {
case "gitignore":
case "eslintrc.json": {
return ".".concat(name);
}
default: {
return name;
}
}
},
});
/**
* pull out package.json and add the plugin name
*/
const packagejson = JSON.parse(
fs.readFileSync(path.join(root, "packagejson"), "utf8")
);
fs.writeFileSync(
path.join(root, "package.json"),
JSON.stringify(
{
name: pluginName,
...packagejson,
},
null,
2
)
);
fs.unlinkSync(path.join(root, "packagejson"));
/**
* These flags will be passed to `install()`, which calls the package manager
* install process.
*/
const installFlags = { packageManager };
/**
* Install package.json dependencies if they exist.
*/
const pkgPath = path.join(root, "package.json");
if (fs.existsSync(pkgPath)) {
console.log("Installing dependencies...");
await install(root, installFlags);
}
};
export * from "./types";

View File

@@ -1,15 +0,0 @@
import { PackageManager } from "../helpers/get-pkg-manager";
export type TemplateType = "default";
export interface GetTemplateFileArgs {
template: TemplateType;
file: string;
}
export interface InstallTemplateArgs {
pluginName: string;
root: string;
packageManager: PackageManager;
template: TemplateType;
}

View File

@@ -1,14 +0,0 @@
{
"compilerOptions": {
"target": "es2019",
"moduleResolution": "node",
"strict": true,
"resolveJsonModule": true,
"esModuleInterop": true,
"skipLibCheck": false
},
"exclude": [
"templates",
"dist"
]
}

View File

@@ -1,5 +1,5 @@
{
"name": "@stability/stablestudio-plugin-webui",
"name": "@stability/stablestudio-plugin-comfy",
"version": "0.0.0",
"license": "MIT",
"main": "./lib/index.js",

View File

@@ -0,0 +1,54 @@
import * as StableStudio from "@stability/stablestudio-plugin";
export const createPlugin = StableStudio.createPlugin(() => ({
manifest: {
name: "ComfyUI Backend",
author: "StabilityAI",
version: "0.0.1",
license: "MIT",
description: "An interface for generating images with ComfyUI",
},
createStableDiffusionImages: async () => {
(
(document.getElementById("comfyui-window") as any)?.contentWindow as any
)?.app.queuePrompt(1, 1);
const image = await fetch(`${window.location.origin}/DummyImage.png`);
const blob = await image.blob();
const createdAt = new Date();
return {
id: `${Math.random() * 10000000}`,
images: [
{
id: `${Math.random() * 10000000}`,
createdAt,
blob,
},
{
id: `${Math.random() * 10000000}`,
createdAt,
blob,
},
{
id: `${Math.random() * 10000000}`,
createdAt,
blob,
},
{
id: `${Math.random() * 10000000}`,
createdAt,
blob,
},
],
};
},
getStatus: () => {
return {
indicator: "success",
text: "Ready",
};
},
}));

View File

@@ -1,2 +0,0 @@
./src/Proto/Generated/**/*
./api-interfaces/**

View File

@@ -1,4 +0,0 @@
{
"extends": ["../../.eslintrc.json"],
"ignorePatterns": ["./src/Proto/Generated/**"]
}

View File

@@ -1,2 +0,0 @@
api-interfaces
lib

View File

@@ -1,2 +0,0 @@
./src/Proto/Generated/**/*
./api-interfaces/**

View File

@@ -1,21 +0,0 @@
MIT License
Copyright (c) 2023 Stability AI
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -1,46 +0,0 @@
{
"name": "@stability/stablestudio-plugin-stability",
"version": "0.0.0",
"license": "MIT",
"main": "./lib/index.js",
"types": "./lib/index.d.ts",
"files": [
"lib"
],
"scripts": {
"clean": "rimraf lib && rimraf api-interfaces && rimraf node_modules",
"generate:proto": "tsx scripts/GenerateProto.ts",
"build:types": "ttsc --project tsconfig.json",
"build:javascript": "tsx scripts/Build.ts",
"build": "yarn build:types && yarn build:javascript",
"dev": "nodemon --watch src --ext ts,json --exec \"yarn build\""
},
"dependencies": {
"@protobuf-ts/grpcweb-transport": "^2.8.2",
"@protobuf-ts/runtime": "^2.8.1",
"@protobuf-ts/runtime-rpc": "^2.8.1"
},
"devDependencies": {
"@protobuf-ts/plugin": "^2.8.1",
"@types/node": "^18.11.9",
"@typescript-eslint/eslint-plugin": "^5.33.1",
"@typescript-eslint/parser": "^5.33.1",
"concurrently": "^7.6.0",
"eslint": "8.22.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-markdown": "^3.0.0",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-react": "^7.30.1",
"eslint-plugin-react-hooks": "^4.6.0",
"nodemon": "^2.0.20",
"prettier": "^2.7.1",
"rimraf": "^3.0.2",
"ts-node": "^10.9.1",
"ts-proto": "^1.133.0",
"tsx": "^3.12.1",
"ttypescript": "^1.5.13",
"typescript": "4.8.4",
"typescript-transform-paths": "^3.4.4"
}
}

View File

@@ -1,21 +0,0 @@
import * as ESBuild from "esbuild";
const main = async () => {
try {
await ESBuild.build({
entryPoints: ["src/index.ts"],
outdir: "lib",
bundle: true,
sourcemap: true,
minify: true,
splitting: true,
format: "esm",
target: ["esnext"],
});
} catch (error) {
console.error(error);
process.exit(1);
}
};
main();

View File

@@ -1,69 +0,0 @@
import * as ChildProcess from "child_process";
import * as FileSystem from "fs";
import * as Path from "path";
// Set up input and output directories
const inputDirectoryPath = Path.join(__dirname, "../api-interfaces");
const outputDirectoryPath = Path.join(__dirname, "../src/Proto/Generated");
// Remove and recreate the output directory
FileSystem.existsSync(outputDirectoryPath) &&
FileSystem.rmSync(outputDirectoryPath, { recursive: true });
FileSystem.mkdirSync(outputDirectoryPath);
// Set up proto directories
const protoDirPath = `${inputDirectoryPath}/src/proto` as const;
const tensorProtoDirPath =
`${inputDirectoryPath}/src/tensorizer/proto` as const;
// Clone latest tensorizer git repository
const tensorizerGitPath = `${inputDirectoryPath}/src/tensorizer`;
// Clone and force update the api-interfaces Git repository
!FileSystem.existsSync(inputDirectoryPath) &&
ChildProcess.execSync(
`git clone https://github.com/Stability-AI/api-interfaces.git ${inputDirectoryPath}`
);
ChildProcess.execSync("git reset --hard origin/main", {
cwd: inputDirectoryPath,
});
// Clone and force update the tensorizer Git repository
!FileSystem.existsSync(`${tensorizerGitPath}/.git`) &&
ChildProcess.execSync(
`git clone https://github.com/coreweave/tensorizer.git ${tensorizerGitPath}`
);
ChildProcess.execSync("git reset --hard origin/main", {
cwd: tensorizerGitPath,
});
// Copy tensors.proto from tensorizer to api-interfaces proto directory
FileSystem.copyFileSync(
`${tensorProtoDirPath}/tensors.proto`,
`${protoDirPath}/tensors.proto`
);
// Get all the proto paths and source files
const protoPaths = [
protoDirPath,
...FileSystem.readdirSync(protoDirPath)
.filter((file) => file.endsWith(".proto"))
.map((file) => Path.join(protoDirPath, file)),
].join(" ");
// Generate TypeScript files from the final list of proto files
ChildProcess.execSync(
`npx protoc --ts_out ${outputDirectoryPath} --proto_path ${protoPaths}`
);

View File

@@ -1,236 +0,0 @@
// @generated by protobuf-ts 2.8.2
// @generated from protobuf file "dashboard.proto" (package "gooseai", syntax proto3)
// tslint:disable
import type { RpcTransport } from "@protobuf-ts/runtime-rpc";
import type { ServiceInfo } from "@protobuf-ts/runtime-rpc";
import { DashboardService } from "./dashboard";
import type { GetAutoChargeRequest } from "./dashboard";
import type { AutoChargeIntent } from "./dashboard";
import type { CreateAutoChargeIntentRequest } from "./dashboard";
import type { Charges } from "./dashboard";
import type { GetChargesRequest } from "./dashboard";
import type { Charge } from "./dashboard";
import type { CreateChargeRequest } from "./dashboard";
import type { UserPasswordChangeTicket } from "./dashboard";
import type { UpdateUserInfoRequest } from "./dashboard";
import type { ClientSettings } from "./dashboard";
import type { UpdateDefaultOrganizationRequest } from "./dashboard";
import type { APIKeyFindRequest } from "./dashboard";
import type { APIKey } from "./dashboard";
import type { APIKeyRequest } from "./dashboard";
import type { Metrics } from "./dashboard";
import type { GetMetricsRequest } from "./dashboard";
import type { Organization } from "./dashboard";
import type { GetOrganizationRequest } from "./dashboard";
import { stackIntercept } from "@protobuf-ts/runtime-rpc";
import type { User } from "./dashboard";
import type { EmptyRequest } from "./dashboard";
import type { UnaryCall } from "@protobuf-ts/runtime-rpc";
import type { RpcOptions } from "@protobuf-ts/runtime-rpc";
/**
* @generated from protobuf service gooseai.DashboardService
*/
export interface IDashboardServiceClient {
/**
* Get info
*
* @generated from protobuf rpc: GetMe(gooseai.EmptyRequest) returns (gooseai.User);
*/
getMe(input: EmptyRequest, options?: RpcOptions): UnaryCall<EmptyRequest, User>;
/**
* @generated from protobuf rpc: GetOrganization(gooseai.GetOrganizationRequest) returns (gooseai.Organization);
*/
getOrganization(input: GetOrganizationRequest, options?: RpcOptions): UnaryCall<GetOrganizationRequest, Organization>;
/**
* @generated from protobuf rpc: GetMetrics(gooseai.GetMetricsRequest) returns (gooseai.Metrics);
*/
getMetrics(input: GetMetricsRequest, options?: RpcOptions): UnaryCall<GetMetricsRequest, Metrics>;
/**
* API key management
*
* @generated from protobuf rpc: CreateAPIKey(gooseai.APIKeyRequest) returns (gooseai.APIKey);
*/
createAPIKey(input: APIKeyRequest, options?: RpcOptions): UnaryCall<APIKeyRequest, APIKey>;
/**
* @generated from protobuf rpc: DeleteAPIKey(gooseai.APIKeyFindRequest) returns (gooseai.APIKey);
*/
deleteAPIKey(input: APIKeyFindRequest, options?: RpcOptions): UnaryCall<APIKeyFindRequest, APIKey>;
/**
* User settings
*
* @generated from protobuf rpc: UpdateDefaultOrganization(gooseai.UpdateDefaultOrganizationRequest) returns (gooseai.User);
*/
updateDefaultOrganization(input: UpdateDefaultOrganizationRequest, options?: RpcOptions): UnaryCall<UpdateDefaultOrganizationRequest, User>;
/**
* @generated from protobuf rpc: GetClientSettings(gooseai.EmptyRequest) returns (gooseai.ClientSettings);
*/
getClientSettings(input: EmptyRequest, options?: RpcOptions): UnaryCall<EmptyRequest, ClientSettings>;
/**
* @generated from protobuf rpc: SetClientSettings(gooseai.ClientSettings) returns (gooseai.ClientSettings);
*/
setClientSettings(input: ClientSettings, options?: RpcOptions): UnaryCall<ClientSettings, ClientSettings>;
/**
* @generated from protobuf rpc: UpdateUserInfo(gooseai.UpdateUserInfoRequest) returns (gooseai.User);
*/
updateUserInfo(input: UpdateUserInfoRequest, options?: RpcOptions): UnaryCall<UpdateUserInfoRequest, User>;
/**
* @generated from protobuf rpc: CreatePasswordChangeTicket(gooseai.EmptyRequest) returns (gooseai.UserPasswordChangeTicket);
*/
createPasswordChangeTicket(input: EmptyRequest, options?: RpcOptions): UnaryCall<EmptyRequest, UserPasswordChangeTicket>;
/**
* @generated from protobuf rpc: DeleteAccount(gooseai.EmptyRequest) returns (gooseai.User);
*/
deleteAccount(input: EmptyRequest, options?: RpcOptions): UnaryCall<EmptyRequest, User>;
/**
* Payment functions
*
* @generated from protobuf rpc: CreateCharge(gooseai.CreateChargeRequest) returns (gooseai.Charge);
*/
createCharge(input: CreateChargeRequest, options?: RpcOptions): UnaryCall<CreateChargeRequest, Charge>;
/**
* @generated from protobuf rpc: GetCharges(gooseai.GetChargesRequest) returns (gooseai.Charges);
*/
getCharges(input: GetChargesRequest, options?: RpcOptions): UnaryCall<GetChargesRequest, Charges>;
/**
* @generated from protobuf rpc: CreateAutoChargeIntent(gooseai.CreateAutoChargeIntentRequest) returns (gooseai.AutoChargeIntent);
*/
createAutoChargeIntent(input: CreateAutoChargeIntentRequest, options?: RpcOptions): UnaryCall<CreateAutoChargeIntentRequest, AutoChargeIntent>;
/**
* @generated from protobuf rpc: UpdateAutoChargeIntent(gooseai.CreateAutoChargeIntentRequest) returns (gooseai.AutoChargeIntent);
*/
updateAutoChargeIntent(input: CreateAutoChargeIntentRequest, options?: RpcOptions): UnaryCall<CreateAutoChargeIntentRequest, AutoChargeIntent>;
/**
* @generated from protobuf rpc: GetAutoChargeIntent(gooseai.GetAutoChargeRequest) returns (gooseai.AutoChargeIntent);
*/
getAutoChargeIntent(input: GetAutoChargeRequest, options?: RpcOptions): UnaryCall<GetAutoChargeRequest, AutoChargeIntent>;
}
/**
* @generated from protobuf service gooseai.DashboardService
*/
export class DashboardServiceClient implements IDashboardServiceClient, ServiceInfo {
typeName = DashboardService.typeName;
methods = DashboardService.methods;
options = DashboardService.options;
constructor(private readonly _transport: RpcTransport) {
}
/**
* Get info
*
* @generated from protobuf rpc: GetMe(gooseai.EmptyRequest) returns (gooseai.User);
*/
getMe(input: EmptyRequest, options?: RpcOptions): UnaryCall<EmptyRequest, User> {
const method = this.methods[0], opt = this._transport.mergeOptions(options);
return stackIntercept<EmptyRequest, User>("unary", this._transport, method, opt, input);
}
/**
* @generated from protobuf rpc: GetOrganization(gooseai.GetOrganizationRequest) returns (gooseai.Organization);
*/
getOrganization(input: GetOrganizationRequest, options?: RpcOptions): UnaryCall<GetOrganizationRequest, Organization> {
const method = this.methods[1], opt = this._transport.mergeOptions(options);
return stackIntercept<GetOrganizationRequest, Organization>("unary", this._transport, method, opt, input);
}
/**
* @generated from protobuf rpc: GetMetrics(gooseai.GetMetricsRequest) returns (gooseai.Metrics);
*/
getMetrics(input: GetMetricsRequest, options?: RpcOptions): UnaryCall<GetMetricsRequest, Metrics> {
const method = this.methods[2], opt = this._transport.mergeOptions(options);
return stackIntercept<GetMetricsRequest, Metrics>("unary", this._transport, method, opt, input);
}
/**
* API key management
*
* @generated from protobuf rpc: CreateAPIKey(gooseai.APIKeyRequest) returns (gooseai.APIKey);
*/
createAPIKey(input: APIKeyRequest, options?: RpcOptions): UnaryCall<APIKeyRequest, APIKey> {
const method = this.methods[3], opt = this._transport.mergeOptions(options);
return stackIntercept<APIKeyRequest, APIKey>("unary", this._transport, method, opt, input);
}
/**
* @generated from protobuf rpc: DeleteAPIKey(gooseai.APIKeyFindRequest) returns (gooseai.APIKey);
*/
deleteAPIKey(input: APIKeyFindRequest, options?: RpcOptions): UnaryCall<APIKeyFindRequest, APIKey> {
const method = this.methods[4], opt = this._transport.mergeOptions(options);
return stackIntercept<APIKeyFindRequest, APIKey>("unary", this._transport, method, opt, input);
}
/**
* User settings
*
* @generated from protobuf rpc: UpdateDefaultOrganization(gooseai.UpdateDefaultOrganizationRequest) returns (gooseai.User);
*/
updateDefaultOrganization(input: UpdateDefaultOrganizationRequest, options?: RpcOptions): UnaryCall<UpdateDefaultOrganizationRequest, User> {
const method = this.methods[5], opt = this._transport.mergeOptions(options);
return stackIntercept<UpdateDefaultOrganizationRequest, User>("unary", this._transport, method, opt, input);
}
/**
* @generated from protobuf rpc: GetClientSettings(gooseai.EmptyRequest) returns (gooseai.ClientSettings);
*/
getClientSettings(input: EmptyRequest, options?: RpcOptions): UnaryCall<EmptyRequest, ClientSettings> {
const method = this.methods[6], opt = this._transport.mergeOptions(options);
return stackIntercept<EmptyRequest, ClientSettings>("unary", this._transport, method, opt, input);
}
/**
* @generated from protobuf rpc: SetClientSettings(gooseai.ClientSettings) returns (gooseai.ClientSettings);
*/
setClientSettings(input: ClientSettings, options?: RpcOptions): UnaryCall<ClientSettings, ClientSettings> {
const method = this.methods[7], opt = this._transport.mergeOptions(options);
return stackIntercept<ClientSettings, ClientSettings>("unary", this._transport, method, opt, input);
}
/**
* @generated from protobuf rpc: UpdateUserInfo(gooseai.UpdateUserInfoRequest) returns (gooseai.User);
*/
updateUserInfo(input: UpdateUserInfoRequest, options?: RpcOptions): UnaryCall<UpdateUserInfoRequest, User> {
const method = this.methods[8], opt = this._transport.mergeOptions(options);
return stackIntercept<UpdateUserInfoRequest, User>("unary", this._transport, method, opt, input);
}
/**
* @generated from protobuf rpc: CreatePasswordChangeTicket(gooseai.EmptyRequest) returns (gooseai.UserPasswordChangeTicket);
*/
createPasswordChangeTicket(input: EmptyRequest, options?: RpcOptions): UnaryCall<EmptyRequest, UserPasswordChangeTicket> {
const method = this.methods[9], opt = this._transport.mergeOptions(options);
return stackIntercept<EmptyRequest, UserPasswordChangeTicket>("unary", this._transport, method, opt, input);
}
/**
* @generated from protobuf rpc: DeleteAccount(gooseai.EmptyRequest) returns (gooseai.User);
*/
deleteAccount(input: EmptyRequest, options?: RpcOptions): UnaryCall<EmptyRequest, User> {
const method = this.methods[10], opt = this._transport.mergeOptions(options);
return stackIntercept<EmptyRequest, User>("unary", this._transport, method, opt, input);
}
/**
* Payment functions
*
* @generated from protobuf rpc: CreateCharge(gooseai.CreateChargeRequest) returns (gooseai.Charge);
*/
createCharge(input: CreateChargeRequest, options?: RpcOptions): UnaryCall<CreateChargeRequest, Charge> {
const method = this.methods[11], opt = this._transport.mergeOptions(options);
return stackIntercept<CreateChargeRequest, Charge>("unary", this._transport, method, opt, input);
}
/**
* @generated from protobuf rpc: GetCharges(gooseai.GetChargesRequest) returns (gooseai.Charges);
*/
getCharges(input: GetChargesRequest, options?: RpcOptions): UnaryCall<GetChargesRequest, Charges> {
const method = this.methods[12], opt = this._transport.mergeOptions(options);
return stackIntercept<GetChargesRequest, Charges>("unary", this._transport, method, opt, input);
}
/**
* @generated from protobuf rpc: CreateAutoChargeIntent(gooseai.CreateAutoChargeIntentRequest) returns (gooseai.AutoChargeIntent);
*/
createAutoChargeIntent(input: CreateAutoChargeIntentRequest, options?: RpcOptions): UnaryCall<CreateAutoChargeIntentRequest, AutoChargeIntent> {
const method = this.methods[13], opt = this._transport.mergeOptions(options);
return stackIntercept<CreateAutoChargeIntentRequest, AutoChargeIntent>("unary", this._transport, method, opt, input);
}
/**
* @generated from protobuf rpc: UpdateAutoChargeIntent(gooseai.CreateAutoChargeIntentRequest) returns (gooseai.AutoChargeIntent);
*/
updateAutoChargeIntent(input: CreateAutoChargeIntentRequest, options?: RpcOptions): UnaryCall<CreateAutoChargeIntentRequest, AutoChargeIntent> {
const method = this.methods[14], opt = this._transport.mergeOptions(options);
return stackIntercept<CreateAutoChargeIntentRequest, AutoChargeIntent>("unary", this._transport, method, opt, input);
}
/**
* @generated from protobuf rpc: GetAutoChargeIntent(gooseai.GetAutoChargeRequest) returns (gooseai.AutoChargeIntent);
*/
getAutoChargeIntent(input: GetAutoChargeRequest, options?: RpcOptions): UnaryCall<GetAutoChargeRequest, AutoChargeIntent> {
const method = this.methods[15], opt = this._transport.mergeOptions(options);
return stackIntercept<GetAutoChargeRequest, AutoChargeIntent>("unary", this._transport, method, opt, input);
}
}

View File

@@ -1,37 +0,0 @@
// @generated by protobuf-ts 2.8.2
// @generated from protobuf file "engines.proto" (package "gooseai", syntax proto3)
// tslint:disable
import type { RpcTransport } from "@protobuf-ts/runtime-rpc";
import type { ServiceInfo } from "@protobuf-ts/runtime-rpc";
import { EnginesService } from "./engines";
import { stackIntercept } from "@protobuf-ts/runtime-rpc";
import type { Engines } from "./engines";
import type { ListEnginesRequest } from "./engines";
import type { UnaryCall } from "@protobuf-ts/runtime-rpc";
import type { RpcOptions } from "@protobuf-ts/runtime-rpc";
/**
* @generated from protobuf service gooseai.EnginesService
*/
export interface IEnginesServiceClient {
/**
* @generated from protobuf rpc: ListEngines(gooseai.ListEnginesRequest) returns (gooseai.Engines);
*/
listEngines(input: ListEnginesRequest, options?: RpcOptions): UnaryCall<ListEnginesRequest, Engines>;
}
/**
* @generated from protobuf service gooseai.EnginesService
*/
export class EnginesServiceClient implements IEnginesServiceClient, ServiceInfo {
typeName = EnginesService.typeName;
methods = EnginesService.methods;
options = EnginesService.options;
constructor(private readonly _transport: RpcTransport) {
}
/**
* @generated from protobuf rpc: ListEngines(gooseai.ListEnginesRequest) returns (gooseai.Engines);
*/
listEngines(input: ListEnginesRequest, options?: RpcOptions): UnaryCall<ListEnginesRequest, Engines> {
const method = this.methods[0], opt = this._transport.mergeOptions(options);
return stackIntercept<ListEnginesRequest, Engines>("unary", this._transport, method, opt, input);
}
}

View File

@@ -1,279 +0,0 @@
// @generated by protobuf-ts 2.8.2
// @generated from protobuf file "engines.proto" (package "gooseai", syntax proto3)
// tslint:disable
import { ServiceType } from "@protobuf-ts/runtime-rpc";
import type { BinaryWriteOptions } from "@protobuf-ts/runtime";
import type { IBinaryWriter } from "@protobuf-ts/runtime";
import { WireType } from "@protobuf-ts/runtime";
import type { BinaryReadOptions } from "@protobuf-ts/runtime";
import type { IBinaryReader } from "@protobuf-ts/runtime";
import { UnknownFieldHandler } from "@protobuf-ts/runtime";
import type { PartialMessage } from "@protobuf-ts/runtime";
import { reflectionMergePartial } from "@protobuf-ts/runtime";
import { MESSAGE_TYPE } from "@protobuf-ts/runtime";
import { MessageType } from "@protobuf-ts/runtime";
/**
* Engine info struct
*
* @generated from protobuf message gooseai.EngineInfo
*/
export interface EngineInfo {
/**
* @generated from protobuf field: string id = 1;
*/
id: string;
/**
* @generated from protobuf field: string owner = 2;
*/
owner: string;
/**
* @generated from protobuf field: bool ready = 3;
*/
ready: boolean;
/**
* @generated from protobuf field: gooseai.EngineType type = 4;
*/
type: EngineType;
/**
* @generated from protobuf field: gooseai.EngineTokenizer tokenizer = 5;
*/
tokenizer: EngineTokenizer;
/**
* @generated from protobuf field: string name = 6;
*/
name: string;
/**
* @generated from protobuf field: string description = 7;
*/
description: string;
}
/**
* Empty
*
* @generated from protobuf message gooseai.ListEnginesRequest
*/
export interface ListEnginesRequest {
}
/**
* Engine info list
*
* @generated from protobuf message gooseai.Engines
*/
export interface Engines {
/**
* @generated from protobuf field: repeated gooseai.EngineInfo engine = 1;
*/
engine: EngineInfo[];
}
/**
* Possible engine type
*
* @generated from protobuf enum gooseai.EngineType
*/
export enum EngineType {
/**
* @generated from protobuf enum value: TEXT = 0;
*/
TEXT = 0,
/**
* @generated from protobuf enum value: PICTURE = 1;
*/
PICTURE = 1,
/**
* @generated from protobuf enum value: AUDIO = 2;
*/
AUDIO = 2,
/**
* @generated from protobuf enum value: VIDEO = 3;
*/
VIDEO = 3,
/**
* @generated from protobuf enum value: CLASSIFICATION = 4;
*/
CLASSIFICATION = 4,
/**
* @generated from protobuf enum value: STORAGE = 5;
*/
STORAGE = 5
}
/**
* @generated from protobuf enum gooseai.EngineTokenizer
*/
export enum EngineTokenizer {
/**
* @generated from protobuf enum value: GPT2 = 0;
*/
GPT2 = 0,
/**
* @generated from protobuf enum value: PILE = 1;
*/
PILE = 1
}
// @generated message type with reflection information, may provide speed optimized methods
class EngineInfo$Type extends MessageType<EngineInfo> {
constructor() {
super("gooseai.EngineInfo", [
{ no: 1, name: "id", kind: "scalar", T: 9 /*ScalarType.STRING*/ },
{ no: 2, name: "owner", kind: "scalar", T: 9 /*ScalarType.STRING*/ },
{ no: 3, name: "ready", kind: "scalar", T: 8 /*ScalarType.BOOL*/ },
{ no: 4, name: "type", kind: "enum", T: () => ["gooseai.EngineType", EngineType] },
{ no: 5, name: "tokenizer", kind: "enum", T: () => ["gooseai.EngineTokenizer", EngineTokenizer] },
{ no: 6, name: "name", kind: "scalar", T: 9 /*ScalarType.STRING*/ },
{ no: 7, name: "description", kind: "scalar", T: 9 /*ScalarType.STRING*/ }
]);
}
create(value?: PartialMessage<EngineInfo>): EngineInfo {
const message = { id: "", owner: "", ready: false, type: 0, tokenizer: 0, name: "", description: "" };
globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
if (value !== undefined)
reflectionMergePartial<EngineInfo>(this, message, value);
return message;
}
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: EngineInfo): EngineInfo {
let message = target ?? this.create(), end = reader.pos + length;
while (reader.pos < end) {
let [fieldNo, wireType] = reader.tag();
switch (fieldNo) {
case /* string id */ 1:
message.id = reader.string();
break;
case /* string owner */ 2:
message.owner = reader.string();
break;
case /* bool ready */ 3:
message.ready = reader.bool();
break;
case /* gooseai.EngineType type */ 4:
message.type = reader.int32();
break;
case /* gooseai.EngineTokenizer tokenizer */ 5:
message.tokenizer = reader.int32();
break;
case /* string name */ 6:
message.name = reader.string();
break;
case /* string description */ 7:
message.description = reader.string();
break;
default:
let u = options.readUnknownField;
if (u === "throw")
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
let d = reader.skip(wireType);
if (u !== false)
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
}
}
return message;
}
internalBinaryWrite(message: EngineInfo, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
/* string id = 1; */
if (message.id !== "")
writer.tag(1, WireType.LengthDelimited).string(message.id);
/* string owner = 2; */
if (message.owner !== "")
writer.tag(2, WireType.LengthDelimited).string(message.owner);
/* bool ready = 3; */
if (message.ready !== false)
writer.tag(3, WireType.Varint).bool(message.ready);
/* gooseai.EngineType type = 4; */
if (message.type !== 0)
writer.tag(4, WireType.Varint).int32(message.type);
/* gooseai.EngineTokenizer tokenizer = 5; */
if (message.tokenizer !== 0)
writer.tag(5, WireType.Varint).int32(message.tokenizer);
/* string name = 6; */
if (message.name !== "")
writer.tag(6, WireType.LengthDelimited).string(message.name);
/* string description = 7; */
if (message.description !== "")
writer.tag(7, WireType.LengthDelimited).string(message.description);
let u = options.writeUnknownFields;
if (u !== false)
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
return writer;
}
}
/**
* @generated MessageType for protobuf message gooseai.EngineInfo
*/
export const EngineInfo = new EngineInfo$Type();
// @generated message type with reflection information, may provide speed optimized methods
class ListEnginesRequest$Type extends MessageType<ListEnginesRequest> {
constructor() {
super("gooseai.ListEnginesRequest", []);
}
create(value?: PartialMessage<ListEnginesRequest>): ListEnginesRequest {
const message = {};
globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
if (value !== undefined)
reflectionMergePartial<ListEnginesRequest>(this, message, value);
return message;
}
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: ListEnginesRequest): ListEnginesRequest {
return target ?? this.create();
}
internalBinaryWrite(message: ListEnginesRequest, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
let u = options.writeUnknownFields;
if (u !== false)
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
return writer;
}
}
/**
* @generated MessageType for protobuf message gooseai.ListEnginesRequest
*/
export const ListEnginesRequest = new ListEnginesRequest$Type();
// @generated message type with reflection information, may provide speed optimized methods
class Engines$Type extends MessageType<Engines> {
constructor() {
super("gooseai.Engines", [
{ no: 1, name: "engine", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => EngineInfo }
]);
}
create(value?: PartialMessage<Engines>): Engines {
const message = { engine: [] };
globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
if (value !== undefined)
reflectionMergePartial<Engines>(this, message, value);
return message;
}
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: Engines): Engines {
let message = target ?? this.create(), end = reader.pos + length;
while (reader.pos < end) {
let [fieldNo, wireType] = reader.tag();
switch (fieldNo) {
case /* repeated gooseai.EngineInfo engine */ 1:
message.engine.push(EngineInfo.internalBinaryRead(reader, reader.uint32(), options));
break;
default:
let u = options.readUnknownField;
if (u === "throw")
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
let d = reader.skip(wireType);
if (u !== false)
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
}
}
return message;
}
internalBinaryWrite(message: Engines, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
/* repeated gooseai.EngineInfo engine = 1; */
for (let i = 0; i < message.engine.length; i++)
EngineInfo.internalBinaryWrite(message.engine[i], writer.tag(1, WireType.LengthDelimited).fork(), options).join();
let u = options.writeUnknownFields;
if (u !== false)
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
return writer;
}
}
/**
* @generated MessageType for protobuf message gooseai.Engines
*/
export const Engines = new Engines$Type();
/**
* @generated ServiceType for protobuf service gooseai.EnginesService
*/
export const EnginesService = new ServiceType("gooseai.EnginesService", [
{ name: "ListEngines", options: {}, I: ListEnginesRequest, O: Engines }
]);

View File

@@ -1,57 +0,0 @@
// @generated by protobuf-ts 2.8.2
// @generated from protobuf file "generation.proto" (package "gooseai", syntax proto3)
// tslint:disable
import type { RpcTransport } from "@protobuf-ts/runtime-rpc";
import type { ServiceInfo } from "@protobuf-ts/runtime-rpc";
import { GenerationService } from "./generation";
import type { ChainRequest } from "./generation";
import { stackIntercept } from "@protobuf-ts/runtime-rpc";
import type { Answer } from "./generation";
import type { Request } from "./generation";
import type { ServerStreamingCall } from "@protobuf-ts/runtime-rpc";
import type { RpcOptions } from "@protobuf-ts/runtime-rpc";
/**
*
* gRPC services
*
*
* @generated from protobuf service gooseai.GenerationService
*/
export interface IGenerationServiceClient {
/**
* @generated from protobuf rpc: Generate(gooseai.Request) returns (stream gooseai.Answer);
*/
generate(input: Request, options?: RpcOptions): ServerStreamingCall<Request, Answer>;
/**
* @generated from protobuf rpc: ChainGenerate(gooseai.ChainRequest) returns (stream gooseai.Answer);
*/
chainGenerate(input: ChainRequest, options?: RpcOptions): ServerStreamingCall<ChainRequest, Answer>;
}
/**
*
* gRPC services
*
*
* @generated from protobuf service gooseai.GenerationService
*/
export class GenerationServiceClient implements IGenerationServiceClient, ServiceInfo {
typeName = GenerationService.typeName;
methods = GenerationService.methods;
options = GenerationService.options;
constructor(private readonly _transport: RpcTransport) {
}
/**
* @generated from protobuf rpc: Generate(gooseai.Request) returns (stream gooseai.Answer);
*/
generate(input: Request, options?: RpcOptions): ServerStreamingCall<Request, Answer> {
const method = this.methods[0], opt = this._transport.mergeOptions(options);
return stackIntercept<Request, Answer>("serverStreaming", this._transport, method, opt, input);
}
/**
* @generated from protobuf rpc: ChainGenerate(gooseai.ChainRequest) returns (stream gooseai.Answer);
*/
chainGenerate(input: ChainRequest, options?: RpcOptions): ServerStreamingCall<ChainRequest, Answer> {
const method = this.methods[1], opt = this._transport.mergeOptions(options);
return stackIntercept<ChainRequest, Answer>("serverStreaming", this._transport, method, opt, input);
}
}

View File

@@ -1,480 +0,0 @@
// @generated by protobuf-ts 2.8.2
// @generated from protobuf file "google/protobuf/struct.proto" (package "google.protobuf", syntax proto3)
// tslint:disable
//
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
import type { BinaryWriteOptions } from "@protobuf-ts/runtime";
import type { IBinaryWriter } from "@protobuf-ts/runtime";
import { WireType } from "@protobuf-ts/runtime";
import type { BinaryReadOptions } from "@protobuf-ts/runtime";
import type { IBinaryReader } from "@protobuf-ts/runtime";
import { UnknownFieldHandler } from "@protobuf-ts/runtime";
import type { PartialMessage } from "@protobuf-ts/runtime";
import { reflectionMergePartial } from "@protobuf-ts/runtime";
import { MESSAGE_TYPE } from "@protobuf-ts/runtime";
import { isJsonObject } from "@protobuf-ts/runtime";
import { typeofJsonValue } from "@protobuf-ts/runtime";
import type { JsonValue } from "@protobuf-ts/runtime";
import type { JsonReadOptions } from "@protobuf-ts/runtime";
import type { JsonWriteOptions } from "@protobuf-ts/runtime";
import type { JsonObject } from "@protobuf-ts/runtime";
import { MessageType } from "@protobuf-ts/runtime";
/**
* `Struct` represents a structured data value, consisting of fields
* which map to dynamically typed values. In some languages, `Struct`
* might be supported by a native representation. For example, in
* scripting languages like JS a struct is represented as an
* object. The details of that representation are described together
* with the proto support for the language.
*
* The JSON representation for `Struct` is JSON object.
*
* @generated from protobuf message google.protobuf.Struct
*/
export interface Struct {
/**
* Unordered map of dynamically typed values.
*
* @generated from protobuf field: map<string, google.protobuf.Value> fields = 1;
*/
fields: {
[key: string]: Value;
};
}
/**
* `Value` represents a dynamically typed value which can be either
* null, a number, a string, a boolean, a recursive struct value, or a
* list of values. A producer of value is expected to set one of these
* variants. Absence of any variant indicates an error.
*
* The JSON representation for `Value` is JSON value.
*
* @generated from protobuf message google.protobuf.Value
*/
export interface Value {
/**
* @generated from protobuf oneof: kind
*/
kind: {
oneofKind: "nullValue";
/**
* Represents a null value.
*
* @generated from protobuf field: google.protobuf.NullValue null_value = 1;
*/
nullValue: NullValue;
} | {
oneofKind: "numberValue";
/**
* Represents a double value.
*
* @generated from protobuf field: double number_value = 2;
*/
numberValue: number;
} | {
oneofKind: "stringValue";
/**
* Represents a string value.
*
* @generated from protobuf field: string string_value = 3;
*/
stringValue: string;
} | {
oneofKind: "boolValue";
/**
* Represents a boolean value.
*
* @generated from protobuf field: bool bool_value = 4;
*/
boolValue: boolean;
} | {
oneofKind: "structValue";
/**
* Represents a structured value.
*
* @generated from protobuf field: google.protobuf.Struct struct_value = 5;
*/
structValue: Struct;
} | {
oneofKind: "listValue";
/**
* Represents a repeated `Value`.
*
* @generated from protobuf field: google.protobuf.ListValue list_value = 6;
*/
listValue: ListValue;
} | {
oneofKind: undefined;
};
}
/**
* `ListValue` is a wrapper around a repeated field of values.
*
* The JSON representation for `ListValue` is JSON array.
*
* @generated from protobuf message google.protobuf.ListValue
*/
export interface ListValue {
/**
* Repeated field of dynamically typed values.
*
* @generated from protobuf field: repeated google.protobuf.Value values = 1;
*/
values: Value[];
}
/**
* `NullValue` is a singleton enumeration to represent the null value for the
* `Value` type union.
*
* The JSON representation for `NullValue` is JSON `null`.
*
* @generated from protobuf enum google.protobuf.NullValue
*/
export enum NullValue {
/**
* Null value.
*
* @generated from protobuf enum value: NULL_VALUE = 0;
*/
NULL_VALUE = 0
}
// @generated message type with reflection information, may provide speed optimized methods
class Struct$Type extends MessageType<Struct> {
constructor() {
super("google.protobuf.Struct", [
{ no: 1, name: "fields", kind: "map", K: 9 /*ScalarType.STRING*/, V: { kind: "message", T: () => Value } }
]);
}
/**
* Encode `Struct` to JSON object.
*/
internalJsonWrite(message: Struct, options: JsonWriteOptions): JsonValue {
let json: JsonObject = {};
for (let [k, v] of Object.entries(message.fields)) {
json[k] = Value.toJson(v);
}
return json;
}
/**
* Decode `Struct` from JSON object.
*/
internalJsonRead(json: JsonValue, options: JsonReadOptions, target?: Struct): Struct {
if (!isJsonObject(json))
throw new globalThis.Error("Unable to parse message " + this.typeName + " from JSON " + typeofJsonValue(json) + ".");
if (!target)
target = this.create();
for (let [k, v] of globalThis.Object.entries(json)) {
target.fields[k] = Value.fromJson(v);
}
return target;
}
create(value?: PartialMessage<Struct>): Struct {
const message = { fields: {} };
globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
if (value !== undefined)
reflectionMergePartial<Struct>(this, message, value);
return message;
}
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: Struct): Struct {
let message = target ?? this.create(), end = reader.pos + length;
while (reader.pos < end) {
let [fieldNo, wireType] = reader.tag();
switch (fieldNo) {
case /* map<string, google.protobuf.Value> fields */ 1:
this.binaryReadMap1(message.fields, reader, options);
break;
default:
let u = options.readUnknownField;
if (u === "throw")
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
let d = reader.skip(wireType);
if (u !== false)
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
}
}
return message;
}
private binaryReadMap1(map: Struct["fields"], reader: IBinaryReader, options: BinaryReadOptions): void {
let len = reader.uint32(), end = reader.pos + len, key: keyof Struct["fields"] | undefined, val: Struct["fields"][any] | undefined;
while (reader.pos < end) {
let [fieldNo, wireType] = reader.tag();
switch (fieldNo) {
case 1:
key = reader.string();
break;
case 2:
val = Value.internalBinaryRead(reader, reader.uint32(), options);
break;
default: throw new globalThis.Error("unknown map entry field for field google.protobuf.Struct.fields");
}
}
map[key ?? ""] = val ?? Value.create();
}
internalBinaryWrite(message: Struct, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
/* map<string, google.protobuf.Value> fields = 1; */
for (let k of Object.keys(message.fields)) {
writer.tag(1, WireType.LengthDelimited).fork().tag(1, WireType.LengthDelimited).string(k);
writer.tag(2, WireType.LengthDelimited).fork();
Value.internalBinaryWrite(message.fields[k], writer, options);
writer.join().join();
}
let u = options.writeUnknownFields;
if (u !== false)
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
return writer;
}
}
/**
* @generated MessageType for protobuf message google.protobuf.Struct
*/
export const Struct = new Struct$Type();
// @generated message type with reflection information, may provide speed optimized methods
class Value$Type extends MessageType<Value> {
constructor() {
super("google.protobuf.Value", [
{ no: 1, name: "null_value", kind: "enum", oneof: "kind", T: () => ["google.protobuf.NullValue", NullValue] },
{ no: 2, name: "number_value", kind: "scalar", oneof: "kind", T: 1 /*ScalarType.DOUBLE*/ },
{ no: 3, name: "string_value", kind: "scalar", oneof: "kind", T: 9 /*ScalarType.STRING*/ },
{ no: 4, name: "bool_value", kind: "scalar", oneof: "kind", T: 8 /*ScalarType.BOOL*/ },
{ no: 5, name: "struct_value", kind: "message", oneof: "kind", T: () => Struct },
{ no: 6, name: "list_value", kind: "message", oneof: "kind", T: () => ListValue }
]);
}
/**
* Encode `Value` to JSON value.
*/
internalJsonWrite(message: Value, options: JsonWriteOptions): JsonValue {
if (message.kind.oneofKind === undefined)
throw new globalThis.Error();
switch (message.kind.oneofKind) {
case undefined: throw new globalThis.Error();
case "boolValue": return message.kind.boolValue;
case "nullValue": return null;
case "numberValue": return message.kind.numberValue;
case "stringValue": return message.kind.stringValue;
case "listValue":
let listValueField = this.fields.find(f => f.no === 6);
if (listValueField?.kind !== "message")
throw new globalThis.Error();
return listValueField.T().toJson(message.kind.listValue);
case "structValue":
let structValueField = this.fields.find(f => f.no === 5);
if (structValueField?.kind !== "message")
throw new globalThis.Error();
return structValueField.T().toJson(message.kind.structValue);
}
}
/**
* Decode `Value` from JSON value.
*/
internalJsonRead(json: JsonValue, options: JsonReadOptions, target?: Value): Value {
if (!target)
target = this.create();
switch (typeof json) {
case "number":
target.kind = { oneofKind: "numberValue", numberValue: json };
break;
case "string":
target.kind = { oneofKind: "stringValue", stringValue: json };
break;
case "boolean":
target.kind = { oneofKind: "boolValue", boolValue: json };
break;
case "object":
if (json === null) {
target.kind = { oneofKind: "nullValue", nullValue: NullValue.NULL_VALUE };
}
else if (globalThis.Array.isArray(json)) {
target.kind = { oneofKind: "listValue", listValue: ListValue.fromJson(json) };
}
else {
let val = Struct.fromJson(json);
target.kind = { oneofKind: "structValue", structValue: Struct.fromJson(json) };
}
break;
default: throw new globalThis.Error("Unable to parse " + this.typeName + " from JSON " + typeofJsonValue(json));
}
return target;
}
create(value?: PartialMessage<Value>): Value {
const message = { kind: { oneofKind: undefined } };
globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
if (value !== undefined)
reflectionMergePartial<Value>(this, message, value);
return message;
}
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: Value): Value {
let message = target ?? this.create(), end = reader.pos + length;
while (reader.pos < end) {
let [fieldNo, wireType] = reader.tag();
switch (fieldNo) {
case /* google.protobuf.NullValue null_value */ 1:
message.kind = {
oneofKind: "nullValue",
nullValue: reader.int32()
};
break;
case /* double number_value */ 2:
message.kind = {
oneofKind: "numberValue",
numberValue: reader.double()
};
break;
case /* string string_value */ 3:
message.kind = {
oneofKind: "stringValue",
stringValue: reader.string()
};
break;
case /* bool bool_value */ 4:
message.kind = {
oneofKind: "boolValue",
boolValue: reader.bool()
};
break;
case /* google.protobuf.Struct struct_value */ 5:
message.kind = {
oneofKind: "structValue",
structValue: Struct.internalBinaryRead(reader, reader.uint32(), options, (message.kind as any).structValue)
};
break;
case /* google.protobuf.ListValue list_value */ 6:
message.kind = {
oneofKind: "listValue",
listValue: ListValue.internalBinaryRead(reader, reader.uint32(), options, (message.kind as any).listValue)
};
break;
default:
let u = options.readUnknownField;
if (u === "throw")
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
let d = reader.skip(wireType);
if (u !== false)
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
}
}
return message;
}
internalBinaryWrite(message: Value, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
/* google.protobuf.NullValue null_value = 1; */
if (message.kind.oneofKind === "nullValue")
writer.tag(1, WireType.Varint).int32(message.kind.nullValue);
/* double number_value = 2; */
if (message.kind.oneofKind === "numberValue")
writer.tag(2, WireType.Bit64).double(message.kind.numberValue);
/* string string_value = 3; */
if (message.kind.oneofKind === "stringValue")
writer.tag(3, WireType.LengthDelimited).string(message.kind.stringValue);
/* bool bool_value = 4; */
if (message.kind.oneofKind === "boolValue")
writer.tag(4, WireType.Varint).bool(message.kind.boolValue);
/* google.protobuf.Struct struct_value = 5; */
if (message.kind.oneofKind === "structValue")
Struct.internalBinaryWrite(message.kind.structValue, writer.tag(5, WireType.LengthDelimited).fork(), options).join();
/* google.protobuf.ListValue list_value = 6; */
if (message.kind.oneofKind === "listValue")
ListValue.internalBinaryWrite(message.kind.listValue, writer.tag(6, WireType.LengthDelimited).fork(), options).join();
let u = options.writeUnknownFields;
if (u !== false)
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
return writer;
}
}
/**
* @generated MessageType for protobuf message google.protobuf.Value
*/
export const Value = new Value$Type();
// @generated message type with reflection information, may provide speed optimized methods
class ListValue$Type extends MessageType<ListValue> {
constructor() {
super("google.protobuf.ListValue", [
{ no: 1, name: "values", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => Value }
]);
}
/**
* Encode `ListValue` to JSON array.
*/
internalJsonWrite(message: ListValue, options: JsonWriteOptions): JsonValue {
return message.values.map(v => Value.toJson(v));
}
/**
* Decode `ListValue` from JSON array.
*/
internalJsonRead(json: JsonValue, options: JsonReadOptions, target?: ListValue): ListValue {
if (!globalThis.Array.isArray(json))
throw new globalThis.Error("Unable to parse " + this.typeName + " from JSON " + typeofJsonValue(json));
if (!target)
target = this.create();
let values = json.map(v => Value.fromJson(v));
target.values.push(...values);
return target;
}
create(value?: PartialMessage<ListValue>): ListValue {
const message = { values: [] };
globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
if (value !== undefined)
reflectionMergePartial<ListValue>(this, message, value);
return message;
}
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: ListValue): ListValue {
let message = target ?? this.create(), end = reader.pos + length;
while (reader.pos < end) {
let [fieldNo, wireType] = reader.tag();
switch (fieldNo) {
case /* repeated google.protobuf.Value values */ 1:
message.values.push(Value.internalBinaryRead(reader, reader.uint32(), options));
break;
default:
let u = options.readUnknownField;
if (u === "throw")
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
let d = reader.skip(wireType);
if (u !== false)
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
}
}
return message;
}
internalBinaryWrite(message: ListValue, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
/* repeated google.protobuf.Value values = 1; */
for (let i = 0; i < message.values.length; i++)
Value.internalBinaryWrite(message.values[i], writer.tag(1, WireType.LengthDelimited).fork(), options).join();
let u = options.writeUnknownFields;
if (u !== false)
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
return writer;
}
}
/**
* @generated MessageType for protobuf message google.protobuf.ListValue
*/
export const ListValue = new ListValue$Type();

View File

@@ -1,178 +0,0 @@
// @generated by protobuf-ts 2.8.2
// @generated from protobuf file "project.proto" (package "gooseai", syntax proto3)
// tslint:disable
import type { RpcTransport } from "@protobuf-ts/runtime-rpc";
import type { ServiceInfo } from "@protobuf-ts/runtime-rpc";
import { ProjectService } from "./project";
import type { DeleteAssetsResponse } from "./project";
import type { DeleteAssetsRequest } from "./project";
import type { QueryAssetsResponse } from "./project";
import type { QueryAssetsRequest } from "./project";
import type { UntagAssetsResponse } from "./project";
import type { UntagAssetsRequest } from "./project";
import type { TagAssetsResponse } from "./project";
import type { TagAssetsRequest } from "./project";
import type { DeleteProjectRequest } from "./project";
import type { GetProjectRequest } from "./project";
import type { ListProjectRequest } from "./project";
import type { ServerStreamingCall } from "@protobuf-ts/runtime-rpc";
import type { UpdateProjectRequest } from "./project";
import { stackIntercept } from "@protobuf-ts/runtime-rpc";
import type { Project } from "./project";
import type { CreateProjectRequest } from "./project";
import type { UnaryCall } from "@protobuf-ts/runtime-rpc";
import type { RpcOptions } from "@protobuf-ts/runtime-rpc";
/**
*
* gRPC services
*
*
* @generated from protobuf service gooseai.ProjectService
*/
export interface IProjectServiceClient {
/**
* Create a new project if it does not exist
*
* @generated from protobuf rpc: Create(gooseai.CreateProjectRequest) returns (gooseai.Project);
*/
create(input: CreateProjectRequest, options?: RpcOptions): UnaryCall<CreateProjectRequest, Project>;
/**
* Update an existing project
*
* @generated from protobuf rpc: Update(gooseai.UpdateProjectRequest) returns (gooseai.Project);
*/
update(input: UpdateProjectRequest, options?: RpcOptions): UnaryCall<UpdateProjectRequest, Project>;
/**
* List all the projects for an organization
*
* @generated from protobuf rpc: List(gooseai.ListProjectRequest) returns (stream gooseai.Project);
*/
list(input: ListProjectRequest, options?: RpcOptions): ServerStreamingCall<ListProjectRequest, Project>;
/**
* Get a project
*
* @generated from protobuf rpc: Get(gooseai.GetProjectRequest) returns (gooseai.Project);
*/
get(input: GetProjectRequest, options?: RpcOptions): UnaryCall<GetProjectRequest, Project>;
/**
* Delete a project
*
* @generated from protobuf rpc: Delete(gooseai.DeleteProjectRequest) returns (gooseai.Project);
*/
delete(input: DeleteProjectRequest, options?: RpcOptions): UnaryCall<DeleteProjectRequest, Project>;
/**
* Add or remove tags from an asset
*
* @generated from protobuf rpc: TagAssets(gooseai.TagAssetsRequest) returns (gooseai.TagAssetsResponse);
*/
tagAssets(input: TagAssetsRequest, options?: RpcOptions): UnaryCall<TagAssetsRequest, TagAssetsResponse>;
/**
* @generated from protobuf rpc: UntagAssets(gooseai.UntagAssetsRequest) returns (gooseai.UntagAssetsResponse);
*/
untagAssets(input: UntagAssetsRequest, options?: RpcOptions): UnaryCall<UntagAssetsRequest, UntagAssetsResponse>;
/**
* Query the assets of a project, with additional filtering
*
* @generated from protobuf rpc: QueryAssets(gooseai.QueryAssetsRequest) returns (gooseai.QueryAssetsResponse);
*/
queryAssets(input: QueryAssetsRequest, options?: RpcOptions): UnaryCall<QueryAssetsRequest, QueryAssetsResponse>;
/**
* Delete one or more assets of a project
*
* @generated from protobuf rpc: DeleteAssets(gooseai.DeleteAssetsRequest) returns (gooseai.DeleteAssetsResponse);
*/
deleteAssets(input: DeleteAssetsRequest, options?: RpcOptions): UnaryCall<DeleteAssetsRequest, DeleteAssetsResponse>;
}
/**
*
* gRPC services
*
*
* @generated from protobuf service gooseai.ProjectService
*/
export class ProjectServiceClient implements IProjectServiceClient, ServiceInfo {
typeName = ProjectService.typeName;
methods = ProjectService.methods;
options = ProjectService.options;
constructor(private readonly _transport: RpcTransport) {
}
/**
* Create a new project if it does not exist
*
* @generated from protobuf rpc: Create(gooseai.CreateProjectRequest) returns (gooseai.Project);
*/
create(input: CreateProjectRequest, options?: RpcOptions): UnaryCall<CreateProjectRequest, Project> {
const method = this.methods[0], opt = this._transport.mergeOptions(options);
return stackIntercept<CreateProjectRequest, Project>("unary", this._transport, method, opt, input);
}
/**
* Update an existing project
*
* @generated from protobuf rpc: Update(gooseai.UpdateProjectRequest) returns (gooseai.Project);
*/
update(input: UpdateProjectRequest, options?: RpcOptions): UnaryCall<UpdateProjectRequest, Project> {
const method = this.methods[1], opt = this._transport.mergeOptions(options);
return stackIntercept<UpdateProjectRequest, Project>("unary", this._transport, method, opt, input);
}
/**
* List all the projects for an organization
*
* @generated from protobuf rpc: List(gooseai.ListProjectRequest) returns (stream gooseai.Project);
*/
list(input: ListProjectRequest, options?: RpcOptions): ServerStreamingCall<ListProjectRequest, Project> {
const method = this.methods[2], opt = this._transport.mergeOptions(options);
return stackIntercept<ListProjectRequest, Project>("serverStreaming", this._transport, method, opt, input);
}
/**
* Get a project
*
* @generated from protobuf rpc: Get(gooseai.GetProjectRequest) returns (gooseai.Project);
*/
get(input: GetProjectRequest, options?: RpcOptions): UnaryCall<GetProjectRequest, Project> {
const method = this.methods[3], opt = this._transport.mergeOptions(options);
return stackIntercept<GetProjectRequest, Project>("unary", this._transport, method, opt, input);
}
/**
* Delete a project
*
* @generated from protobuf rpc: Delete(gooseai.DeleteProjectRequest) returns (gooseai.Project);
*/
delete(input: DeleteProjectRequest, options?: RpcOptions): UnaryCall<DeleteProjectRequest, Project> {
const method = this.methods[4], opt = this._transport.mergeOptions(options);
return stackIntercept<DeleteProjectRequest, Project>("unary", this._transport, method, opt, input);
}
/**
* Add or remove tags from an asset
*
* @generated from protobuf rpc: TagAssets(gooseai.TagAssetsRequest) returns (gooseai.TagAssetsResponse);
*/
tagAssets(input: TagAssetsRequest, options?: RpcOptions): UnaryCall<TagAssetsRequest, TagAssetsResponse> {
const method = this.methods[5], opt = this._transport.mergeOptions(options);
return stackIntercept<TagAssetsRequest, TagAssetsResponse>("unary", this._transport, method, opt, input);
}
/**
* @generated from protobuf rpc: UntagAssets(gooseai.UntagAssetsRequest) returns (gooseai.UntagAssetsResponse);
*/
untagAssets(input: UntagAssetsRequest, options?: RpcOptions): UnaryCall<UntagAssetsRequest, UntagAssetsResponse> {
const method = this.methods[6], opt = this._transport.mergeOptions(options);
return stackIntercept<UntagAssetsRequest, UntagAssetsResponse>("unary", this._transport, method, opt, input);
}
/**
* Query the assets of a project, with additional filtering
*
* @generated from protobuf rpc: QueryAssets(gooseai.QueryAssetsRequest) returns (gooseai.QueryAssetsResponse);
*/
queryAssets(input: QueryAssetsRequest, options?: RpcOptions): UnaryCall<QueryAssetsRequest, QueryAssetsResponse> {
const method = this.methods[7], opt = this._transport.mergeOptions(options);
return stackIntercept<QueryAssetsRequest, QueryAssetsResponse>("unary", this._transport, method, opt, input);
}
/**
* Delete one or more assets of a project
*
* @generated from protobuf rpc: DeleteAssets(gooseai.DeleteAssetsRequest) returns (gooseai.DeleteAssetsResponse);
*/
deleteAssets(input: DeleteAssetsRequest, options?: RpcOptions): UnaryCall<DeleteAssetsRequest, DeleteAssetsResponse> {
const method = this.methods[8], opt = this._transport.mergeOptions(options);
return stackIntercept<DeleteAssetsRequest, DeleteAssetsResponse>("unary", this._transport, method, opt, input);
}
}

View File

@@ -1,436 +0,0 @@
// @generated by protobuf-ts 2.8.2
// @generated from protobuf file "tensors.proto" (package "tensors", syntax proto3)
// tslint:disable
import type { BinaryWriteOptions } from "@protobuf-ts/runtime";
import type { IBinaryWriter } from "@protobuf-ts/runtime";
import type { BinaryReadOptions } from "@protobuf-ts/runtime";
import type { IBinaryReader } from "@protobuf-ts/runtime";
import { UnknownFieldHandler } from "@protobuf-ts/runtime";
import { WireType } from "@protobuf-ts/runtime";
import type { PartialMessage } from "@protobuf-ts/runtime";
import { reflectionMergePartial } from "@protobuf-ts/runtime";
import { MESSAGE_TYPE } from "@protobuf-ts/runtime";
import { MessageType } from "@protobuf-ts/runtime";
/**
* @generated from protobuf message tensors.Tensor
*/
export interface Tensor {
/**
* @generated from protobuf field: tensors.Dtype dtype = 1;
*/
dtype: Dtype;
/**
* @generated from protobuf field: repeated int64 shape = 2;
*/
shape: bigint[];
/**
* @generated from protobuf field: bytes data = 3;
*/
data: Uint8Array;
/**
* @generated from protobuf field: optional tensors.AttributeType attr_type = 4;
*/
attrType?: AttributeType;
}
/**
* @generated from protobuf message tensors.Attribute
*/
export interface Attribute {
/**
* @generated from protobuf field: string name = 1;
*/
name: string;
/**
* @generated from protobuf oneof: value
*/
value: {
oneofKind: "module";
/**
* @generated from protobuf field: tensors.Module module = 3;
*/
module: Module;
} | {
oneofKind: "tensor";
/**
* @generated from protobuf field: tensors.Tensor tensor = 4;
*/
tensor: Tensor;
} | {
oneofKind: "string";
/**
* @generated from protobuf field: string string = 5;
*/
string: string;
} | {
oneofKind: "int64";
/**
* @generated from protobuf field: int64 int64 = 6;
*/
int64: bigint;
} | {
oneofKind: "float";
/**
* @generated from protobuf field: float float = 7;
*/
float: number;
} | {
oneofKind: "bool";
/**
* @generated from protobuf field: bool bool = 8;
*/
bool: boolean;
} | {
oneofKind: undefined;
};
}
/**
* @generated from protobuf message tensors.Module
*/
export interface Module {
/**
* @generated from protobuf field: string name = 1;
*/
name: string;
/**
* @generated from protobuf field: repeated string names = 2;
*/
names: string[];
/**
* @generated from protobuf field: repeated tensors.Attribute attributes = 3;
*/
attributes: Attribute[];
}
/**
* @generated from protobuf enum tensors.Dtype
*/
export enum Dtype {
/**
* @generated from protobuf enum value: DT_INVALID = 0;
*/
DT_INVALID = 0,
/**
* @generated from protobuf enum value: DT_FLOAT32 = 1;
*/
DT_FLOAT32 = 1,
/**
* @generated from protobuf enum value: DT_FLOAT64 = 2;
*/
DT_FLOAT64 = 2,
/**
* @generated from protobuf enum value: DT_FLOAT16 = 3;
*/
DT_FLOAT16 = 3,
/**
* @generated from protobuf enum value: DT_BFLOAT16 = 4;
*/
DT_BFLOAT16 = 4,
/**
* @generated from protobuf enum value: DT_COMPLEX32 = 5;
*/
DT_COMPLEX32 = 5,
/**
* @generated from protobuf enum value: DT_COMPLEX64 = 6;
*/
DT_COMPLEX64 = 6,
/**
* @generated from protobuf enum value: DT_COMPLEX128 = 7;
*/
DT_COMPLEX128 = 7,
/**
* @generated from protobuf enum value: DT_UINT8 = 8;
*/
DT_UINT8 = 8,
/**
* @generated from protobuf enum value: DT_INT8 = 9;
*/
DT_INT8 = 9,
/**
* @generated from protobuf enum value: DT_INT16 = 10;
*/
DT_INT16 = 10,
/**
* @generated from protobuf enum value: DT_INT32 = 11;
*/
DT_INT32 = 11,
/**
* @generated from protobuf enum value: DT_INT64 = 12;
*/
DT_INT64 = 12,
/**
* @generated from protobuf enum value: DT_BOOL = 13;
*/
DT_BOOL = 13,
/**
* @generated from protobuf enum value: DT_QUINT8 = 14;
*/
DT_QUINT8 = 14,
/**
* @generated from protobuf enum value: DT_QINT8 = 15;
*/
DT_QINT8 = 15,
/**
* @generated from protobuf enum value: DT_QINT32 = 16;
*/
DT_QINT32 = 16,
/**
* @generated from protobuf enum value: DT_QUINT4_2 = 17;
*/
DT_QUINT4_2 = 17
}
/**
* @generated from protobuf enum tensors.AttributeType
*/
export enum AttributeType {
/**
* @generated from protobuf enum value: AT_PARAMETER = 0;
*/
AT_PARAMETER = 0,
/**
* @generated from protobuf enum value: AT_BUFFER = 1;
*/
AT_BUFFER = 1
}
// @generated message type with reflection information, may provide speed optimized methods
class Tensor$Type extends MessageType<Tensor> {
constructor() {
super("tensors.Tensor", [
{ no: 1, name: "dtype", kind: "enum", T: () => ["tensors.Dtype", Dtype] },
{ no: 2, name: "shape", kind: "scalar", repeat: 1 /*RepeatType.PACKED*/, T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ },
{ no: 3, name: "data", kind: "scalar", T: 12 /*ScalarType.BYTES*/ },
{ no: 4, name: "attr_type", kind: "enum", opt: true, T: () => ["tensors.AttributeType", AttributeType] }
]);
}
create(value?: PartialMessage<Tensor>): Tensor {
const message = { dtype: 0, shape: [], data: new Uint8Array(0) };
globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
if (value !== undefined)
reflectionMergePartial<Tensor>(this, message, value);
return message;
}
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: Tensor): Tensor {
let message = target ?? this.create(), end = reader.pos + length;
while (reader.pos < end) {
let [fieldNo, wireType] = reader.tag();
switch (fieldNo) {
case /* tensors.Dtype dtype */ 1:
message.dtype = reader.int32();
break;
case /* repeated int64 shape */ 2:
if (wireType === WireType.LengthDelimited)
for (let e = reader.int32() + reader.pos; reader.pos < e;)
message.shape.push(reader.int64().toBigInt());
else
message.shape.push(reader.int64().toBigInt());
break;
case /* bytes data */ 3:
message.data = reader.bytes();
break;
case /* optional tensors.AttributeType attr_type */ 4:
message.attrType = reader.int32();
break;
default:
let u = options.readUnknownField;
if (u === "throw")
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
let d = reader.skip(wireType);
if (u !== false)
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
}
}
return message;
}
internalBinaryWrite(message: Tensor, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
/* tensors.Dtype dtype = 1; */
if (message.dtype !== 0)
writer.tag(1, WireType.Varint).int32(message.dtype);
/* repeated int64 shape = 2; */
if (message.shape.length) {
writer.tag(2, WireType.LengthDelimited).fork();
for (let i = 0; i < message.shape.length; i++)
writer.int64(message.shape[i]);
writer.join();
}
/* bytes data = 3; */
if (message.data.length)
writer.tag(3, WireType.LengthDelimited).bytes(message.data);
/* optional tensors.AttributeType attr_type = 4; */
if (message.attrType !== undefined)
writer.tag(4, WireType.Varint).int32(message.attrType);
let u = options.writeUnknownFields;
if (u !== false)
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
return writer;
}
}
/**
* @generated MessageType for protobuf message tensors.Tensor
*/
export const Tensor = new Tensor$Type();
// @generated message type with reflection information, may provide speed optimized methods
class Attribute$Type extends MessageType<Attribute> {
constructor() {
super("tensors.Attribute", [
{ no: 1, name: "name", kind: "scalar", T: 9 /*ScalarType.STRING*/ },
{ no: 3, name: "module", kind: "message", oneof: "value", T: () => Module },
{ no: 4, name: "tensor", kind: "message", oneof: "value", T: () => Tensor },
{ no: 5, name: "string", kind: "scalar", oneof: "value", T: 9 /*ScalarType.STRING*/ },
{ no: 6, name: "int64", kind: "scalar", oneof: "value", T: 3 /*ScalarType.INT64*/, L: 0 /*LongType.BIGINT*/ },
{ no: 7, name: "float", kind: "scalar", oneof: "value", T: 2 /*ScalarType.FLOAT*/ },
{ no: 8, name: "bool", kind: "scalar", oneof: "value", T: 8 /*ScalarType.BOOL*/ }
]);
}
create(value?: PartialMessage<Attribute>): Attribute {
const message = { name: "", value: { oneofKind: undefined } };
globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
if (value !== undefined)
reflectionMergePartial<Attribute>(this, message, value);
return message;
}
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: Attribute): Attribute {
let message = target ?? this.create(), end = reader.pos + length;
while (reader.pos < end) {
let [fieldNo, wireType] = reader.tag();
switch (fieldNo) {
case /* string name */ 1:
message.name = reader.string();
break;
case /* tensors.Module module */ 3:
message.value = {
oneofKind: "module",
module: Module.internalBinaryRead(reader, reader.uint32(), options, (message.value as any).module)
};
break;
case /* tensors.Tensor tensor */ 4:
message.value = {
oneofKind: "tensor",
tensor: Tensor.internalBinaryRead(reader, reader.uint32(), options, (message.value as any).tensor)
};
break;
case /* string string */ 5:
message.value = {
oneofKind: "string",
string: reader.string()
};
break;
case /* int64 int64 */ 6:
message.value = {
oneofKind: "int64",
int64: reader.int64().toBigInt()
};
break;
case /* float float */ 7:
message.value = {
oneofKind: "float",
float: reader.float()
};
break;
case /* bool bool */ 8:
message.value = {
oneofKind: "bool",
bool: reader.bool()
};
break;
default:
let u = options.readUnknownField;
if (u === "throw")
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
let d = reader.skip(wireType);
if (u !== false)
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
}
}
return message;
}
internalBinaryWrite(message: Attribute, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
/* string name = 1; */
if (message.name !== "")
writer.tag(1, WireType.LengthDelimited).string(message.name);
/* tensors.Module module = 3; */
if (message.value.oneofKind === "module")
Module.internalBinaryWrite(message.value.module, writer.tag(3, WireType.LengthDelimited).fork(), options).join();
/* tensors.Tensor tensor = 4; */
if (message.value.oneofKind === "tensor")
Tensor.internalBinaryWrite(message.value.tensor, writer.tag(4, WireType.LengthDelimited).fork(), options).join();
/* string string = 5; */
if (message.value.oneofKind === "string")
writer.tag(5, WireType.LengthDelimited).string(message.value.string);
/* int64 int64 = 6; */
if (message.value.oneofKind === "int64")
writer.tag(6, WireType.Varint).int64(message.value.int64);
/* float float = 7; */
if (message.value.oneofKind === "float")
writer.tag(7, WireType.Bit32).float(message.value.float);
/* bool bool = 8; */
if (message.value.oneofKind === "bool")
writer.tag(8, WireType.Varint).bool(message.value.bool);
let u = options.writeUnknownFields;
if (u !== false)
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
return writer;
}
}
/**
* @generated MessageType for protobuf message tensors.Attribute
*/
export const Attribute = new Attribute$Type();
// @generated message type with reflection information, may provide speed optimized methods
class Module$Type extends MessageType<Module> {
constructor() {
super("tensors.Module", [
{ no: 1, name: "name", kind: "scalar", T: 9 /*ScalarType.STRING*/ },
{ no: 2, name: "names", kind: "scalar", repeat: 2 /*RepeatType.UNPACKED*/, T: 9 /*ScalarType.STRING*/ },
{ no: 3, name: "attributes", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => Attribute }
]);
}
create(value?: PartialMessage<Module>): Module {
const message = { name: "", names: [], attributes: [] };
globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
if (value !== undefined)
reflectionMergePartial<Module>(this, message, value);
return message;
}
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: Module): Module {
let message = target ?? this.create(), end = reader.pos + length;
while (reader.pos < end) {
let [fieldNo, wireType] = reader.tag();
switch (fieldNo) {
case /* string name */ 1:
message.name = reader.string();
break;
case /* repeated string names */ 2:
message.names.push(reader.string());
break;
case /* repeated tensors.Attribute attributes */ 3:
message.attributes.push(Attribute.internalBinaryRead(reader, reader.uint32(), options));
break;
default:
let u = options.readUnknownField;
if (u === "throw")
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
let d = reader.skip(wireType);
if (u !== false)
(u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
}
}
return message;
}
internalBinaryWrite(message: Module, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter {
/* string name = 1; */
if (message.name !== "")
writer.tag(1, WireType.LengthDelimited).string(message.name);
/* repeated string names = 2; */
for (let i = 0; i < message.names.length; i++)
writer.tag(2, WireType.LengthDelimited).string(message.names[i]);
/* repeated tensors.Attribute attributes = 3; */
for (let i = 0; i < message.attributes.length; i++)
Attribute.internalBinaryWrite(message.attributes[i], writer.tag(3, WireType.LengthDelimited).fork(), options).join();
let u = options.writeUnknownFields;
if (u !== false)
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
return writer;
}
}
/**
* @generated MessageType for protobuf message tensors.Module
*/
export const Module = new Module$Type();

View File

@@ -1,9 +0,0 @@
export * as Dashboard from "./Generated/dashboard";
export * from "./Generated/dashboard.client";
export * as Engines from "./Generated/engines";
export * from "./Generated/engines.client";
export * as Generation from "./Generated/generation";
export * from "./Generated/generation.client";
export * as Project from "./Generated/project";
export * from "./Generated/project.client";
export * from "./Generated/google/protobuf/struct";

View File

@@ -1,634 +0,0 @@
import { GrpcWebFetchTransport } from "@protobuf-ts/grpcweb-transport";
import { RpcError } from "@protobuf-ts/runtime-rpc";
import * as StableStudio from "@stability/stablestudio-plugin";
import {
EnginesServiceClient,
Generation,
GenerationServiceClient,
Project,
ProjectServiceClient,
Struct,
} from "./Proto";
const getStableDiffusionDefaultCount = () => 4;
const getStableDiffusionDefaultInputFromPrompt = (prompt: string) => ({
prompts: [
{
text: prompt,
weight: 1,
},
{
text: "",
weight: -0.75,
},
],
model: "stable-diffusion-xl-beta-v2-2-2",
sampler: { id: "0", name: "DDIM" },
style: "enhance",
width: 512,
height: 512,
cfgScale: 7,
steps: 50,
});
export const createPlugin = StableStudio.createPlugin<{
settings: {
apiKey: StableStudio.PluginSettingString;
};
}>(({ context, set }) => {
const functionsWhichNeedAPIKey = (
apiKey?: string
): Pick<
StableStudio.Plugin,
| "createStableDiffusionImages"
| "getStableDiffusionExistingImages"
| "getStableDiffusionModels"
| "deleteStableDiffusionImages"
| "getStatus"
| "getStableDiffusionSamplers"
> => {
if (!apiKey)
return {
createStableDiffusionImages: undefined,
getStableDiffusionExistingImages: undefined,
getStableDiffusionModels: undefined,
deleteStableDiffusionImages: undefined,
getStatus: () => ({
indicator: "error",
text: "Missing API key",
}),
};
const transport = new GrpcWebFetchTransport({
baseUrl: "https://grpc.stability.ai",
meta: {
Authorization: `Bearer ${apiKey}`,
"stability-client-id": "StableStudio",
"stability-client-version": context.getGitHash(),
},
});
const generation = new GenerationServiceClient(transport);
const engines = new EnginesServiceClient(transport);
const project = new ProjectServiceClient(transport);
return {
createStableDiffusionImages: async (options) => {
const count = options?.count ?? getStableDiffusionDefaultCount();
const defaultStableDiffusionInput =
getStableDiffusionDefaultInputFromPrompt(
context.getStableDiffusionRandomPrompt()
);
const input = {
...defaultStableDiffusionInput,
...options?.input,
};
const width = input.width ?? defaultStableDiffusionInput.width;
const height = input.height ?? defaultStableDiffusionInput.height;
const prompt =
input.prompts?.map(
({ text = context.getStableDiffusionRandomPrompt(), weight }) =>
Generation.Prompt.create({
prompt: { oneofKind: "text", text },
parameters: { weight },
})
) ?? [];
// add init and mask
if (input.maskImage?.blob) {
prompt.push(
Generation.Prompt.create({
parameters: { init: false, weight: 1 },
prompt: {
oneofKind: "artifact",
artifact: Generation.Artifact.create({
type: Generation.ArtifactType.ARTIFACT_MASK,
mime: "image/png",
data: {
oneofKind: "binary",
binary: new Uint8Array(
await input.maskImage.blob.arrayBuffer()
),
},
}),
},
})
);
}
if (input.initialImage?.blob) {
prompt.push(
Generation.Prompt.create({
parameters: { init: true, weight: input.initialImage.weight },
prompt: {
oneofKind: "artifact",
artifact: Generation.Artifact.create({
type: Generation.ArtifactType.ARTIFACT_IMAGE,
mime: "image/png",
data: {
oneofKind: "binary",
binary: new Uint8Array(
await input.initialImage.blob.arrayBuffer()
),
},
}),
},
})
);
}
console.log(input.sampler.id ? parseInt(input.sampler.id) : 0);
const imageParams = Generation.ImageParameters.create({
width: BigInt(width),
height: BigInt(height),
steps: BigInt(input.steps),
samples: BigInt(count),
seed: Array.from({ length: count }, () => input.seed ?? 0),
transform: Generation.TransformType.create({
type: {
oneofKind: "diffusion",
diffusion: input.sampler.id ? parseInt(input.sampler.id) : 0,
},
}),
parameters: [
Generation.StepParameter.create({
sampler: Generation.SamplerParameters.create({
cfgScale: input.cfgScale,
}),
scaledStep: 0,
schedule: Generation.ScheduleParameters.create({
start: input.initialImage
? 1 - (input.initialImage.weight ?? 0)
: 1,
}),
}),
],
});
const extras = (input.style || input.width !== input.height) && {
extras: Struct.fromJson({
$IPC: {
preset: input.style,
...(input.width !== input.height && { mode: "multistage" }),
},
}),
};
const request = generation.chainGenerate({
requestId: "",
stage: [
{
id: "Main",
request: Generation.Request.create({
prompt,
engineId: input.model,
requestedType: Generation.ArtifactType.ARTIFACT_IMAGE,
params: { oneofKind: "image", image: imageParams },
...extras,
}),
onStatus: [
{
target: "Asset",
reason: [],
action: [
Generation.StageAction.PASS,
Generation.StageAction.RETURN,
],
},
],
},
{
id: "Asset",
request: Generation.Request.create({
engineId: "asset-service",
params: {
oneofKind: "asset",
asset: {
projectId: "",
action: Generation.AssetAction.ASSET_PUT,
use: Generation.AssetUse.OUTPUT,
},
},
}),
onStatus: [
{ action: [Generation.StageAction.RETURN], reason: [] },
],
},
],
});
let id: string | undefined;
const images: StableStudio.StableDiffusionImage[] = [];
for await (const response of request.responses) {
for (const artifact of response.artifacts) {
if (
artifact.type === Generation.ArtifactType.ARTIFACT_TEXT &&
artifact.finishReason === Generation.FinishReason.FILTER
)
throw new RpcError("Banned word detected!", "BANNED_TERM");
if (
artifact.type === Generation.ArtifactType.ARTIFACT_IMAGE &&
artifact.data.oneofKind === "binary"
) {
id = response.requestId;
images.push({
input: {
...input,
seed: artifact.seed,
},
id: artifact.uuid,
blob: new Blob([artifact.data.binary], { type: "image/png" }),
});
}
}
}
return id ? { id, images } : undefined;
},
getStableDiffusionExistingImages: async (options) => {
const { limit, exclusiveStartImageID } = { limit: 25, ...options };
if (limit <= 0) return [];
const { response } = await project.queryAssets({
id: "",
limit: BigInt(limit),
startKey: exclusiveStartImageID,
use: [Project.ProjectAssetUse.OUTPUT],
sortDir: Project.ProjectSortDir.DESC,
tags: {},
});
type ImageWithBlobPromise = Omit<
StableStudio.StableDiffusionImage,
"blob"
> & { blob: Promise<Blob> };
type ImagesWithBlobPromises = Record<
StableStudio.ID,
Omit<StableStudio.StableDiffusionImages, "images"> & {
images: ImageWithBlobPromise[];
}
>;
const images = response.assets.reduce((previous, response) => {
if (
!response.request ||
response.request.params.oneofKind !== "image"
)
return previous;
const prompts = response.request.prompt.reduce((prompts, prompt) => {
if (
prompt.prompt.oneofKind !== "artifact" ||
prompt.prompt.artifact.data.oneofKind !== "text"
)
return prompts;
return [
...prompts,
{
text: prompt.prompt.artifact.data.text,
weight: prompt.parameters?.weight ?? 1,
},
];
}, [] as StableStudio.StableDiffusionPrompt[]);
if (prompts.length === 0) return previous;
const id = response.request.requestId.split(":")[0];
if (!id) return previous;
const imageID = response.id;
const createdAt = new Date(Number(response.createdAt) * 1000);
const model = response.request.engineId;
const style = parseExtras(response.request.extras?.fields).$IPC
?.preset;
const width = response.request.params.image.width
? Number(response.request.params.image.width)
: undefined;
const height = response.request.params.image.height
? Number(response.request.params.image.height)
: undefined;
const cfgScale = response.request.params.image.parameters.reduce(
(_, parameters) =>
parameters.sampler?.cfgScale
? Number(parameters.sampler.cfgScale)
: undefined,
undefined as number | undefined
);
const steps = response.request.params.image.steps
? Number(response.request.params.image.steps)
: undefined;
const seed = response.request.params.image.seed[0]
? Number(response.request.params.image.seed[0])
: undefined;
const input: StableStudio.StableDiffusionInput = {
prompts,
model,
style,
width,
height,
cfgScale,
steps,
seed,
};
const src = response.uri
?.replace(
"https://object.lga1.coreweave.com/stability-staging-assets",
"https://staging-cdn.stability.ai/assets"
)
?.replace(
"https://object.lga1.coreweave.com/stability-assets",
"https://cdn.stability.ai/assets"
);
const image = {
id: imageID,
createdAt,
input,
blob: fetch(src).then((response) => response.blob()),
};
return {
...previous,
[id]: {
...previous[id],
...(exclusiveStartImageID === imageID && {
exclusiveStartImageID: imageID,
}),
images: [...(previous[id]?.images ?? []), image],
id: id,
},
};
}, {} as ImagesWithBlobPromises);
return Promise.all(
Object.values(images).map(async ({ id, images }) => ({
id,
images: await Promise.all(
images?.map(async ({ blob, ...image }) => ({
...image,
blob: await blob,
}))
),
exclusiveStartImageID: images?.[images.length - 1]?.id,
}))
);
},
getStableDiffusionModels: async () => {
const request = await engines.listEngines({});
const allEngines = await request.response.engine;
return allEngines.filter((engine) => engine.type === 1 && engine.ready);
},
deleteStableDiffusionImages: async (options) => {
const imageIDs = options?.imageIDs;
imageIDs &&
(await project.deleteAssets({ id: "", assetIds: imageIDs }));
},
getStatus: () => ({
indicator: "success",
text: "Ready",
}),
};
};
return {
...functionsWhichNeedAPIKey(
localStorage.getItem("stability-apiKey") ?? undefined
),
getStableDiffusionSamplers: () => [
{ id: "0", name: "DDIM" },
{ id: "1", name: "DDPM" },
{ id: "2", name: "K Euler" },
{ id: "3", name: "K Euler Ancestral" },
{ id: "4", name: "K Heun" },
{ id: "5", name: "K DPM 2" },
{ id: "6", name: "K DPM 2 Ancestral" },
{ id: "7", name: "K LMS" },
{ id: "8", name: "K DPM++ 2S Ancestral" },
{ id: "9", name: "K DPM++ 2M" },
{ id: "10", name: "K DPM++ SDE" },
],
getStableDiffusionStyles: () => [
{
id: "enhance",
name: "Enhance",
image: "https://dreamstudio.ai/presets/enhance.png",
},
{
id: "anime",
name: "Anime",
image: "https://dreamstudio.ai/presets/anime.png",
},
{
id: "photographic",
name: "Photographic",
image: "https://dreamstudio.ai/presets/photographic.png",
},
{
id: "digital-art",
name: "Digital art",
image: "https://dreamstudio.ai/presets/digital-art.png",
},
{
id: "comic-book",
name: "Comic book",
image: "https://dreamstudio.ai/presets/comic-book.png",
},
{
id: "fantasy-art",
name: "Fantasy art",
image: "https://dreamstudio.ai/presets/fantasy-art.png",
},
{
id: "analog-film",
name: "Analog film",
image: "https://dreamstudio.ai/presets/analog-film.png",
},
{
id: "neon-punk",
name: "Neon punk",
image: "https://dreamstudio.ai/presets/neon-punk.png",
},
{
id: "isometric",
name: "Isometric",
image: "https://dreamstudio.ai/presets/isometric.png",
},
{
id: "low-poly",
name: "Low poly",
image: "https://dreamstudio.ai/presets/low-poly.png",
},
{
id: "origami",
name: "Origami",
image: "https://dreamstudio.ai/presets/origami.png",
},
{
id: "line-art",
name: "Line art",
image: "https://dreamstudio.ai/presets/line-art.png",
},
{
id: "modeling-compound",
name: "Craft clay",
image: "https://dreamstudio.ai/presets/modeling-compound.png",
},
{
id: "cinematic",
name: "Cinematic",
image: "https://dreamstudio.ai/presets/cinematic.png",
},
{
id: "3d-model",
name: "3D model",
image: "https://dreamstudio.ai/presets/3d-model.png",
},
{
id: "pixel-art",
name: "Pixel art",
image: "https://dreamstudio.ai/presets/pixel-art.png",
},
],
getStableDiffusionDefaultCount,
getStableDiffusionDefaultInput: () =>
getStableDiffusionDefaultInputFromPrompt(
context.getStableDiffusionRandomPrompt()
),
settings: {
apiKey: {
type: "string",
title: "API key",
description:
"You can find your Stability API key at https://dreamstudio.ai/account",
placeholder: "sk-...",
required: true,
password: true,
value: localStorage.getItem("stability-apiKey") ?? "",
},
},
setSetting: (key, value) => {
set(({ settings }) => ({
settings: {
...settings,
[key]: { ...settings[key], value: value as string },
},
}));
if (key === "apiKey" && typeof value === "string") {
localStorage.setItem("stability-apiKey", value);
set((plugin) => ({ ...plugin, ...functionsWhichNeedAPIKey(value) }));
}
},
manifest: {
author: "Stability AI",
description: markdownDescription,
name: "Stability AI",
license: "MIT",
link: "https://stability.ai",
version: "0.0.0",
icon: "https://stability.ai/favicon.ico",
},
};
});
function parseExtras(extras: any): any | undefined {
if (!extras) return undefined;
if (extras.kind?.oneofKind === "structValue") {
return parseExtras(extras.kind.structValue.fields);
} else if (extras.kind?.oneofKind === "listValue") {
return extras.listValue.values.map(parseExtras);
} else if (extras.kind?.oneofKind === "numberValue") {
return Number(extras.kind.numberValue);
} else if (extras.kind?.oneofKind === "stringValue") {
return extras.kind.stringValue;
} else if (extras.kind?.oneofKind === "boolValue") {
return extras.kind.boolValue;
} else if (extras.kind?.oneofKind === undefined) {
return {
...Object.keys(extras).reduce((previous, key) => {
return { ...previous, [key]: parseExtras(extras[key]) };
}, {}),
};
}
return undefined;
}
const markdownDescription = `
# Welcome to StableStudio!
## [📖 README](https://github.com/Stability-AI/StableStudio) · [🎮 Discord](https://discord.com/channels/1002292111942635562/1108055793674227782) · [🌈 DreamStudio](https://dreamstudio.ai) · [💬 Discussion](https://github.com/Stability-AI/StableStudio/discussions)
# Setup
To get started, you'll need to sign up for a [DreamStudio](https://dreamstudio.ai) account.
Once you're logged in, head to the [account page](https://dreamstudio.ai/account).
You should see a section called \`API keys\`...
![](/media/api_keys_screenshot.png)
If you don't already have a key, you can create one via the plus button...
![](/media/create_api_key_screenshot.png)
You can copy your API key by clicking the copy button...
![](/media/copy_api_key_screenshot.png)
You'll be asked to accept the terms of service.
Now, paste the key into the field below...
The plugin status should change to \`Ready\` once everything is working.
` as const;

View File

@@ -1,21 +0,0 @@
MIT License
Copyright (c) 2023 Stability AI
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -1,39 +0,0 @@
{
"name": "@stability/stablestudio-plugin-webgpu",
"version": "0.0.0",
"license": "MIT",
"main": "./lib/index.js",
"types": "./lib/index.d.ts",
"files": [
"lib"
],
"scripts": {
"clean": "rimraf lib && rimraf node_modules",
"build:types": "ttsc --project tsconfig.json",
"build:javascript": "tsx scripts/Build.ts",
"build": "yarn build:types && yarn build:javascript",
"dev": "nodemon --watch src --ext ts,tsx,json --exec \"yarn build\""
},
"dependencies": {
"@stability/stablestudio-plugin": "workspace:^"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^5.33.1",
"@typescript-eslint/parser": "^5.33.1",
"eslint": "8.22.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-markdown": "^3.0.0",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-react": "^7.30.1",
"eslint-plugin-react-hooks": "^4.6.0",
"nodemon": "^2.0.20",
"prettier": "^2.7.1",
"rimraf": "^3.0.2",
"ts-node": "^10.9.1",
"tsx": "^3.12.1",
"ttypescript": "^1.5.13",
"typescript": "4.8.4",
"typescript-transform-paths": "^3.4.4"
}
}

View File

@@ -1,21 +0,0 @@
import * as ESBuild from "esbuild";
const main = async () => {
try {
await ESBuild.build({
entryPoints: ["src/index.ts"],
outdir: "lib",
bundle: true,
sourcemap: true,
minify: true,
splitting: true,
format: "esm",
target: ["esnext"],
});
} catch (error) {
console.error(error);
process.exit(1);
}
};
main();

View File

@@ -1,3 +0,0 @@
import * as StableStudio from "@stability/stablestudio-plugin";
export const createPlugin = StableStudio.createPlugin(() => ({}));

View File

@@ -1,21 +0,0 @@
{
"extends": "../../tsconfig.json",
"include": ["src/**/*"],
"exclude": ["node_modules"],
"compilerOptions": {
"emitDeclarationOnly": true,
"declaration": true,
"noUncheckedIndexedAccess": false,
"outDir": "./lib",
"baseUrl": "./",
"paths": {
"~/*": ["./src/*"]
},
"plugins": [
{ "transform": "typescript-transform-paths" },
{ "transform": "typescript-transform-paths", "afterDeclarations": true }
]
}
}

View File

@@ -1 +0,0 @@
{ "extends": ["../../.eslintrc.json"] }

View File

@@ -1 +0,0 @@
lib

View File

@@ -1,21 +0,0 @@
MIT License
Copyright (c) 2023 Stability AI
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -1,67 +0,0 @@
<div align="center">
# 🔌 [`stable-diffusion-webui`](https://github.com/AUTOMATIC1111/stable-diffusion-webui) Plugin
**🗺 Contents [ About](#about) · [⚙️ Usage](#usage) · [⭐️ Features](#features)**
**[⬆️ Top-Level README](../../README.md)**
![Electric1111](../../misc/Electric1111.png)
</div>
# <a id="about" href="#about"> About</a>
This plugin enables StableStudio to run using [`stable-diffusion-webui`](https://github.com/AUTOMATIC1111/stable-diffusion-webui), which means you can generate images entirely on your own machine!
Thanks goes to [Terry Jia](https://github.com/jtydhr88) for the original work on this plugin.
# <a id="usage" href="#usage">⚙️ Usage</a>
1. First, you'll need to configure your local installation of `stable-diffusion-webui` to run without the UI and with CORS enabled.
**Windows**
Edit the command line arguments within `webui-user.bat`:
```
set COMMANDLINE_ARGS=--nowebui --cors-allow-origins=http://localhost:3000
```
**Mac**
Edit the command line arguments within `webui-macos-env.sh`:
```
export COMMANDLINE_ARGS="--nowebui --cors-allow-origins=http://localhost:3000"
```
2. Start `stable-diffusion-webui` and look for `INFO: Uvicorn running on http://127.0.0.1:7861`.
You can make sure everything is running correctly by checking to see if [`http://127.0.0.1:7861/docs`](http://127.0.0.1:7861/docs) displays API documentation.
3. Within your installation of StableStudio, run `yarn dev:use-webui-plugin`.
_**That's it!**_ 🎉 You should now be able to generate images using your local machine.
## <a id="image-history" href="#image-history">💾 Image History</a>
To persist your image history, you'll need to install the [`sd-webui-StableStudio`](https://github.com/jtydhr88/sd-webui-StableStudio) extension for `stable-diffusion-webui`.
> 🛑 Be wary installing third-party extensions for `stable-diffusion-webui`, it's always a good idea to check before running untrusted code.
# <a id="features" href="#features">⭐️ Features</a>
Missing something? Please [let us know](https://github.com/Stability-AI/StableStudio/issues/new/choose)!
- [x] Text-to-image
- [x] Image-to-image
- [x] Basic features (prompt, negative prompt, steps, batch size, image size)
- [x] Model selection
- [x] Sampler selection
- [x] Masking, in-painting, and out-painting
- [x] Settings storage
- [x] Accurate plugin status
- [x] [Loading existing images]("#image-history)
- [x] Upscaling
- [ ] Lora support

View File

@@ -1,21 +0,0 @@
import * as ESBuild from "esbuild";
const main = async () => {
try {
await ESBuild.build({
entryPoints: ["src/index.ts"],
outdir: "lib",
bundle: true,
sourcemap: true,
minify: true,
splitting: true,
format: "esm",
target: ["esnext"],
});
} catch (error) {
console.error(error);
process.exit(1);
}
};
main();

View File

@@ -1,184 +0,0 @@
import { StableDiffusionInput } from "@stability/stablestudio-plugin";
export function base64ToBlob(base64: string, contentType = ""): Promise<Blob> {
return fetch(`data:${contentType};base64,${base64}`).then((res) =>
res.blob()
);
}
export function blobToBase64(blob: Blob): Promise<string> {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onloadend = () => resolve(reader.result as string);
reader.onerror = reject;
reader.readAsDataURL(blob);
});
}
export async function fetchOptions(baseUrl: string | undefined) {
const optionsResponse = await fetch(`${baseUrl}/sdapi/v1/options`, {
method: "GET",
headers: {
"Content-Type": "application/json",
},
});
return await optionsResponse.json();
}
export async function setOptions(baseUrl: string | undefined, options: any) {
const optionsResponse = await fetch(`${baseUrl}/sdapi/v1/options`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(options),
});
return await optionsResponse.json();
}
export async function getImageInfo(
baseUrl: string | undefined,
base64image: any
) {
const imageInfoResponse = await fetch(`${baseUrl}/sdapi/v1/png-info`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ image: base64image }),
});
const imageInfoJson = await imageInfoResponse.json();
const info = imageInfoJson.info.split("\n");
const data: any = {};
if (info.length === 0) {
return data;
}
data.prompt = info[0];
let detailIndex = 1;
if (info.length === 3) {
data.nagtivePrompt = info[1].split(":")[1].trim();
detailIndex = 2;
}
const details = info[detailIndex].split(",");
details.map((detail: any) => {
const detailInfo = detail.trim().split(":");
data[detailInfo[0]] = detailInfo[1].trim();
});
return data;
}
export async function testForHistoryPlugin(webuiHostUrl: string) {
// timeout after 1 second
const finished = Promise.race([
fetch(`${webuiHostUrl}/StableStudio/get-generated-images`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
limit: 1,
}),
}),
new Promise((_, reject) =>
setTimeout(() => reject(new Error("Request timed out")), 1000)
),
]);
try {
await finished;
return (finished as any).ok;
} catch (error) {
return false;
}
}
export async function constructPayload(
options: {
input?: StableDiffusionInput | undefined;
count?: number | undefined;
},
isUpscale = false,
upscaler: string | undefined
) {
const { sampler, prompts, initialImage, maskImage, width, height, steps } =
options?.input ?? {};
// Construct payload
const data: any = {
seed: options?.input?.seed === 0 ? -1 : options?.input?.seed,
cfgScale: options?.input?.cfgScale ?? 7,
};
if (isUpscale) {
/*
Upscaling values
*/
data.upscaling_resize_w = width ?? 512;
data.upscaling_resize_h = height ?? 512;
data.upscaler_1 = upscaler;
} else {
/*
regular image generation values
*/
data.width = width ?? 512;
data.height = height ?? 512;
data.sampler_name = sampler?.name ?? "";
data.sampler_index = sampler?.name ?? "";
data.prompt =
prompts?.find((p) => (p.text && (p.weight ?? 0) > 0) ?? 0 > 0)?.text ??
"";
data.negative_prompt =
prompts?.find((p) => (p.text && (p.weight ?? 0) < 0) ?? 0 < 0)?.text ??
"";
data.steps = steps ?? 20;
data.batch_size = options?.count;
data.save_images = true;
}
if (initialImage?.weight && !isUpscale) {
data.denoising_strength = 1 - initialImage.weight;
}
if (initialImage?.blob) {
const initImgB64 = await blobToBase64(initialImage?.blob);
if (isUpscale) {
data.image = initImgB64.split(",")[1];
} else {
data.init_images = [initImgB64.split(",")[1]];
}
}
if (maskImage?.blob) {
const maskImgB64 = await blobToBase64(maskImage?.blob);
data.mask = maskImgB64.split(",")[1];
data.inpainting_mask_invert = 1; // Mask mode
data.inpainting_fill = 1; // Masked content
data.inpaint_full_res = false; // Inpaint area
}
return data;
}

View File

@@ -1,392 +0,0 @@
import * as StableStudio from "@stability/stablestudio-plugin";
import { StableDiffusionImage } from "@stability/stablestudio-plugin";
import {
base64ToBlob,
constructPayload,
fetchOptions,
getImageInfo,
setOptions,
testForHistoryPlugin,
} from "./Utilities";
const manifest = {
name: "stable-diffusion-webui",
author: "Terry Jia",
link: "https://github.com/jtydhr88",
icon: `${window.location.origin}/DummyImage.png`,
version: "0.0.0",
license: "MIT",
description:
"This plugin uses [`stable-diffusion-webui`](https://github.com/AUTOMATIC1111/stable-diffusion-webui) as its back-end for inference",
};
const webuiUpscalers = [
{
label: "None",
value: "None",
},
{
label: "Lanczos",
value: "Lanczos",
},
{
label: "Nearest",
value: "Nearest",
},
{
label: "ESRGAN_4x",
value: "ESRGAN_4x",
},
{
label: "LDSR",
value: "LDSR",
},
{
label: "R-ESRGAN 4x+",
value: "R-ESRGAN 4x+",
},
{
label: "R-ESRGAN 4x+ Anime6B",
value: "R-ESRGAN 4x+ Anime6B",
},
{
label: "ScuNET GAN",
value: "ScuNET GAN",
},
{
label: "ScuNET PSNR",
value: "ScuNET PSNR",
},
{
label: "SwinIR_4x",
value: "SwinIR_4x",
},
];
const getNumber = (strValue: string | null, defaultValue: number) => {
let retValue = defaultValue;
if (strValue) {
retValue = Number(strValue);
}
return retValue;
};
const getStableDiffusionDefaultCount = () => 4;
export const createPlugin = StableStudio.createPlugin<{
settings: {
baseUrl: StableStudio.PluginSettingString;
upscaler: StableStudio.PluginSettingString;
historyImagesCount: StableStudio.PluginSettingNumber;
};
}>(({ set, get }) => {
const webuiLoad = (
webuiHostUrl?: string
): Pick<
StableStudio.Plugin,
| "createStableDiffusionImages"
| "getStatus"
| "getStableDiffusionModels"
| "getStableDiffusionSamplers"
| "getStableDiffusionDefaultCount"
| "getStableDiffusionDefaultInput"
| "getStableDiffusionExistingImages"
> => {
webuiHostUrl = webuiHostUrl ?? "http://127.0.0.1:7861";
return {
createStableDiffusionImages: async (options) => {
if (!options) {
throw new Error("options is required");
}
// fetch the current webui options (model/sampler/etc)
const webUIOptions = await fetchOptions(webuiHostUrl);
const { model, sampler, initialImage } = options?.input ?? {};
options.count = options?.count ?? getStableDiffusionDefaultCount();
// quickly save the sampler and model name to local storage
if (sampler?.name) {
localStorage.setItem("webui-saved-sampler", sampler.name);
}
if (model) {
localStorage.setItem("webui-saved-model", model);
}
// little hacky until StableStudio is better with upscaling
const isUpscale =
options?.input?.initialImage?.weight === 1 &&
model === "esrgan-v1-x2plus";
// WebUI doesn't have the right model loaded, switch the model
if (model && model !== webUIOptions.sd_model_checkpoint && !isUpscale) {
localStorage.setItem("webui-saved-model", model);
const modelResponse = await setOptions(webuiHostUrl, {
sd_model_checkpoint: model,
});
if (modelResponse.ok) {
console.log("applied model");
}
}
// Construct payload for webui
const data = await constructPayload(
options,
isUpscale,
get().settings.upscaler.value
);
// Send payload to webui
const response = await fetch(
initialImage
? isUpscale
? `${webuiHostUrl}/sdapi/v1/extra-single-image`
: `${webuiHostUrl}/sdapi/v1/img2img`
: `${webuiHostUrl}/sdapi/v1/txt2img`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
}
);
const responseData = await response.json();
const images = [];
const createdAt = new Date();
if (isUpscale) {
// Upscaling only returns one image
const blob = await base64ToBlob(responseData.image, "image/jpeg");
const image = {
id: `${Math.random() * 10000000}`,
createdAt: createdAt,
blob: blob,
input: {
model: model ?? "",
},
};
images.push(image);
} else {
// Image generation returns an array of images
const startIndex =
responseData.images.length > data.batch_size ? 1 : 0;
for (let i = startIndex; i < responseData.images.length; i++) {
const blob = await base64ToBlob(
responseData.images[i],
"image/jpeg"
);
const image: StableDiffusionImage = {
id: `${Math.random() * 10000000}`,
createdAt,
blob,
input: {
prompts: options?.input?.prompts ?? [],
steps: options?.input?.steps ?? 0,
seed: responseData.images[i].seed,
model: model ?? "",
width: options?.input?.width ?? 512,
height: options?.input?.height ?? 512,
cfgScale: options?.input?.cfgScale ?? 7,
sampler: sampler ?? { id: "", name: "" },
},
};
images.push(image);
}
}
return {
id: `${Math.random() * 10000000}`,
images: images,
};
},
getStableDiffusionModels: async () => {
const response = await fetch(`${webuiHostUrl}/sdapi/v1/sd-models`);
const responseData = await response.json();
return responseData.map((model: any) => ({
id: model.title,
name: model.model_name,
}));
},
getStatus: async () => {
const optionsResponse = await fetch(`${webuiHostUrl}/sdapi/v1/options`);
const hasWebuiHistoryPlugin = await testForHistoryPlugin(
`${webuiHostUrl}`
);
return optionsResponse.ok
? {
indicator: hasWebuiHistoryPlugin ? "success" : "info",
text: `Ready ${
hasWebuiHistoryPlugin ? "with" : "without"
} history plugin`,
}
: {
indicator: "error",
text: "unable to connect webui on " + webuiHostUrl,
};
},
};
};
const webuiHostUrl =
localStorage.getItem("webui-host-url") ?? "http://127.0.0.1:7861";
return {
...webuiLoad(webuiHostUrl),
getStableDiffusionDefaultCount: () => 4,
getStableDiffusionDefaultInput: () => {
return {
steps: 20,
sampler: {
id: localStorage.getItem("webui-saved-sampler") ?? "",
name: localStorage.getItem("webui-saved-sampler") ?? "",
},
model: localStorage.getItem("webui-saved-model") ?? "",
};
},
getStableDiffusionSamplers: async () => {
const response = await fetch(`${webuiHostUrl}/sdapi/v1/samplers`);
const responseData = await response.json();
return responseData.map((sampler: any) => ({
id: sampler.name,
name: sampler.name,
}));
},
getStableDiffusionExistingImages: async () => {
const existingImagesResponse = await fetch(
`${webuiHostUrl}/StableStudio/get-generated-images`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
limit: get().settings.historyImagesCount.value,
}),
}
);
if (!existingImagesResponse.ok) {
console.warn("unable to get existing data from webui");
}
const responseData = await existingImagesResponse.json();
const images = [];
for (let i = 0; i < responseData.length; i++) {
const imageInfo = await getImageInfo(
webuiHostUrl,
responseData[i].content
);
const blob = await base64ToBlob(responseData[i].content, "image/jpeg");
const timestampInSeconds = responseData[i].create_date;
const timestampInMilliseconds = timestampInSeconds * 1000;
const createdAt = new Date(timestampInMilliseconds);
const stableDiffusionImage = {
id: responseData[i].image_name,
createdAt: createdAt,
blob: blob,
input: {
prompts: [
{
text: imageInfo["prompt"],
weight: imageInfo["CFG scale"],
},
],
style: "",
steps: Number(imageInfo["Steps"]) ?? -1,
seed: Number(imageInfo["Seed"]) ?? -1,
model: imageInfo["Model"] ?? "",
width: responseData[i].width,
height: responseData[i].height,
},
};
images.push(stableDiffusionImage);
}
return [
{
id: `${Math.random() * 10000000}`,
images: images,
},
];
},
settings: {
baseUrl: {
type: "string",
title: "Host URL",
placeholder: "http://127.0.0.1:7861",
value: localStorage.getItem("webui-host-url") ?? "",
description:
"The URL of the `stable-diffusion-webui` host, usually http://127.0.0.1:7861",
},
upscaler: {
type: "string",
title: "Upscaler 1",
options: webuiUpscalers,
value: localStorage.getItem("upscaler1") ?? webuiUpscalers[0].value,
description:
"Select the upscaler used when downloading images at more than 1x size",
},
historyImagesCount: {
type: "number",
title: "History image count",
description: "How many images should be fetched from local history?",
min: 0,
max: 50,
step: 1,
variant: "slider",
value: getNumber(localStorage.getItem("historyImagesCount"), 20),
},
},
setSetting: (key, value) => {
set(({ settings }) => ({
settings: {
...settings,
[key]: { ...settings[key], value: value as string },
},
}));
if (key === "baseUrl" && typeof value === "string") {
localStorage.setItem("webui-host-url", value);
set((plugin) => ({ ...plugin, ...webuiLoad(value) }));
} else if (key === "upscaler" && typeof value === "string") {
localStorage.setItem("upscaler1", value);
} else if (key === "historyImagesCount" && typeof value === "number") {
localStorage.setItem("historyImagesCount", value.toString());
}
},
manifest,
};
});

View File

@@ -1,21 +0,0 @@
{
"extends": "../../tsconfig.json",
"include": ["src/**/*"],
"exclude": ["node_modules"],
"compilerOptions": {
"emitDeclarationOnly": true,
"declaration": true,
"noUncheckedIndexedAccess": false,
"outDir": "./lib",
"baseUrl": "./",
"paths": {
"~/*": ["./src/*"]
},
"plugins": [
{ "transform": "typescript-transform-paths" },
{ "transform": "typescript-transform-paths", "afterDeclarations": true }
]
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "@stability/stablestudio-plugin",
"version": "0.0.1",
"version": "0.0.0",
"license": "MIT",
"main": "./lib/index.js",
"types": "./lib/index.d.ts",
@@ -12,8 +12,7 @@
"build:types": "ttsc --project tsconfig.json",
"build:javascript": "tsx scripts/Build.ts",
"build": "yarn build:types && yarn build:javascript",
"dev": "nodemon --watch src --ext ts,tsx,json --exec \"yarn build\"",
"prepublish": "yarn build"
"dev": "nodemon --watch src --ext ts,tsx,json --exec \"yarn build\""
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^5.33.1",

View File

@@ -12,7 +12,8 @@
"build:preview": "yarn build:types && vite build --mode preview",
"build:production": "yarn build:types && vite build --mode production",
"dev:types": "tsc --noEmit --watch",
"dev": "vite"
"dev": "cargo tauri dev",
"dev:vite": "vite"
},
"dependencies": {
"@emotion/css": "^11.10.5",
@@ -21,10 +22,11 @@
"@react-hook/resize-observer": "^1.2.6",
"@reecelucas/react-use-hotkeys": "^2.0.0",
"@stability/stablestudio-plugin": "workspace:^",
"@stability/stablestudio-plugin-stability": "workspace:^",
"@stability/stablestudio-plugin-comfy": "workspace:^",
"@tanstack/react-query": "^4.22.0",
"@tanstack/react-query-devtools": "^4.22.0",
"@tanstack/react-virtual": "beta",
"@tauri-apps/api": "^1.4.0",
"buffer": "^6.0.3",
"date-fns": "^2.29.3",
"file-saver": "^2.0.5",
@@ -40,6 +42,7 @@
"notistack": "^3.0.0-alpha.11",
"query-string": "^8.1.0",
"react": "^18.2.0",
"react-circular-progressbar": "^2.1.0",
"react-dom": "^18.2.0",
"react-konva": "^18.2.3",
"react-konva-utils": "^0.3.1",
@@ -53,6 +56,7 @@
"remark-custom-heading-id": "^1.0.0",
"remark-gfm": "^3.0.1",
"tailwind-merge": "^1.8.1",
"tauri-plugin-upload": "https://github.com/tauri-apps/tauri-plugin-upload#v1",
"throttled-queue": "^2.1.4",
"tiny-invariant": "^1.3.1",
"ts-custom-error": "^3.3.1",

View File

@@ -0,0 +1,7 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="24" height="24" fill="#3D3D3D"/>
<path d="M5 21H17.25C17.7141 21 18.1592 20.8104 18.4874 20.4728C18.8156 20.1352 19 19.6774 19 19.2V7.95L14.1875 3H6.75C6.28587 3 5.84075 3.18964 5.51256 3.52721C5.18437 3.86477 5 4.32261 5 4.8V8.4" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M14 3V8H19" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M9 17L12 14.5L9 12" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M6 12L3 14.5L6 17" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 757 B

View File

@@ -0,0 +1,3 @@
# Generated by Cargo
# will have compiled files and executables
/target/

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,37 @@
[package]
name = "app"
version = "0.1.0"
description = "A Tauri App"
authors = ["you"]
license = ""
repository = ""
default-run = "app"
edition = "2021"
rust-version = "1.60"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[build-dependencies]
tauri-build = { version = "1.4.0", features = [] }
[dependencies]
serde_json = "1.0"
serde = { version = "1.0", features = ["derive"] }
tauri = { version = "1.4.1", features = [ "os-all", "fs-all", "path-all", "process-command-api", "devtools"] }
tauri-plugin-upload = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" }
zip = "0.6.6"
zip-extensions = "0.6.1"
reqwest = { version = "0.11.6", features = ["blocking"] }
tiny_http = "0.12.0"
portpicker = "0.1.1"
http = "0.2.9"
once_cell = "1.18.0"
[target.'cfg(unix)'.dependencies]
fork = "0.1.22"
[features]
# this feature is used for production builds or when `devPath` points to the filesystem and the built-in dev server is disabled.
# If you use cargo directly instead of tauri's cli you can use this feature flag to switch between tauri's `dev` and `build` modes.
# DO NOT REMOVE!!
custom-protocol = ["tauri/custom-protocol"]

View File

@@ -0,0 +1,3 @@
fn main() {
tauri_build::build()
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 540 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Some files were not shown because too many files have changed in this diff Show More