241 lines
7.6 KiB
JavaScript
241 lines
7.6 KiB
JavaScript
import { app } from '../../../scripts/app.js'
|
|
// import { api } from '../../../scripts/api.js'
|
|
import { ComfyWidgets } from '../../../scripts/widgets.js'
|
|
import { $el } from '../../../scripts/ui.js'
|
|
|
|
async function getConfig () {
|
|
let api_host = `${window.location.hostname}:${window.location.port}`
|
|
let api_base = ''
|
|
let url = `${window.location.protocol}//${api_host}${api_base}`
|
|
|
|
const res = await fetch(`${url}/mixlab`, {
|
|
method: 'POST'
|
|
})
|
|
return await res.json()
|
|
}
|
|
|
|
function get_position_style (ctx, widget_width, y, node_height) {
|
|
const MARGIN = 4 // the margin around the html element
|
|
|
|
/* Create a transform that deals with all the scrolling and zooming */
|
|
const elRect = ctx.canvas.getBoundingClientRect()
|
|
const transform = new DOMMatrix()
|
|
.scaleSelf(
|
|
elRect.width / ctx.canvas.width,
|
|
elRect.height / ctx.canvas.height
|
|
)
|
|
.multiplySelf(ctx.getTransform())
|
|
.translateSelf(MARGIN, MARGIN + y)
|
|
|
|
return {
|
|
transformOrigin: '0 0',
|
|
transform: transform,
|
|
left: `0`,
|
|
top: `0`,
|
|
cursor: 'pointer',
|
|
position: 'absolute',
|
|
maxWidth: `${widget_width - MARGIN * 2}px`,
|
|
// maxHeight: `${node_height - MARGIN * 2}px`, // we're assuming we have the whole height of the node
|
|
width: `${widget_width - MARGIN * 2}px`,
|
|
// height: `${node_height * 0.3 - MARGIN * 2}px`,
|
|
// background: '#EEEEEE',
|
|
display: 'flex',
|
|
flexDirection: 'column',
|
|
// alignItems: 'center',
|
|
justifyContent: 'space-around'
|
|
}
|
|
}
|
|
|
|
app.registerExtension({
|
|
name: 'Mixlab.GPT.ChatGPT',
|
|
async getCustomWidgets (app) {
|
|
return {
|
|
KEY (node, inputName, inputData, app) {
|
|
// console.log('node', inputName, inputData[0])
|
|
const widget = {
|
|
type: inputData[0], // the type, CHEESE
|
|
name: inputName, // the name, slice
|
|
size: [128, 24], // a default size
|
|
draw (ctx, node, width, y) {},
|
|
computeSize (...args) {
|
|
return [128, 24] // a method to compute the current size of the widget
|
|
},
|
|
async serializeValue (nodeId, widgetIndex) {
|
|
//localStorage.getItem('_mixlab_api_key') || ''
|
|
return 'by Mixlab'
|
|
}
|
|
}
|
|
// widget.something = something; // maybe adds stuff to it
|
|
node.addCustomWidget(widget) // adds it to the node
|
|
return widget // and returns it.
|
|
},
|
|
URL (node, inputName, inputData, app) {
|
|
// console.log('node', inputName, inputData[0])
|
|
const widget = {
|
|
type: inputData[0], // the type, CHEESE
|
|
name: inputName, // the name, slice
|
|
size: [128, 24], // a default size
|
|
draw (ctx, node, width, y) {
|
|
// a method to draw the widget (ctx is a CanvasRenderingContext2D)
|
|
},
|
|
computeSize (...args) {
|
|
return [128, 24] // a method to compute the current size of the widget
|
|
},
|
|
async serializeValue (nodeId, widgetIndex) {
|
|
return localStorage.getItem('_mixlab_api_url') || 'https://api.openai.com/v1'
|
|
}
|
|
}
|
|
// widget.something = something; // maybe adds stuff to it
|
|
node.addCustomWidget(widget) // adds it to the node
|
|
return widget // and returns it.
|
|
}
|
|
}
|
|
},
|
|
async beforeRegisterNodeDef (nodeType, nodeData, app) {
|
|
// console.log(nodeType.comfyClass)
|
|
if (nodeType.comfyClass == 'ChatGPT') {
|
|
const orig_nodeCreated = nodeType.prototype.onNodeCreated
|
|
nodeType.prototype.onNodeCreated = function () {
|
|
orig_nodeCreated?.apply(this, arguments)
|
|
|
|
console.log('ChatGPT widtget', this.widgets)
|
|
|
|
const api_key = this.widgets.filter(w => w.name == 'api_key')[0]
|
|
const api_url = this.widgets.filter(w => w.name == 'api_url')[0]
|
|
// console.log('api_key', api_key, api_url)
|
|
|
|
const widget = {
|
|
type: 'div',
|
|
name: 'chatgpt div',
|
|
draw (ctx, node, widget_width, y, widget_height) {
|
|
Object.assign(
|
|
this.div.style,
|
|
get_position_style(ctx, widget_width, api_key.y, node.size[1])
|
|
)
|
|
}
|
|
}
|
|
|
|
widget.div = $el('div', {})
|
|
|
|
document.body.appendChild(widget.div)
|
|
|
|
const inputKey = document.createElement('input'),
|
|
inputUrl = document.createElement('input')
|
|
inputKey.type = 'text'
|
|
inputUrl.type = 'text'
|
|
|
|
inputKey.placeholder = 'Key'
|
|
inputUrl.placeholder = 'URL'
|
|
|
|
inputKey.style = `margin:4px 48px;`
|
|
inputUrl.style = `margin:4px 48px`
|
|
|
|
inputUrl.value = localStorage.getItem('_mixlab_api_url') || 'https://api.openai.com/v1'
|
|
inputKey.value = localStorage.getItem('_mixlab_api_key') || 'by Mixlab'
|
|
|
|
widget.div.appendChild(inputKey)
|
|
widget.div.appendChild(inputUrl)
|
|
|
|
inputKey.addEventListener('change', () => {
|
|
api_key.serializeValue = () => inputKey.value || 'by Mixlab'
|
|
localStorage.setItem('_mixlab_api_key', inputKey.value)
|
|
})
|
|
|
|
inputUrl.addEventListener('change', () => {
|
|
api_url.serializeValue = () => inputUrl.value || 'https://api.openai.com/v1'
|
|
localStorage.setItem('_mixlab_api_url', inputUrl.value)
|
|
})
|
|
|
|
/*
|
|
Add the widget, make sure we clean up nicely, and we do not want to be serialized!
|
|
*/
|
|
this.addCustomWidget(widget)
|
|
|
|
const onRemoved = this.onRemoved
|
|
this.onRemoved = () => {
|
|
inputUrl.remove()
|
|
inputKey.remove()
|
|
widget.div.remove()
|
|
return onRemoved?.()
|
|
}
|
|
|
|
this.serialize_widgets = false
|
|
}
|
|
}
|
|
}
|
|
})
|
|
|
|
app.registerExtension({
|
|
name: 'Mixlab.GPT.ShowTextForGPT',
|
|
async beforeRegisterNodeDef (nodeType, nodeData, app) {
|
|
if (nodeData.name === 'ShowTextForGPT') {
|
|
function populate (text) {
|
|
if (this.widgets) {
|
|
// const pos = this.widgets.findIndex((w) => w.name === "text");
|
|
// if (pos !== -1) {
|
|
// for (let i = pos; i < this.widgets.length; i++) {
|
|
// this.widgets[i].onRemove?.();
|
|
// }
|
|
// this.widgets.length = pos;
|
|
// }
|
|
|
|
for (let i = 0; i < this.widgets.length; i++) {
|
|
this.widgets[i].onRemove?.()
|
|
}
|
|
this.widgets.length = 0
|
|
}
|
|
|
|
console.log('ShowTextForGPT', this.widgets, text)
|
|
|
|
for (const list of text) {
|
|
const w = ComfyWidgets['STRING'](
|
|
this,
|
|
'text',
|
|
['STRING', { multiline: true }],
|
|
app
|
|
).widget
|
|
w.inputEl.readOnly = true
|
|
w.inputEl.style.opacity = 0.6
|
|
|
|
let res = list
|
|
|
|
try {
|
|
res = JSON.stringify(JSON.parse(list), null, 2)
|
|
} catch (error) {
|
|
// console.log(list)
|
|
}
|
|
|
|
w.value = res
|
|
}
|
|
|
|
requestAnimationFrame(() => {
|
|
const sz = this.computeSize()
|
|
if (sz[0] < this.size[0]) {
|
|
sz[0] = this.size[0]
|
|
}
|
|
if (sz[1] < this.size[1]) {
|
|
sz[1] = this.size[1]
|
|
}
|
|
this.onResize?.(sz)
|
|
app.graph.setDirtyCanvas(true, false)
|
|
})
|
|
}
|
|
|
|
// When the node is executed we will be sent the input text, display this in the widget
|
|
const onExecuted = nodeType.prototype.onExecuted
|
|
nodeType.prototype.onExecuted = function (message) {
|
|
onExecuted?.apply(this, arguments)
|
|
populate.call(this, message.text)
|
|
}
|
|
|
|
const onConfigure = nodeType.prototype.onConfigure
|
|
nodeType.prototype.onConfigure = function () {
|
|
onConfigure?.apply(this, arguments)
|
|
if (this.widgets_values?.length) {
|
|
populate.call(this, this.widgets_values)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
})
|