Skip to content

Commit aeeae20

Browse files
committed
neutral theme, comfy auth, dynamic workflows
1 parent 3635e59 commit aeeae20

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+760
-486
lines changed

documentation/design/README.md

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# Design
2+
3+
(those are just quick notes for now, we can elaborate later)
4+
5+
## Designing Clapper for the Web
6+
7+
### Targeted devices
8+
9+
Currently Clapper works best on a laptop,
10+
since the UI has been developed around the presence of a relatively wide screen,
11+
a mouse and a touch pad (for horizontal scrolling in the timeline).
12+
13+
However I think we should try to better support the following environments:
14+
15+
- Tiny laptop (12", 11")
16+
- Tablet (without a mouse)
17+
- Desktop computer with multiple screens
18+
19+
(mobile has its own chapter, see below in this document)
20+
21+
### Use Web APIs in priority
22+
23+
We should try to use standard Web APIs (ratified by the W3C) as much as possible, with polyfills in case some browsers don't implement them yet.
24+
25+
We can use experimental standards (eg. WebGPU),
26+
but since they are unstable and not supported by all browsers, they should not be mandatory to the experience.
27+
28+
## Designing Clapper for desktop
29+
30+
The experience on Desktop should be similar to the one in a browser, but we can do some changes:
31+
32+
### Customizing the look of the app window
33+
34+
Electron offers us to hide or customize the app's window, so we should do it.
35+
36+
We don't have to follow the design principles of the underlying operating system (some apps don't care eg. video games, Spotify, Slack, FLStudio, Discord..) but it may be necessary for some operations (file pickers, installer, window management etc).
37+
38+
### Use the native file system
39+
40+
The big benefit of running Clapper as a desktop application is that we can access the file system, meaning we can work with files of arbitrary file length (note: for this kind of file system manipulation, we will have to use extra code eg. NodeJS)
41+
42+
This can also be used for performance optimization such as using temporary files, or pre-computing things and store them in a cache for the next time Clapper is opened.
43+
44+
### Download additional data for local use
45+
46+
By running Clapper on the user's device, we can also make it download data of arbitrary size.
47+
48+
This can help with various use cases, such as running AI models locally.
49+
50+
For instance the desktop app LMStudio can download models from Hugging Face.
51+
52+
### Call external or embedded native libraries
53+
54+
We have complete freedom to ship Clapper with embedded native tools eg. a database or a native library (eg. a C++ library to run a LLM locally).
55+
56+
We could even use Python scripts with Clapper.
57+
58+
Please note however that we will have to make sure anything we embed works on various operating systems (Windows/macOS/Linux) so this requires dedicated skills and maintenance.
59+
60+
### Use System Notifications
61+
62+
When a job is pending, finished, a software update is ready etc.
63+
64+
## Clapper Design For Mobile
65+
66+
Currently Clapper can *run* on mobile, but it is not designed for it.
67+
68+
So things like the top menu etc will be pretty much unuseable, unless we adapt them.
69+
70+

package-lock.json

