Initial commit
|
@ -0,0 +1,67 @@
|
|||
{
|
||||
"root": true,
|
||||
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2018,
|
||||
"ecmaFeatures": { "jsx": true },
|
||||
"sourceType": "module",
|
||||
"project": "./tsconfig.json",
|
||||
"extraFileExtensions": [".md"]
|
||||
},
|
||||
|
||||
"extends": [
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"plugin:react/recommended",
|
||||
"plugin:react-hooks/recommended",
|
||||
"plugin:prettier/recommended",
|
||||
"plugin:markdown/recommended"
|
||||
],
|
||||
|
||||
"plugins": ["react", "react-hooks", "import"],
|
||||
"settings": { "react": { "version": "detect" } },
|
||||
|
||||
"rules": {
|
||||
"prettier/prettier": ["error", {}, { "usePrettierrc": true }],
|
||||
|
||||
"react/react-in-jsx-scope": "off",
|
||||
"react/jsx-no-undef": "off",
|
||||
"react/prop-types": "off",
|
||||
"react-hooks/rules-of-hooks": "off",
|
||||
"react/no-unknown-property": ["error", { "ignore": ["css"] }],
|
||||
"react/display-name": "off",
|
||||
|
||||
"@typescript-eslint/no-namespace": "off",
|
||||
"@typescript-eslint/no-unused-vars": [
|
||||
"error",
|
||||
{ "varsIgnorePattern": "^_", "argsIgnorePattern": "^_" }
|
||||
],
|
||||
|
||||
"no-unused-vars": [
|
||||
"error",
|
||||
{ "varsIgnorePattern": "^_", "argsIgnorePattern": "^_" }
|
||||
],
|
||||
|
||||
"import/order": [
|
||||
"error",
|
||||
{
|
||||
"newlines-between": "always-and-inside-groups",
|
||||
"alphabetize": { "order": "asc", "caseInsensitive": true },
|
||||
|
||||
"groups": ["builtin", "external", "parent", "index", "sibling"],
|
||||
"pathGroups": [
|
||||
{ "pattern": "~/**", "group": "external" },
|
||||
{ "pattern": ".", "group": "sibling" }
|
||||
]
|
||||
}
|
||||
],
|
||||
|
||||
"sort-imports": [
|
||||
"error",
|
||||
{
|
||||
"ignoreCase": true,
|
||||
"ignoreDeclarationSort": true
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
* text=auto eol=lf
|
|
@ -0,0 +1,13 @@
|
|||
.DS_Store
|
||||
.idea
|
||||
*.iml
|
||||
|
||||
node_modules
|
||||
|
||||
.pnp.*
|
||||
.yarn/*
|
||||
!.yarn/patches
|
||||
!.yarn/plugins
|
||||
!.yarn/releases
|
||||
!.yarn/sdks
|
||||
!.yarn/versions
|
|
@ -0,0 +1,8 @@
|
|||
command_exists () {
|
||||
command -v "$1" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
# Windows 10, Git Bash and Yarn workaround
|
||||
if command_exists winpty && test -t 1; then
|
||||
exec < /dev/tty
|
||||
fi
|
|
@ -0,0 +1,12 @@
|
|||
#!/usr/bin/env sh
|
||||
. "$(dirname -- "$0")/_/husky.sh"
|
||||
. "$(dirname "$0")/common.sh"
|
||||
|
||||
# Ensure the entire project still compiles
|
||||
blue=$(tput setaf 4)
|
||||
normal=$(tput sgr0)
|
||||
printf "%b" "${blue}Type checking... ${normal}"
|
||||
yarn stablestudio-ui build:types
|
||||
|
||||
# Run the lint-staged job in the root package.json
|
||||
yarn lint-staged
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"endOfLine": "auto"
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Launch UI in Chrome",
|
||||
"type": "chrome",
|
||||
"request": "launch",
|
||||
"url": "http://localhost:3000",
|
||||
"webRoot": "${workspaceFolder}"
|
||||
},
|
||||
{
|
||||
"name": "Launch UI in Edge",
|
||||
"type": "msedge",
|
||||
"request": "launch",
|
||||
"url": "http://localhost:3000",
|
||||
"webRoot": "${workspaceFolder}"
|
||||
},
|
||||
{
|
||||
"name": "Attach to Chrome",
|
||||
"port": 9222,
|
||||
"request": "attach",
|
||||
"type": "pwa-chrome",
|
||||
"urlFilter": "http://localhost:3000/*",
|
||||
"webRoot": "${workspaceFolder}"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"typescript.tsdk": "node_modules/typescript/lib",
|
||||
"typescript.enablePromptUseWorkspaceTsdk": true
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
nodeLinker: node-modules
|
||||
|
||||
plugins:
|
||||
- path: .yarn/plugins/@yarnpkg/plugin-workspace-tools.cjs
|
||||
spec: "@yarnpkg/plugin-workspace-tools"
|
||||
|
||||
yarnPath: .yarn/releases/yarn-3.3.0.cjs
|
|
@ -0,0 +1,127 @@
|
|||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
We as members, contributors, and leaders pledge to make participation in our
|
||||
community a harassment-free experience for everyone, regardless of age, body
|
||||
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
||||
identity and expression, level of experience, education, socio-economic status,
|
||||
nationality, personal appearance, race, religion, or sexual identity
|
||||
and orientation.
|
||||
|
||||
We pledge to act and interact in ways that contribute to an open, welcoming,
|
||||
diverse, inclusive, and healthy community.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to a positive environment for our
|
||||
community include:
|
||||
|
||||
- Demonstrating empathy and kindness toward other people
|
||||
- Being respectful of differing opinions, viewpoints, and experiences
|
||||
- Giving and gracefully accepting constructive feedback
|
||||
- Accepting responsibility and apologizing to those affected by our mistakes,
|
||||
and learning from the experience
|
||||
- Focusing on what is best not just for us as individuals, but for the
|
||||
overall community
|
||||
|
||||
Examples of unacceptable behavior include:
|
||||
|
||||
- The use of sexualized language or imagery, and sexual attention or
|
||||
advances of any kind
|
||||
- Trolling, insulting or derogatory comments, and personal or political attacks
|
||||
- Public or private harassment
|
||||
- Publishing others' private information, such as a physical or email
|
||||
address, without their explicit permission
|
||||
- Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
## Enforcement Responsibilities
|
||||
|
||||
Community leaders are responsible for clarifying and enforcing our standards of
|
||||
acceptable behavior and will take appropriate and fair corrective action in
|
||||
response to any behavior that they deem inappropriate, threatening, offensive,
|
||||
or harmful.
|
||||
|
||||
Community leaders have the right and responsibility to remove, edit, or reject
|
||||
comments, commits, code, wiki edits, issues, and other contributions that are
|
||||
not aligned to this Code of Conduct, and will communicate reasons for moderation
|
||||
decisions when appropriate.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies within all community spaces, and also applies when
|
||||
an individual is officially representing the community in public spaces.
|
||||
Examples of representing our community include using an official e-mail address,
|
||||
posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported to the community leaders responsible for enforcement at [Stability AI](https://stability.ai).
|
||||
All complaints will be reviewed and investigated promptly and fairly.
|
||||
|
||||
All community leaders are obligated to respect the privacy and security of the
|
||||
reporter of any incident.
|
||||
|
||||
## Enforcement Guidelines
|
||||
|
||||
Community leaders will follow these Community Impact Guidelines in determining
|
||||
the consequences for any action they deem in violation of this Code of Conduct:
|
||||
|
||||
### 1. Correction
|
||||
|
||||
**Community Impact**: Use of inappropriate language or other behavior deemed
|
||||
unprofessional or unwelcome in the community.
|
||||
|
||||
**Consequence**: A private, written warning from community leaders, providing
|
||||
clarity around the nature of the violation and an explanation of why the
|
||||
behavior was inappropriate. A public apology may be requested.
|
||||
|
||||
### 2. Warning
|
||||
|
||||
**Community Impact**: A violation through a single incident or series
|
||||
of actions.
|
||||
|
||||
**Consequence**: A warning with consequences for continued behavior. No
|
||||
interaction with the people involved, including unsolicited interaction with
|
||||
those enforcing the Code of Conduct, for a specified period of time. This
|
||||
includes avoiding interactions in community spaces as well as external channels
|
||||
like social media. Violating these terms may lead to a temporary or
|
||||
permanent ban.
|
||||
|
||||
### 3. Temporary Ban
|
||||
|
||||
**Community Impact**: A serious violation of community standards, including
|
||||
sustained inappropriate behavior.
|
||||
|
||||
**Consequence**: A temporary ban from any sort of interaction or public
|
||||
communication with the community for a specified period of time. No public or
|
||||
private interaction with the people involved, including unsolicited interaction
|
||||
with those enforcing the Code of Conduct, is allowed during this period.
|
||||
Violating these terms may lead to a permanent ban.
|
||||
|
||||
### 4. Permanent Ban
|
||||
|
||||
**Community Impact**: Demonstrating a pattern of violation of community
|
||||
standards, including sustained inappropriate behavior, harassment of an
|
||||
individual, or aggression toward or disparagement of classes of individuals.
|
||||
|
||||
**Consequence**: A permanent ban from any sort of public interaction within
|
||||
the community.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
||||
version 2.0, available at
|
||||
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
|
||||
|
||||
Community Impact Guidelines were inspired by [Mozilla's code of conduct
|
||||
enforcement ladder](https://github.com/mozilla/diversity).
|
||||
|
||||
[homepage]: https://www.contributor-covenant.org
|
||||
|
||||
For answers to common questions about this code of conduct, see the FAQ at
|
||||
https://www.contributor-covenant.org/faq. Translations are available at
|
||||
https://www.contributor-covenant.org/translations.
|
|
@ -0,0 +1,21 @@
|
|||
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.
|
|
@ -0,0 +1,97 @@
|
|||
<div align="center">
|
||||
|
||||
![StableStudio](./misc/Banner.png)
|
||||
|
||||
# StableStudio by [Stability AI](https://stability.ai/)
|
||||
|
||||
**👋 Welcome to the community repository for StableStudio, the open-source version of [DreamStudio](https://www.dreamstudio.ai)**
|
||||
|
||||
**🗺 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>**
|
||||
|
||||
**🔗 Links – <a href="https://discord.gg/wHM9XjyVpU" 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>**
|
||||
|
||||
</div>
|
||||
|
||||
<div align="center" style="display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: 1em; margin: 4em 0;">
|
||||
<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;" />
|
||||
</div>
|
||||
|
||||
# <a id="quick-start" href="#quick-start">🚀 Quick Start</a>
|
||||
|
||||
You'll need to have [Node.js](https://nodejs.org/en/) and [Yarn](https://yarnpkg.com/) installed.
|
||||
|
||||
Once that's done, you can run the following commands...
|
||||
|
||||
```bash
|
||||
git clone https://github.com/Stability-AI/StableStudio.git
|
||||
|
||||
cd StableStudio
|
||||
|
||||
yarn
|
||||
|
||||
yarn dev
|
||||
```
|
||||
|
||||
_**That's it! 🎉**_
|
||||
|
||||
StableStudio will be running at [localhost:3000](http://localhost:3000) by default.
|
||||
|
||||
You'll need to have your [API key](https://platform.stability.ai/docs/getting-started/authentication) handy to use the default [Stability API](https://platform.stability.ai/docs/getting-started) plugin.
|
||||
|
||||
If you don't have one, you can create an account on [DreamStudio](https://dreamstudio.ai) and get a key from the [account page](https://dreamstudio.ai/account).
|
||||
|
||||
# <a id="about" href="#about">ℹ️ About</a>
|
||||
|
||||
<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;" />
|
||||
</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!
|
||||
|
||||
# <a id="faq" href="#faq">🙋 FAQ</a>
|
||||
|
||||
## What's the difference between StableStudio and [DreamStudio](https://dreamstudio.ai)?
|
||||
|
||||
_Not much!_ There are a few tweaks we made to make the project more community-friendly:
|
||||
|
||||
- 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.
|
||||
|
||||
- On release, we'll only be providing a plugin for the Stability API, but with a little bit of TypeScript, you can [create your own](./packages/stablestudio-plugin/README.md).
|
||||
|
||||
- We removed Stability-specific account features such as billing, API key management, etc.
|
||||
|
||||
- These features are still available at [DreamStudio's account page](https://dreamstudio.ai/account).
|
||||
|
||||
## 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.
|
||||
|
||||
# <a id="contributing" href="#contributing">🧑💻 Contributing</a>
|
||||
|
||||
<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;" />
|
||||
</div>
|
||||
|
||||
_**Community contributions are encouraged!**_
|
||||
|
||||
_**The UI package's [README](./packages/stablestudio-ui/README.md) is a great place to start.**_
|
||||
|
||||
Bug fixes, documentation, general clean-up, new features, etc. are all welcome.
|
||||
|
||||
Here are some useful links...
|
||||
|
||||
- [Discussion](https://github.com/Stability-AI/StableStudio/discussions)
|
||||
- [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)
|
After Width: | Height: | Size: 352 KiB |
After Width: | Height: | Size: 1.9 MiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 387 KiB |
After Width: | Height: | Size: 29 KiB |
After Width: | Height: | Size: 2.1 MiB |
After Width: | Height: | Size: 26 KiB |
After Width: | Height: | Size: 1.6 MiB |
After Width: | Height: | Size: 2.2 MiB |
After Width: | Height: | Size: 2.2 MiB |
After Width: | Height: | Size: 2.0 MiB |
After Width: | Height: | Size: 356 KiB |
After Width: | Height: | Size: 1.9 MiB |
After Width: | Height: | Size: 2.0 MiB |
|
@ -0,0 +1,35 @@
|
|||
{
|
||||
"license": "MIT",
|
||||
"packageManager": "yarn@3.3.0",
|
||||
"workspaces": {
|
||||
"packages": [
|
||||
"packages/*"
|
||||
]
|
||||
},
|
||||
"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-example": "yarn workspace @stability/stablestudio-plugin-example",
|
||||
"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-ui": "yarn workspace @stability/stablestudio-ui",
|
||||
"dev:use-example-plugin": "cross-env VITE_USE_EXAMPLE_PLUGIN=true yarn dev",
|
||||
"dev": "yarn workspaces foreach --all --interlaced --verbose --parallel --jobs unlimited run dev",
|
||||
"build": "yarn workspaces foreach --all --interlaced --verbose --jobs unlimited run build",
|
||||
"clean": "yarn workspaces foreach --all --interlaced --verbose --parallel --jobs unlimited run clean && rimraf node_modules"
|
||||
},
|
||||
"devDependencies": {
|
||||
"cross-env": "^7.0.3",
|
||||
"husky": "^8.0.3",
|
||||
"lint-staged": "^13.1.2",
|
||||
"rimraf": "^3.0.2",
|
||||
"yarn": "^1.22.19"
|
||||
},
|
||||
"lint-staged": {
|
||||
"./packages/ui/**/*.{ts,tsx,js,jsx,md}": [
|
||||
"prettier --write",
|
||||
"eslint --fix"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
{ "extends": ["../../.eslintrc.json"] }
|
|
@ -0,0 +1 @@
|
|||
lib
|
|
@ -0,0 +1,21 @@
|
|||
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.
|
|
@ -0,0 +1,39 @@
|
|||
{
|
||||
"name": "@stability/stablestudio-plugin-example",
|
||||
"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"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
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();
|
|
@ -0,0 +1,82 @@
|
|||
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 },
|
||||
},
|
||||
})),
|
||||
}));
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"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 }
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
./src/Proto/Generated/**/*
|
||||
./api-interfaces/**
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"extends": ["../../.eslintrc.json"],
|
||||
"ignorePatterns": ["./src/Proto/Generated/**"]
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
api-interfaces
|
||||
lib
|
|
@ -0,0 +1,2 @@
|
|||
./src/Proto/Generated/**/*
|
||||
./api-interfaces/**
|
|
@ -0,0 +1,21 @@
|
|||
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.
|
|
@ -0,0 +1,46 @@
|
|||
{
|
||||
"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"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
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();
|
|
@ -0,0 +1,69 @@
|
|||
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}`
|
||||
);
|
|
@ -0,0 +1,236 @@
|
|||
// @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);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
// @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);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,279 @@
|
|||
// @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 }
|
||||
]);
|
|
@ -0,0 +1,57 @@
|
|||
// @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);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,480 @@
|
|||
// @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();
|
|
@ -0,0 +1,178 @@
|
|||
// @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);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,436 @@
|
|||
// @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();
|
|
@ -0,0 +1,9 @@
|
|||
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";
|
|
@ -0,0 +1,616 @@
|
|||
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",
|
||||
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"
|
||||
> => {
|
||||
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()
|
||||
),
|
||||
},
|
||||
}),
|
||||
},
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
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: Generation.DiffusionSampler.SAMPLER_DDIM,
|
||||
},
|
||||
}),
|
||||
|
||||
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
|
||||
),
|
||||
|
||||
getStableDiffusionStyles: () => [
|
||||
{
|
||||
id: "enhance",
|
||||
name: "Enhance",
|
||||
imageURL: "https://dreamstudio.ai/presets/enhance.png",
|
||||
},
|
||||
{
|
||||
id: "anime",
|
||||
name: "Anime",
|
||||
imageURL: "https://dreamstudio.ai/presets/anime.png",
|
||||
},
|
||||
{
|
||||
id: "photographic",
|
||||
name: "Photographic",
|
||||
imageURL: "https://dreamstudio.ai/presets/photographic.png",
|
||||
},
|
||||
{
|
||||
id: "digital-art",
|
||||
name: "Digital art",
|
||||
imageURL: "https://dreamstudio.ai/presets/digital-art.png",
|
||||
},
|
||||
{
|
||||
id: "comic-book",
|
||||
name: "Comic book",
|
||||
imageURL: "https://dreamstudio.ai/presets/comic-book.png",
|
||||
},
|
||||
{
|
||||
id: "fantasy-art",
|
||||
name: "Fantasy art",
|
||||
imageURL: "https://dreamstudio.ai/presets/fantasy-art.png",
|
||||
},
|
||||
{
|
||||
id: "analog-film",
|
||||
name: "Analog film",
|
||||
imageURL: "https://dreamstudio.ai/presets/analog-film.png",
|
||||
},
|
||||
{
|
||||
id: "neon-punk",
|
||||
name: "Neon punk",
|
||||
imageURL: "https://dreamstudio.ai/presets/neon-punk.png",
|
||||
},
|
||||
{
|
||||
id: "isometric",
|
||||
name: "Isometric",
|
||||
imageURL: "https://dreamstudio.ai/presets/isometric.png",
|
||||
},
|
||||
{
|
||||
id: "low-poly",
|
||||
name: "Low poly",
|
||||
imageURL: "https://dreamstudio.ai/presets/low-poly.png",
|
||||
},
|
||||
{
|
||||
id: "origami",
|
||||
name: "Origami",
|
||||
imageURL: "https://dreamstudio.ai/presets/origami.png",
|
||||
},
|
||||
{
|
||||
id: "line-art",
|
||||
name: "Line art",
|
||||
imageURL: "https://dreamstudio.ai/presets/line-art.png",
|
||||
},
|
||||
{
|
||||
id: "modeling-compound",
|
||||
name: "Craft clay",
|
||||
imageURL: "https://dreamstudio.ai/presets/modeling-compound.png",
|
||||
},
|
||||
{
|
||||
id: "cinematic",
|
||||
name: "Cinematic",
|
||||
imageURL: "https://dreamstudio.ai/presets/cinematic.png",
|
||||
},
|
||||
{
|
||||
id: "3d-model",
|
||||
name: "3D model",
|
||||
imageURL: "https://dreamstudio.ai/presets/3d-model.png",
|
||||
},
|
||||
{
|
||||
id: "pixel-art",
|
||||
name: "Pixel art",
|
||||
imageURL: "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/1072239614644994169) · [🌈 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;
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"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 }
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
{ "extends": ["../../.eslintrc.json"] }
|
|
@ -0,0 +1 @@
|
|||
lib
|
|
@ -0,0 +1,21 @@
|
|||
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.
|
|
@ -0,0 +1,39 @@
|
|||
{
|
||||
"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"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
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();
|
|
@ -0,0 +1,3 @@
|
|||
import * as StableStudio from "@stability/stablestudio-plugin";
|
||||
|
||||
export const createPlugin = StableStudio.createPlugin(() => ({}));
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"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 }
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
{ "extends": ["../../.eslintrc.json"] }
|
|
@ -0,0 +1 @@
|
|||
lib
|
|
@ -0,0 +1,21 @@
|
|||
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.
|
|
@ -0,0 +1,39 @@
|
|||
{
|
||||
"name": "@stability/stablestudio-plugin-webui",
|
||||
"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"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
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();
|
|
@ -0,0 +1,3 @@
|
|||
import * as StableStudio from "@stability/stablestudio-plugin";
|
||||
|
||||
export const createPlugin = StableStudio.createPlugin(() => ({}));
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"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 }
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
{ "extends": ["../../.eslintrc.json"] }
|
|
@ -0,0 +1 @@
|
|||
lib
|
|
@ -0,0 +1,21 @@
|
|||
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.
|
|
@ -0,0 +1,119 @@
|
|||
<div align="center">
|
||||
|
||||
# 🔌 Plugins
|
||||
|
||||
**🗺 Contents – [ℹ️ About](#about) · [📦 Installation](#installation) · [🤝 Contract](#technology) · [🔮 Future](#conventions)**
|
||||
|
||||
**[⬆️ Top-Level README](../../README.md)**
|
||||
|
||||
![MagicalElectricPlugs](../../misc/MagicalElectricPlugs.png)
|
||||
|
||||
### 🚧 👷 **PLUGINS ARE EXPERIMENTAL AND NOT FINAL** 🛠 🚧
|
||||
|
||||
_The contract and implementation are [likely to change](https://github.com/Stability-AI/StableStudio/issues/3)..._
|
||||
|
||||
</div>
|
||||
|
||||
# <a id="about" href="#about">ℹ️ About</a>
|
||||
|
||||
In order to make StableStudio easier to extend, we've ripped out the "back-end" into a plugin system.
|
||||
|
||||
This means you can implement an entirely different inference stack, StableStudio doesn't care if it's local or a hosted API.
|
||||
|
||||
## ⭐️ Features
|
||||
|
||||
We're hoping this list expands [over time](#future), but here's what's available right now...
|
||||
|
||||
- **🏞 Image Generation**
|
||||
|
||||
All aspects of image generation are handled by plugins including the default input, how styles are implemented, how to fetch existing images, etc.
|
||||
|
||||
- **🪪 Plugin Manifest**
|
||||
|
||||
Plugins can provide a manifest with a markdown description, author details, version information, etc.
|
||||
|
||||
- **⚙️ Plugin Settings**
|
||||
|
||||
Plugins can declare settings which are available to the user in the settings menu.
|
||||
|
||||
## 🧪 Development
|
||||
|
||||
**If you want to play around with an example plugin which has nice developer tooling, check out the [example plugin](../stablestudio-plugin-example/src/index.ts).**
|
||||
|
||||
You can load the UI using example plugin instead of the default [Stability plugin](../stablestudio-plugin-stability/src/index.ts) by running...
|
||||
|
||||
```bash
|
||||
yarn dev:use-example-plugin
|
||||
```
|
||||
|
||||
Any changes you make within the [example plugin](../stablestudio-plugin-example/src/index.ts) will be hot-reloaded into StableStudio.
|
||||
|
||||
# <a id="installation" href="#installation">📦 Installation</a>
|
||||
|
||||
**This is mainly a feature intended for developers, we're [likely to change](https://github.com/Stability-AI/StableStudio/issues/3) how plugins work for end-users.**
|
||||
|
||||
_Never install plugins from untrusted sources!_
|
||||
|
||||
Although they are sand-boxed to the browser, a malicious actor could read through your image history or steal your API key if you're not careful.
|
||||
|
||||
To install a plugin, first enable "developer mode" in the settings menu...
|
||||
|
||||
![DeveloperMode](../../misc/DeveloperMode.png)
|
||||
|
||||
Now you can point to any fetch-able JavaScript file which exports a plugin...
|
||||
|
||||
![InstallPlugin](../../misc/InstallPlugin.png)
|
||||
|
||||
If loaded successfully, you'll see it in the settings menu...
|
||||
|
||||
![ExamplePlugin](../../misc/ExamplePlugin.png)
|
||||
|
||||
✅ _**That's it!**_
|
||||
|
||||
As of now, you can only have one active plugin at a time.
|
||||
|
||||
The main purpose of plugins in their current form is to allow developers to experiment with different inference stacks.
|
||||
|
||||
# <a id="contract" href="#contract">🤝 Contract</a>
|
||||
|
||||
**Check out the [TypeScript source](./src/Plugin.ts) to see full documentation of the API.**
|
||||
|
||||
Plugins are effectively just a bag of JavaScript functions.
|
||||
|
||||
StableStudio calls these functions for core functionality, such as `createStableDiffusionImages`, `getStableDiffusionStyles`, `getStableDiffusionDefaultInput`, etc.
|
||||
|
||||
Functionality degrades gracefully, for example, if you don't implement `getStableDiffusionStyles`, no styles will be shown in the UI.
|
||||
|
||||
# <a id="future" href="#future">🔮 Future</a>
|
||||
|
||||
Plugins were mostly created to rip out calls to Stability's [gRPC API](https://platform.stability.ai), so their functionality is quite limited.
|
||||
|
||||
**Given the importance of a robust plugin system, we're really hoping to [gather feedback](https://github.com/Stability-AI/StableStudio/issues/3) on how we can improve the API.**
|
||||
|
||||
Here's what's on our mind when it comes to the future of StableStudio plugins...
|
||||
|
||||
- **🧠 More Inference Stacks**
|
||||
|
||||
The default [Stability plugin](../stablestudio-plugin-stability/src/index.ts) enables inference relying on [Stability's API](../stablestudio-plugin-stability/src/index.ts), but we're hoping to expand support for local inference.
|
||||
|
||||
We're particularly interested in creating a plugin for using [`stable-diffusion-webui`](https://github.com/AUTOMATIC1111/stable-diffusion-webui)'s [REST API](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/API).
|
||||
|
||||
Though it's not fully-ready, we're excited about the future of [WebGPU](https://developer.mozilla.org/en-US/docs/Web/API/WebGPU_API), and would love to support it via a plugin.
|
||||
|
||||
_We've stubbed out two empty packages to house these potential plugins..._
|
||||
|
||||
[`stablestudio-plugin-webui`](../stablestudio-plugin-webui/src/index.ts)
|
||||
|
||||
[`stablestudio-plugin-webgpu`](../stablestudio-plugin-webgpu/src/index.ts)
|
||||
|
||||
- **🎨 Deeper UI Extensibility**
|
||||
|
||||
Currently plugins can only change "back-end" functionality. We'd love to allow plugins to create entire new features or modify existing ones.
|
||||
|
||||
- **🧱 Multiple Plugins**
|
||||
|
||||
Only one plugin can be loaded at a time with our current implementation. Allowing multiple plugins to play nicely with each other would be a huge win.
|
||||
|
||||
- **🛍 Plugin Library**
|
||||
|
||||
If there is enough interest and community momentum, we'd love to create a plugin library where users can easily install plugins from a curated list.
|
|
@ -0,0 +1,39 @@
|
|||
{
|
||||
"name": "@stability/stablestudio-plugin",
|
||||
"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\""
|
||||
},
|
||||
"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"
|
||||
},
|
||||
"dependencies": {
|
||||
"zustand": "^4.3.7"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
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();
|
|
@ -0,0 +1,297 @@
|
|||
import { createStore, StoreApi } from "zustand";
|
||||
|
||||
/**
|
||||
* Function used to create a `Plugin`
|
||||
*
|
||||
* ```ts
|
||||
* import * as StableStudio from "@stability/stablestudio-plugin";
|
||||
*
|
||||
* // You need to export your plugin like this...
|
||||
* export const createPlugin = StableStudio.createPlugin(() => ({}));
|
||||
* ```
|
||||
*
|
||||
* It returns a function waiting for `PluginCreateContext` as an argument, which the UI provides
|
||||
*/
|
||||
export const createPlugin =
|
||||
<P extends PluginTypeHelper>(
|
||||
createPlugin: (options: {
|
||||
context: PluginCreateContext;
|
||||
set: StoreApi<Plugin<P>>["setState"];
|
||||
get: StoreApi<Plugin<P>>["getState"];
|
||||
}) => Plugin<P>
|
||||
) =>
|
||||
(context: PluginCreateContext) =>
|
||||
createStore<Plugin<P>>((set, get) => createPlugin({ set, get, context }));
|
||||
|
||||
/** `PluginCreateContext` is passed to the `createPlugin` function and provides some useful functions */
|
||||
type PluginCreateContext = {
|
||||
/** Get the git hash of the repository */
|
||||
getGitHash: () => string;
|
||||
|
||||
/** Get a random prompt for image generation */
|
||||
getStableDiffusionRandomPrompt: () => string;
|
||||
};
|
||||
|
||||
/** `PluginManifest` is used to describe your plugin on the settings page */
|
||||
export type PluginManifest = {
|
||||
/** What is your plugin called? */
|
||||
name?: string;
|
||||
|
||||
/** A link to your plugin's icon */
|
||||
icon?: URLString;
|
||||
|
||||
/** A link to your plugin's website */
|
||||
link?: URLString;
|
||||
|
||||
/** Your plugin version, no versioning schema is currently enforced */
|
||||
version?: string;
|
||||
|
||||
/** What's the license, no licensing schema is currently enforced */
|
||||
license?: string;
|
||||
|
||||
/** Who made this plugin? */
|
||||
author?: string;
|
||||
|
||||
/** What does your plugin do? */
|
||||
description?: Markdown;
|
||||
};
|
||||
|
||||
export type PluginSettingCommon = {
|
||||
/** What is your plugin called? */
|
||||
title?: string;
|
||||
|
||||
/** What is your plugin called? */
|
||||
description?: Markdown;
|
||||
|
||||
/** Is this setting required? If so, users will be forced to provide an input */
|
||||
required?: boolean;
|
||||
};
|
||||
|
||||
/** `PluginSetting` allows for `string`, `number`, and `boolean` input types */
|
||||
export type PluginSetting<T> =
|
||||
| PluginSettingString<T>
|
||||
| PluginSettingNumber<T>
|
||||
| PluginSettingBoolean<T>;
|
||||
|
||||
/** `PluginSetting` which is displayed and input as a `string` */
|
||||
export type PluginSettingString<T = string> = PluginSettingCommon & {
|
||||
type: "string";
|
||||
|
||||
/** The current `value` */
|
||||
value?: T;
|
||||
|
||||
/** If you provide `options`, this will become a dropdown */
|
||||
options?: { label: string; value: T }[];
|
||||
|
||||
/** The `placeholder` input `string` */
|
||||
placeholder?: string;
|
||||
|
||||
/** Given a `value`, how should it be displayed? Useful if your value is a `Date` for example */
|
||||
formatter?: (value: T) => string;
|
||||
|
||||
/** Given a `string`, how should it be saved as a `value`? */
|
||||
parser?: (string: string) => T;
|
||||
|
||||
/** Determines whether this input is displayed as a `password` type */
|
||||
password?: boolean;
|
||||
};
|
||||
|
||||
/** `PluginSetting` which is displayed and input as a `number` */
|
||||
export type PluginSettingNumber<T = number> = PluginSettingCommon & {
|
||||
type: "number";
|
||||
|
||||
/** The current `value` */
|
||||
value?: T;
|
||||
|
||||
/** The `placeholder` input `number` */
|
||||
placeholder?: number;
|
||||
|
||||
/** Enforces an inclusive `min` allowed `value` */
|
||||
min?: number;
|
||||
|
||||
/** Enforces an inclusive `max` allowed `value` */
|
||||
max?: number;
|
||||
|
||||
/** Enforces a `step` size between each `value` */
|
||||
step?: number;
|
||||
|
||||
/** Given a `value`, how can it formatted as a `number`? */
|
||||
formatter?: (value: T) => number;
|
||||
|
||||
/** Given a `number`, how should it be saved as a `value`? */
|
||||
parser?: (value: number) => T;
|
||||
|
||||
/** Determines whether to use a slider or input. Uses `input` by default */
|
||||
variant?: "slider" | "input";
|
||||
};
|
||||
|
||||
/** `PluginSetting` which is displayed and input as a `boolean` */
|
||||
export type PluginSettingBoolean<T = boolean> = PluginSettingCommon & {
|
||||
type: "boolean";
|
||||
|
||||
/** The current `value` */
|
||||
value?: T;
|
||||
};
|
||||
|
||||
/** `PluginStatus` is displayed via an indicator on the `/settings` page */
|
||||
export type PluginStatus = {
|
||||
/** Determines the text displayed next to the `indicator` icon */
|
||||
text?: string;
|
||||
|
||||
/** Determines the `indicator` color and icon */
|
||||
indicator?: "success" | "error" | "warning" | "info" | "loading";
|
||||
};
|
||||
|
||||
/** `PluginSettings` is a map of the settings your plugin will show on the `/settings` page */
|
||||
export type PluginSettings = {
|
||||
/** Each setting needs a unique `key` */
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
[settingKey: string]: PluginSetting<any>;
|
||||
};
|
||||
|
||||
/** Useful for strictly-typing things */
|
||||
export type PluginTypeHelper = { settings?: PluginSettings };
|
||||
export type PluginTypeHelperDefault = { settings: undefined };
|
||||
|
||||
/** The `Plugin` type defines the API which StableStudio uses to provide functionality via plugins */
|
||||
export type Plugin<P extends PluginTypeHelper = PluginTypeHelperDefault> = {
|
||||
/** You should provide a `PluginManifest`, otherwise the UI shows a warning */
|
||||
manifest?: PluginManifest;
|
||||
|
||||
/** The most fundamental function needed for stable diffusion generations */
|
||||
createStableDiffusionImages?: (options?: {
|
||||
/** The `StableDiffusionInput` you've been asked to generate, if empty, you could still return a random image */
|
||||
input?: StableDiffusionInput;
|
||||
|
||||
/** Determines how many images will be created using the given `StableDiffusionInput` */
|
||||
count?: number;
|
||||
}) => MaybePromise<StableDiffusionImages | undefined>;
|
||||
|
||||
/** This function provides historical access to generated images. If omitted, the app will lose its history on refresh */
|
||||
getStableDiffusionExistingImages?: (options?: {
|
||||
/** How many images the UI is requesting */
|
||||
limit?: number;
|
||||
|
||||
/** The `ID` of last image the UI has access to, it should be omitted from the response */
|
||||
exclusiveStartImageID?: ID;
|
||||
}) => MaybePromise<StableDiffusionImages[] | undefined>;
|
||||
|
||||
/** If more than one `StableDiffusionModel`, you can return them via this function and they will be presented as a dropdown in the UI */
|
||||
getStableDiffusionModels?: () => MaybePromise<
|
||||
StableDiffusionModel[] | undefined
|
||||
>;
|
||||
|
||||
/** If more than one `StableDiffusionStyle`, you can return them via this function and they will be presented as a dropdown in the UI */
|
||||
getStableDiffusionStyles?: () => MaybePromise<
|
||||
StableDiffusionStyle[] | undefined
|
||||
>;
|
||||
|
||||
/** Determines the default count passed to `createStableDiffusionImages` */
|
||||
getStableDiffusionDefaultCount?: () => number | undefined;
|
||||
|
||||
/** Determines the default input passed to `createStableDiffusionImages` and is also used when setting up a new generation */
|
||||
getStableDiffusionDefaultInput?: () => StableDiffusionInput | undefined;
|
||||
|
||||
/** If you support deleting existing images by `ID`, this function will enable a deletion UI */
|
||||
deleteStableDiffusionImages?: (options?: {
|
||||
imageIDs?: ID[];
|
||||
}) => MaybePromise<void>;
|
||||
|
||||
/** Determines whether to display a `PluginStatus` and sets its contents */
|
||||
getStatus?: () => MaybePromise<PluginStatus | undefined>;
|
||||
|
||||
/** If your plugin has `settings` you want to make available on the `/settings page, you can declare them here` */
|
||||
settings?: P["settings"];
|
||||
|
||||
/** Handles changes in `settings`, you'll need to actually use Zustand's `set` to persist the change */
|
||||
setSetting?: (
|
||||
settingKey: keyof P["settings"],
|
||||
value: string | number | boolean
|
||||
) => void;
|
||||
} & P;
|
||||
|
||||
export type StableDiffusionInput = {
|
||||
prompts?: StableDiffusionPrompt[];
|
||||
|
||||
/** If `getStableDiffusionModels` is available and a `StableDiffusionModel` is selected, this is its `ID` */
|
||||
model?: ID;
|
||||
|
||||
/** If `getStableDiffusionStyles` is available and a `StableDiffusionStyle` is selected, this is its `ID` */
|
||||
style?: ID;
|
||||
|
||||
width?: number;
|
||||
height?: number;
|
||||
|
||||
cfgScale?: number;
|
||||
steps?: number;
|
||||
seed?: number;
|
||||
|
||||
/** `StableDiffusionInputImage` in the form of a black and white mask used for in-painting and out-painting */
|
||||
maskImage?: StableDiffusionInputImage;
|
||||
|
||||
/** `StableDiffusionInputImage` which is used for image-to-image generations such as creating variations */
|
||||
initialImage?: StableDiffusionInputImage;
|
||||
};
|
||||
|
||||
export type StableDiffusionPrompt = {
|
||||
text?: string;
|
||||
|
||||
/** Value between `-1` and `1` */
|
||||
weight?: number;
|
||||
};
|
||||
|
||||
/** This controls how a `StableDiffusionModel` is displayed in the UI */
|
||||
export type StableDiffusionModel = {
|
||||
id: ID;
|
||||
name?: string;
|
||||
description?: string;
|
||||
image?: URLString;
|
||||
};
|
||||
|
||||
/** This controls how a `StableDiffusionStyle` is displayed in the UI */
|
||||
export type StableDiffusionStyle = {
|
||||
id: ID;
|
||||
name?: string;
|
||||
description?: string;
|
||||
image?: URLString;
|
||||
};
|
||||
|
||||
export type StableDiffusionInputImage = {
|
||||
blob?: Blob;
|
||||
|
||||
/** Value between `0` and `1` */
|
||||
weight?: number;
|
||||
};
|
||||
|
||||
/** Since multiple images can be generated at once, this is how they are grouped */
|
||||
export type StableDiffusionImages = {
|
||||
id: ID;
|
||||
|
||||
/** If `exclusiveStartImageID` is set, this means more images exist for this group and the `ID` is passed to `getStableDiffusionExistingImages` */
|
||||
exclusiveStartImageID?: ID;
|
||||
|
||||
images?: StableDiffusionImage[];
|
||||
};
|
||||
|
||||
export type StableDiffusionImage = {
|
||||
id: ID;
|
||||
|
||||
createdAt?: Date;
|
||||
|
||||
/** The `StableDiffusionInput` used to create this image */
|
||||
input?: StableDiffusionInput;
|
||||
|
||||
blob?: Blob;
|
||||
};
|
||||
|
||||
/** Allows both asynchronous and synchronous return types */
|
||||
type MaybePromise<T> = T | Promise<T>;
|
||||
|
||||
/** In this context, an `ID` represents a unique-within-this-plugin `ID`, no schema is enforced */
|
||||
export type ID = string;
|
||||
|
||||
/** A valid URL */
|
||||
export type URLString = string;
|
||||
|
||||
/** Markdown string which is rendered as markdown in the UI */
|
||||
export type Markdown = string;
|
|
@ -0,0 +1 @@
|
|||
export * from "./Plugin";
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"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 }
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
{ "extends": ["../../.eslintrc.json"] }
|
|
@ -0,0 +1,3 @@
|
|||
stats.html
|
||||
|
||||
dist
|
|
@ -0,0 +1,21 @@
|
|||
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.
|
|
@ -0,0 +1,341 @@
|
|||
<div align="center">
|
||||
|
||||
# 🎨 UI
|
||||
|
||||
**🗺 Contents – [ℹ️ About](#about) · [🦾 Technology](#technology) · [🏗 Structure](#structure) · [🤝 Conventions](#conventions)**
|
||||
|
||||
**[⬆️ Top-Level README](../../README.md)**
|
||||
|
||||
![ManStandingBeforeUI](../../misc/ManStandingBeforeUI.png)
|
||||
|
||||
</div>
|
||||
|
||||
# <a id="about" href="#about">ℹ️ About</a>
|
||||
|
||||
_Welcome to the UI package for StableStudio!_
|
||||
|
||||
**If you're ready to dive in and make changes, be sure to read about [technology](#technology), [structure](#structure), [conventions](#conventions), and [plugins](../stablestudio-plugin/README.md) first.**
|
||||
|
||||
## 📜 History
|
||||
|
||||
StableStudio represents a new direction for [DreamStudio](https://dreamstudio.ai) with renewed focus on open-source and community-driven development, but the project has an interesting backstory...
|
||||
|
||||
- **Pre-Stable Diffusion Launch**
|
||||
|
||||
_Summer 2022_
|
||||
|
||||
[DreamStudio](https://dreamstudio.ai) began as passion-project by [@nin](https://twitter.com/nin_artificial) with the goal of creating an all-in-one creative studio for generative animations using Disco Diffusion. He and several collaborators wrote the original UI using Vue.js and a local Python back-end. With the imminent arrival of Stable Diffusion, focus shifted toward creating an easy-to-use interface for image generation so the release of the model would be as accessible as possible.
|
||||
|
||||
- **Post-Stable Diffusion Launch**
|
||||
|
||||
_August 2022 – November 2022_
|
||||
|
||||
Following the release of Stable Diffusion, [DreamStudio](https://dreamstudio.ai) served as a vehicle for new models and features shipped by [Stability AI](http://stability.ai). This period saw the introduction of [in-painting](https://platform.stability.ai/docs/features/inpainting?tab=typescript), [out-painting](https://platform.stability.ai/docs/features/inpainting?tab=typescript), and [image-to-image](https://platform.stability.ai/docs/features/image-to-image?tab=typescript).
|
||||
|
||||
- **React**
|
||||
|
||||
_December 2022 – April 2023_
|
||||
|
||||
In early December, work began on a new infinite-canvas version of the existing editor. Given the need to manage complicated state and side effects declaratively, the decision was made to switch the editor to React. Once a working editor MVP was finished, the opportunity was taken to rewrite the entire app while also shipping a re-imagined UX.
|
||||
|
||||
- **StableStudio**
|
||||
|
||||
_Present – Future_
|
||||
|
||||
The breakneck speed of the Stable Diffusion community has proven distributing generative AI is better achieved through open-source development. We're hopeful StableStudio can serve as a hub for community collaboration and a home for exciting new features.
|
||||
|
||||
# <a id="technology" href="#technology">🦾 Technology</a>
|
||||
|
||||
![SorcererWithReact](../../misc/SorcererWithReact.png)
|
||||
|
||||
- **[TypeScript](https://www.typescriptlang.org/)** – Type safety ftw!
|
||||
|
||||
- **[Vite](https://vitejs.dev/)** – Bundler and live-development tool. You can see the full config in [`vite.config.ts`](./vite.config.ts)
|
||||
|
||||
- **[React](https://reactjs.org/)** – We're using React with modern hooks and functional components
|
||||
|
||||
- **[Zustand](https://docs.pmnd.rs/zustand/getting-started/introduction)** – Extremely fast and easy-to-use state management, it's powerful and tiny!
|
||||
|
||||
- **[Tailwind](https://tailwindcss.com/)** – Our prefered method of styling components, the config is at [`tailwind.config.js`](./tailwind.config.cjs)
|
||||
|
||||
- **[Emotion](https://emotion.sh/docs/introduction)** – For when we need to break free of Tailwind and write "native CSS"
|
||||
|
||||
# <a id="structure" href="#structure">🏗 Structure</a>
|
||||
|
||||
![CyberPyramid](../../misc/CyberPyramid.png)
|
||||
|
||||
## 🧱 Domain-Driven Design
|
||||
|
||||
**The most important aspect of this codebase's structure is adherence to domain-driven design.**
|
||||
|
||||
This means we organize code around the _concepts_ rather than technical implementation details.
|
||||
|
||||
For example, if we identify a _concept_, let's say `User`, we would create a `User` "domain."
|
||||
|
||||
The `User` domain would _own_ all user-related code, including visual representation, state, hooks, etc.
|
||||
|
||||
Most domains are _composed_ of smaller domains; a hypothetical `User` domain might be composed of `User.State`, `User.Avatar`, `User.Preferences`, `User.Details`, etc.
|
||||
|
||||
_This structure is fractal in nature,_ meaning `User.Details` might itself be composed of `User.Details.SocialMedia`, `User.Details.ContactInformation`, `User.Details.UpdateRequest`, etc.
|
||||
|
||||
### \*️⃣ Domain Syntax
|
||||
|
||||
Here's an example of how we might represent a `User` domain in code...
|
||||
|
||||
```tsx
|
||||
import { Avatar } from "./Avatar";
|
||||
import { Preferences } from "./Preferences";
|
||||
import { Details } from "./Details";
|
||||
|
||||
export type User = {
|
||||
id: ID;
|
||||
avatar?: User.Avatar;
|
||||
preferences?: User.Preferences;
|
||||
details?: User.Details;
|
||||
};
|
||||
|
||||
export function User({ id }: User.Props) {
|
||||
const user = User.use(id);
|
||||
return (
|
||||
<>
|
||||
<User.Avatar avatar={avatar} />
|
||||
<User.Preferences preferences={preferences} />
|
||||
<User.Details details={details} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export declare namespace User {
|
||||
export { Avatar, Preferences, Details };
|
||||
}
|
||||
|
||||
export namespace User {
|
||||
User.Avatar = Avatar;
|
||||
User.Preferences = Preferences;
|
||||
User.Details = Details;
|
||||
|
||||
export type Props = {
|
||||
id?: ID;
|
||||
};
|
||||
|
||||
export const use = (id: ID) => {
|
||||
// Make an API call for the user or something
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
This syntax takes advantage of TypeScript's declaration merging feature to enable nice fluent-style APIs for domains...
|
||||
|
||||
```tsx
|
||||
import { User } from "./User";
|
||||
|
||||
// You can use `User` as a type
|
||||
|
||||
const bob: User = { id: "bob" };
|
||||
|
||||
function App(id: ID) {
|
||||
// You can use `User` as a namespace
|
||||
|
||||
const user = User.use(id);
|
||||
const userPreferences = User.Preferences.use(id);
|
||||
|
||||
// You can use `User` as a component
|
||||
|
||||
return (
|
||||
<>
|
||||
<User id={user.id} />
|
||||
<User.Preferences id={user.id} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
Here is an example of a real domain ([`Editor.Camera`](./src/Editor/Camera/index.tsx)) you'll find in the app...
|
||||
|
||||
```tsx
|
||||
// Owner of all things camera-related in the editor
|
||||
Editor.Camera;
|
||||
|
||||
// Centers the camera in the editor
|
||||
Editor.Camera.Center;
|
||||
|
||||
// The hand tool is used for panning around
|
||||
Editor.Camera.Hand;
|
||||
|
||||
// For resetting the camera to the default view
|
||||
Editor.Camera.Reset;
|
||||
|
||||
// Specifies keyboard shortcuts for camera actions
|
||||
Editor.Camera.Shortcuts;
|
||||
|
||||
// Controls the zoom level of the camera and mouse wheel controls
|
||||
Editor.Camera.Zoom;
|
||||
```
|
||||
|
||||
Quick note about the `export declare namespace User` syntax from the first example...
|
||||
|
||||
This is needed when a namespace exports a type.
|
||||
|
||||
It's an unfortunate bit of syntax which might [not be needed](https://github.com/microsoft/TypeScript/issues/39865) in the future.
|
||||
|
||||
If you want to discuss this further, please check out [this issue](https://github.com/Stability-AI/StableStudio/issues/7).
|
||||
|
||||
### 📁 Directories and Files
|
||||
|
||||
_Domains are usually correlated one-to-one with file/folder structure._
|
||||
|
||||
For example, the [`Editor.Camera`](./src/Editor/Camera/index.tsx) domain mentioned above is composed of the following files...
|
||||
|
||||
```
|
||||
./src/Editor/Camera/
|
||||
├── Center.tsx
|
||||
├── Hand.tsx
|
||||
├── Reset.tsx
|
||||
├── Shortcut.tsx
|
||||
├── Zoom.tsx
|
||||
└── index.tsx
|
||||
```
|
||||
|
||||
This means if you see a domain like [`Generation.Image.Download`](./src/Generation/Image/Download/index.tsx), you can expect to find it at `./src/Generation/Image/Download`.
|
||||
|
||||
All root-level domains located at the top-level of the [`./src`](./src) folder and can be imported using the shorthand syntax...
|
||||
|
||||
```ts
|
||||
import { ExampleDomain } from "~/ExampleDomain";
|
||||
|
||||
import { ExampleDomain } from "../../../../../ExampleDomain";
|
||||
// ^ If you were deep in the folder tree, it would look like this without the `~` alias
|
||||
```
|
||||
|
||||
### 📋 Structuring Tips
|
||||
|
||||
- **Look for repeated references to a word or concept**
|
||||
|
||||
For example, if you're working in a `User` domain and find yourself using the word "avatar" a lot, you might want to create a `User.Avatar` domain
|
||||
|
||||
- **Compound words are structuring hints**
|
||||
|
||||
Domains like `DeviceInformation` might be better represented as `Device.Information`.
|
||||
|
||||
- **Plural domains are very important**
|
||||
|
||||
The singular [`Generation.Image.Input`](./src/Generation/Image/Input/index.tsx) domain owns everything related to the concept of what's being fed to an image generation, but [`Generation.Image.Inputs`](./src/Generation/Image/index.tsx) owns the state of all inputs as a collective.
|
||||
|
||||
Plural domains are usually exported at the same level as their singular counterparts, such as [`Editor.Dream`](./src/Editor/Dream/index.tsx) and [`Editor.Dreams`](./src/Editor/Dream/Dreams.tsx).
|
||||
|
||||
### ⭐️ Important Domains
|
||||
|
||||
- **[`App`](./src/App/index.tsx)** – Owner of app-level functionality such as the React root, sidebars, providers, etc.
|
||||
|
||||
- **[`Generation.Image`](./src/Generation/Image/index.tsx)** – Likely the largest domain, owns all things related to image generation
|
||||
- **[`Generation.Image.Session`](./src/Generation/Image/Session/index.tsx)** – Domain which was poorly named and grew too large as a result, manages the active "image generation session"
|
||||
- **[`Editor`](./src/GlobalVariables/index.tsd)** – Home of all editor functionality
|
||||
- **[`Plugin`](./src/Plugin/index.ts)** – Owner of plugin setup and access, contains the important `Plugin.use` hook
|
||||
- **[`Theme`](./src/Theme/index.ts)** – Contains the StableStudio's design system and common components such as `Theme.Icon`, `Theme.Button`, etc.
|
||||
- **[`Shortcut`](./src/Shortcut/index.ts)** – Contains the StableStudio's keyboard shortcut system and menu
|
||||
- **[`GlobalState`](./src/GlobalState/index.ts)** – Mostly a pass-through wrapper around [Zustand](https://docs.pmnd.rs/zustand/getting-started/introduction)
|
||||
- <span id="global-variables">**[`GlobalVariables`](./src/GlobalVariables/index.ts)**</span> – Extremely useful functions and types available across the StableStudio without needing any imports (`css`, `classes`, `useEffect`, etc.)
|
||||
|
||||
# <a id="conventions" href="#conventions">🤝 Conventions</a>
|
||||
|
||||
![RobotsHoldingHands](../../misc/RobotsHoldingHands.png)
|
||||
|
||||
## 💅 Styles and CSS
|
||||
|
||||
Most styling in StableStudio is implemented with [Tailwind CSS](https://tailwindcss.com/).
|
||||
|
||||
The [`Theme`](./src/Theme/index.ts) domain contains a bunch of useful pre-made components, make sure to check there first if you need something "off-the-shelf."
|
||||
|
||||
You can use the [`classes`](#global-variables) function anywhere without imports if you need conditional styling or to break apart class names...
|
||||
|
||||
```tsx
|
||||
function Example({
|
||||
isEmphasized,
|
||||
isDisabled,
|
||||
children,
|
||||
}: PropsWithChildren<{
|
||||
isEmphasized?: boolean;
|
||||
isDisabled: boolean;
|
||||
}>) {
|
||||
return (
|
||||
<div
|
||||
className={classes(
|
||||
"bg-gray-100",
|
||||
isEmphasized && "bg-red-500 text-4xl font-bold",
|
||||
isDisabled && "text-xs opacity-50"
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
You can always "break glass" and use raw CSS via the globally-available `css` function if you need to, but please try to avoid it...
|
||||
|
||||
```tsx
|
||||
function Example() {
|
||||
return (
|
||||
<div
|
||||
css={css`
|
||||
::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
`}
|
||||
>
|
||||
Hello, World!
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## 🏛 State Management via [Zustand](https://docs.pmnd.rs/zustand/getting-started/introduction)
|
||||
|
||||
StableStudio uses [Zustand](https://docs.pmnd.rs/zustand/getting-started/introduction) for state management, which is honestly super cool.
|
||||
|
||||
It's fast and small, you can read through the whole codebase in a few minutes.
|
||||
|
||||
We originally used [Recoil](https://recoiljs.org/) it couldn't handle "hot" paths nearly as well.
|
||||
|
||||
Whenever you need globally-available state, you can use the [`GlobalState`](./src/GlobalState/index.ts) domain, which wraps Zustand...
|
||||
|
||||
```tsx
|
||||
import { GlobalState } from "~/GlobalState";
|
||||
|
||||
function Count() {
|
||||
const count = Count.use();
|
||||
const setCount = Count.useSet();
|
||||
return (
|
||||
<div>
|
||||
<button onClick={() => setCount(count + 1)}>Increment</button>
|
||||
<span>{count}</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export namespace Count {
|
||||
export const use = State.use(({ count }) => count);
|
||||
export const useSet = () =>
|
||||
State.use(({ setCount }) => setCount, GlobalState.shallow);
|
||||
}
|
||||
|
||||
type State = {
|
||||
count: number;
|
||||
setCount: (count: number) => void;
|
||||
};
|
||||
|
||||
namespace State {
|
||||
const store = GlobalState.create<State>((set) => ({
|
||||
count: 0,
|
||||
setCount: (count) => set({ count }),
|
||||
}));
|
||||
|
||||
export const use = store;
|
||||
}
|
||||
```
|
||||
|
||||
Notice how the `Count` domain exports `Count.use` and `Count.useSet` instead of exporting its state directly.
|
||||
|
||||
This allows us to change the state implementation without breaking any code that uses it.
|
||||
|
||||
Finally, you can see `GlobalState.shallow` used to [limit rerenders](https://github.com/pmndrs/zustand#selecting-multiple-state-slices).
|
|
@ -0,0 +1,29 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>StableStudio</title>
|
||||
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no, viewport-fit=cover" />
|
||||
|
||||
<link rel="stylesheet" href="./src/Theme/index.css" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<link
|
||||
rel="preload"
|
||||
href="Inter.ttf"
|
||||
as="font"
|
||||
type="font/ttf"
|
||||
crossorigin
|
||||
/>
|
||||
</head>
|
||||
<body>
|
||||
<div
|
||||
id="tooltip-root"
|
||||
class="dark h-[100vh] w-[100vw] overflow-hidden text-white"
|
||||
></div>
|
||||
<div id="modal-root" class="dark overflow-hidden text-white"></div>
|
||||
<div id="app" class="dark"></div>
|
||||
|
||||
<script type="module" src="/src/index.tsx"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,97 @@
|
|||
{
|
||||
"name": "@stability/stablestudio-ui",
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"clean": "rimraf dist && rimraf node_modules",
|
||||
"lint": "eslint \"./src/**/*.{ts,tsx}\"",
|
||||
"lint:fix": "yarn lint --fix",
|
||||
"build:types": "tsc --noEmit",
|
||||
"build": "yarn build:preview",
|
||||
"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"
|
||||
},
|
||||
"dependencies": {
|
||||
"@emotion/css": "^11.10.5",
|
||||
"@emotion/react": "^11.10.5",
|
||||
"@emotion/styled": "^11.10.5",
|
||||
"@react-hook/resize-observer": "^1.2.6",
|
||||
"@reecelucas/react-use-hotkeys": "^2.0.0",
|
||||
"@stability/stablestudio-plugin": "workspace:^",
|
||||
"@stability/stablestudio-plugin-example": "workspace:^",
|
||||
"@stability/stablestudio-plugin-stability": "workspace:^",
|
||||
"@tanstack/react-query": "^4.22.0",
|
||||
"@tanstack/react-query-devtools": "^4.22.0",
|
||||
"@tanstack/react-virtual": "beta",
|
||||
"buffer": "^6.0.3",
|
||||
"date-fns": "^2.29.3",
|
||||
"file-saver": "^2.0.5",
|
||||
"flexsearch": "^0.7.31",
|
||||
"framer-motion": "^8.5.0",
|
||||
"idb-keyval": "^6.2.0",
|
||||
"immer": "^9.0.18",
|
||||
"jszip": "^3.10.1",
|
||||
"konva": "^8.4.2",
|
||||
"lodash.throttle": "^4.1.1",
|
||||
"lucide-react": "^0.105.0",
|
||||
"minisearch": "^6.0.0",
|
||||
"notistack": "^3.0.0-alpha.11",
|
||||
"query-string": "^8.1.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-konva": "^18.2.3",
|
||||
"react-konva-utils": "^0.3.1",
|
||||
"react-markdown": "^8.0.7",
|
||||
"react-router-dom": "^6.7.0",
|
||||
"react-slider": "^2.0.4",
|
||||
"react-syntax-highlighter": "^15.5.0",
|
||||
"react-use": "^17.4.0",
|
||||
"react-virtualized-auto-sizer": "^1.0.7",
|
||||
"react-window": "^1.8.8",
|
||||
"remark-custom-heading-id": "^1.0.0",
|
||||
"remark-gfm": "^3.0.1",
|
||||
"tailwind-merge": "^1.8.1",
|
||||
"throttled-queue": "^2.1.4",
|
||||
"tiny-invariant": "^1.3.1",
|
||||
"ts-custom-error": "^3.3.1",
|
||||
"unified": "^10.1.2",
|
||||
"zundo": "beta",
|
||||
"zustand": "^4.3.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tailwindcss/typography": "^0.5.9",
|
||||
"@types/file-saver": "^2.0.5",
|
||||
"@types/lodash.throttle": "^4.1.7",
|
||||
"@types/react": "^18.0.27",
|
||||
"@types/react-dom": "^18.0.10",
|
||||
"@types/react-slider": "^1.3.1",
|
||||
"@types/react-syntax-highlighter": "^15.5.6",
|
||||
"@types/react-virtualized-auto-sizer": "^1.0.1",
|
||||
"@types/react-window": "^1.8.5",
|
||||
"@typescript-eslint/eslint-plugin": "^5.48.2",
|
||||
"@typescript-eslint/parser": "^5.48.2",
|
||||
"@vitejs/plugin-react": "^3.0.1",
|
||||
"autoprefixer": "^10.4.13",
|
||||
"eslint": "8.32.0",
|
||||
"eslint-config-prettier": "^8.6.0",
|
||||
"eslint-plugin-import": "^2.27.5",
|
||||
"eslint-plugin-markdown": "^3.0.0",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
"eslint-plugin-react": "^7.32.1",
|
||||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"postcss": "^8.4.21",
|
||||
"prettier": "^2.8.3",
|
||||
"prettier-plugin-tailwindcss": "^0.2.1",
|
||||
"rimraf": "^4.1.1",
|
||||
"rollup-plugin-visualizer": "^5.9.0",
|
||||
"tailwindcss": "^3.2.4",
|
||||
"tsx": "^3.12.2",
|
||||
"typescript": "4.9.4",
|
||||
"typescript-styled-plugin": "^0.18.2",
|
||||
"vite": "^4.0.4",
|
||||
"vite-tsconfig-paths": "^4.0.5"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
// This project includes code from `caniuse-lite` by Ben Briggs, available under a CC BY 4.0 license.
|
||||
// The original work can be found at the repository: https://github.com/browserslist/caniuse-lite.
|
||||
|
||||
module.exports = {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
},
|
||||
};
|
After Width: | Height: | Size: 957 B |
After Width: | Height: | Size: 489 KiB |
|
@ -0,0 +1,52 @@
|
|||
var l = (t) => {
|
||||
let e,
|
||||
i = new Set(),
|
||||
r = (o, u) => {
|
||||
let s = typeof o == "function" ? o(e) : o;
|
||||
if (!Object.is(s, e)) {
|
||||
let g = e;
|
||||
(e = u ?? typeof s != "object" ? s : Object.assign({}, e, s)),
|
||||
i.forEach((p) => p(e, g));
|
||||
}
|
||||
},
|
||||
a = () => e,
|
||||
n = {
|
||||
setState: r,
|
||||
getState: a,
|
||||
subscribe: (o) => (i.add(o), () => i.delete(o)),
|
||||
destroy: () => {
|
||||
(import.meta.env && import.meta.env.MODE) !== "production" &&
|
||||
console.warn(
|
||||
"[DEPRECATED] The `destroy` method will be unsupported in a future version. Instead use unsubscribe function returned by subscribe. Everything will be garbage-collected if store is garbage-collected."
|
||||
),
|
||||
i.clear();
|
||||
},
|
||||
};
|
||||
return (e = t(r, a, n)), n;
|
||||
},
|
||||
d = (t) => (t ? l(t) : l),
|
||||
c = (t) => (e) => d((i, r) => t({ set: i, get: r, context: e }));
|
||||
var m = c(() => ({
|
||||
manifest: {
|
||||
name: "Example Plugin",
|
||||
description: "An example plugin for StableStudio",
|
||||
version: "1.2.3",
|
||||
author: "Bobby Joe",
|
||||
license: "MIT",
|
||||
link: "https://github.com",
|
||||
icon: "https://place.dog/100/100",
|
||||
},
|
||||
getStatus: () => ({
|
||||
indicator: "success",
|
||||
message: "This plugin is working",
|
||||
}),
|
||||
settings: {
|
||||
exampleSetting: {
|
||||
type: "string",
|
||||
default: "Hello, World!",
|
||||
placeholder: "Example setting",
|
||||
},
|
||||
},
|
||||
}));
|
||||
export { m as createPlugin };
|
||||
//# sourceMappingURL=index.js.map
|
|
@ -0,0 +1,52 @@
|
|||
var l = (t) => {
|
||||
let e,
|
||||
i = new Set(),
|
||||
r = (o, u) => {
|
||||
let s = typeof o == "function" ? o(e) : o;
|
||||
if (!Object.is(s, e)) {
|
||||
let g = e;
|
||||
(e = u ?? typeof s != "object" ? s : Object.assign({}, e, s)),
|
||||
i.forEach((p) => p(e, g));
|
||||
}
|
||||
},
|
||||
a = () => e,
|
||||
n = {
|
||||
setState: r,
|
||||
getState: a,
|
||||
subscribe: (o) => (i.add(o), () => i.delete(o)),
|
||||
destroy: () => {
|
||||
(import.meta.env && import.meta.env.MODE) !== "production" &&
|
||||
console.warn(
|
||||
"[DEPRECATED] The `destroy` method will be unsupported in a future version. Instead use unsubscribe function returned by subscribe. Everything will be garbage-collected if store is garbage-collected."
|
||||
),
|
||||
i.clear();
|
||||
},
|
||||
};
|
||||
return (e = t(r, a, n)), n;
|
||||
},
|
||||
d = (t) => (t ? l(t) : l),
|
||||
c = (t) => (e) => d((i, r) => t({ set: i, get: r, context: e }));
|
||||
var m = c(() => ({
|
||||
// manifest: {
|
||||
// name: "Example Plugin",
|
||||
// description: "An example plugin for StableStudio",
|
||||
// version: "1.2.3",
|
||||
// author: "Bobby Joe",
|
||||
// license: "MIT",
|
||||
// link: "https://github.com",
|
||||
// icon: "place.dog/100/100",
|
||||
// },
|
||||
getStatus: () => ({
|
||||
indicator: "success",
|
||||
message: "This plugin is working",
|
||||
}),
|
||||
settings: {
|
||||
exampleSetting: {
|
||||
type: "string",
|
||||
default: "Hello, World!",
|
||||
placeholder: "Example setting",
|
||||
},
|
||||
},
|
||||
}));
|
||||
export { m as createPlugin };
|
||||
//# sourceMappingURL=index.js.map
|
After Width: | Height: | Size: 333 KiB |
After Width: | Height: | Size: 406 KiB |
After Width: | Height: | Size: 477 KiB |
After Width: | Height: | Size: 419 KiB |
After Width: | Height: | Size: 351 KiB |