Lines changed: 31 additions & 16 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
"dependencies": {
3939
"@aitube/broadway": "0.2.3",
4040
"@aitube/clap": "0.2.3",
41-
"@aitube/clapper-services": "0.2.3-1",
41+
"@aitube/clapper-services": "0.2.3-2",
4242
"@aitube/client": "0.2.3",
4343
"@aitube/engine": "0.2.3",
4444
"@aitube/timeline": "0.2.3",
@@ -60,7 +60,7 @@
6060
"@radix-ui/react-avatar": "^1.0.4",
6161
"@radix-ui/react-checkbox": "^1.0.4",
6262
"@radix-ui/react-collapsible": "^1.0.3",
63-
"@radix-ui/react-dialog": "^1.0.5",
63+
"@radix-ui/react-dialog": "^1.1.1",
6464
"@radix-ui/react-dropdown-menu": "^2.0.6",
6565
"@radix-ui/react-icons": "^1.3.0",
6666
"@radix-ui/react-label": "^2.0.2",
@@ -93,7 +93,7 @@
9393
"class-variance-authority": "^0.7.0",
9494
"clsx": "^2.1.1",
9595
"cmdk": "^0.2.1",
96-
"comfydeploy": "^0.0.19-beta.13",
96+
"comfydeploy": "^0.0.21",
9797
"date-fns": "^3.6.0",
9898
"dotenv": "^16.4.5",
9999
"fflate": "^0.8.2",
@@ -116,6 +116,7 @@
116116
"react-dnd-html5-backend": "^16.0.1",
117117
"react-dom": "^18.3.1",
118118
"react-drag-drop-files": "^2.3.10",
119+
"react-error-boundary": "^4.0.13",
119120
"react-hook-consent": "^3.5.3",
120121
"react-hotkeys-hook": "^4.5.0",
121122
"react-icons": "^5.2.1",
@@ -126,7 +127,7 @@
126127
"replicate": "^0.32.0",
127128
"sharp": "0.33.4",
128129
"sonner": "^1.5.0",
129-
"tailwind-merge": "^2.4.0",
130+
"tailwind-merge": "^2.5.2",
130131
"tailwindcss-animate": "^1.0.7",
131132
"three": "^0.164.1",
132133
"ts-node": "^10.9.2",
@@ -136,7 +137,7 @@
136137
"web-audio-beat-detector": "^8.2.12",
137138
"yaml": "^2.4.5",
138139
"zustand": "4.5.2",
139-
"zx": "^8.1.3"
140+
"zx": "^8.1.4"
140141
},
141142
"devDependencies": {
142143
"@electron-forge/cli": "^7.4.0",

src/app/api/resolve/providers/comfy-replicate/index.ts

Lines changed: 52 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
1-
import { ClapSegmentStatus, getClapAssetSourceType } from '@aitube/clap'
1+
import {
2+
ClapSegmentCategory,
3+
ClapSegmentStatus,
4+
getClapAssetSourceType,
5+
} from '@aitube/clap'
26

37
import { ResolveRequest } from '@aitube/clapper-services'
4-
import { getComfyWorkflow } from '../comfyui/getComfyWorkflow'
8+
import { getComfyWorkflow } from '../../../../../services/editors/workflow-editor/workflows/comfyui/getComfyWorkflow'
59
import { runWorkflow } from './runWorkflow'
610
import { TimelineSegment } from '@aitube/timeline'
711

@@ -11,22 +15,55 @@ export async function resolveSegment(
1115
if (!request.settings.replicateApiKey) {
1216
throw new Error(`Missing API key for "Replicate.com"`)
1317
}
14-
const workflow = getComfyWorkflow(request)
1518

1619
const segment: TimelineSegment = request.segment
1720

18-
try {
19-
segment.assetUrl = await runWorkflow({
20-
apiKey: request.settings.replicateApiKey,
21-
workflow,
22-
})
23-
segment.assetSourceType = getClapAssetSourceType(segment.assetUrl)
24-
} catch (err) {
25-
console.error(`failed to call Replicate: `, err)
26-
segment.assetUrl = ''
27-
segment.assetSourceType = getClapAssetSourceType(segment.assetUrl)
28-
segment.status = ClapSegmentStatus.TO_GENERATE
29-
// request.segment.status = ClapSegmentStatus.ERROR
21+
if (request.segment.category === ClapSegmentCategory.STORYBOARD) {
22+
const inputFields =
23+
request.settings.imageGenerationWorkflow.inputFields || []
24+
25+
// since this is a random "wild" workflow, it is possible
26+
// that the field name is a bit different
27+
// we try to look into the workflow input fields
28+
// to find the best match
29+
const promptFields = [
30+
inputFields.find((f) => f.id === 'prompt'), // exactMatch,
31+
inputFields.find((f) => f.id.includes('prompt')), // similarName,
32+
inputFields.find((f) => f.type === 'string'), // similarType
33+
].filter((x) => typeof x !== 'undefined')
34+
35+
const promptField = promptFields[0]
36+
if (!promptField) {
37+
throw new Error(
38+
`this workflow doesn't seem to have a parameter called "prompt"`
39+
)
40+
}
41+
42+
console.log(`TODO: inject parameters into the final request object`)
43+
const workflow = `{}` // <- the final workflow sent to Replicate
44+
45+
try {
46+
segment.assetUrl = await runWorkflow({
47+
apiKey: request.settings.replicateApiKey,
48+
workflow,
49+
})
50+
segment.assetSourceType = getClapAssetSourceType(segment.assetUrl)
51+
} catch (err) {
52+
console.error(`failed to call Replicate: `, err)
53+
segment.assetUrl = ''
54+
segment.assetSourceType = getClapAssetSourceType(segment.assetUrl)
55+
segment.status = ClapSegmentStatus.TO_GENERATE
56+
// request.segment.status = ClapSegmentStatus.ERROR
57+
}
58+
} else if (request.segment.category === ClapSegmentCategory.VIDEO) {
59+
// TODO do the same for video
60+
throw new Error(
61+
`Clapper doesn't support ${request.segment.category} generation for provider "Comfy.icu". Please open a pull request with (working code) to solve this!`
62+
)
63+
} else {
64+
throw new Error(
65+
`Clapper doesn't support ${request.segment.category} generation for provider "Comfy.icu". Please open a pull request with (working code) to solve this!`
66+
)
3067
}
3168

3269
return segment

src/app/api/resolve/providers/comfyui/getComfyWorkflow.ts

Lines changed: 0 additions & 33 deletions
This file was deleted.

0 commit comments

Comments
 (0)