1+ import crud from '@cocreate/crud-client'
2+ import Actions from '@cocreate/actions'
3+
4+ // todo: apikey from orgainization'
5+ // const apifromCrud = await crud.send({
6+ // array: 'organizations',
7+ // object: { _id: '' },
8+ // })
9+
10+ // console.log('test', apifromCrud)
11+ const apiKey = localStorage . getItem ( 'openAiKey' ) ;
12+ const apiUrl = 'https://api.openai.com/v1/chat/completions' ;
13+ const model = 'gpt-3.5-turbo'
14+ const max_tokens = 1024 ;
15+ const temperature = 0.6 ;
16+ const n = 1 ;
17+ const stop = '###STOP###' ;
18+
19+ const forms = new Map ( )
20+
21+ const componentsReference = {
22+ "componentsReference" : {
23+ "socket" : {
24+ "functions" : {
25+ "send" : "<data>" ,
26+ "listen" : "<method>"
27+ } ,
28+ "data" : { 'broadcast' : 'boolean' , 'broadcast-sender' : 'boolean' , 'broadcast-browser' : 'boolean' } ,
29+ "html-attributes" : [ 'broadcast' , 'broadcast-sender' , 'broadcast-browser' , 'namespace' , 'room' , 'balancer' ]
30+ } ,
31+ "crud" : {
32+ "functions" : {
33+ "send" : "<data>" ,
34+ "listen" : "<method>"
35+ } ,
36+ "methods" : [ "database.create" , "database.read" , "database.update" , "database.delete" , "array.create" , "array.read" , "array.update" , "array.delete" , "index.create" , "index.read" , "index.update" , "index.delete" , "object.create" , "object.read" , "object.update" , "object.delete" ] ,
37+ "data" : { method : "" , database : "" , array : "" , index : "" , object : { } || [ ] , filter : { } } ,
38+ "html-attributes" : [ 'storage' , 'database' , 'array' , 'object' , 'key' , 'index' , 'save' , 'read' , 'update' , 'delete' , 'realtime' , 'crud' , 'upsert' , 'value-type' , 'value-prefix' , 'value-suffix' ]
39+ } ,
40+ "filter" : {
41+ "functions" : {
42+ "getFilter" : "<filter>" ,
43+ "setFilter" : "<filter>"
44+ } ,
45+ "filter" : { query : [ { key : "" , value : "" , operator : "$eq | $ne | $includes" , logicalOperator : "" , caseSensitive : "true | false" } ] , sort : [ { key : "" , direction : "asc | desc" } ] , search : [ { value : "" , operator : "" , caseSensitive : "true | false" } ] } ,
46+ "html-attributes" : [ 'filter-selector' , 'filter-closest' , 'filter-parent' , 'filter-prvious' , 'filter-next' , 'filter-key' , 'filter-value' , 'filter-value-type' , 'filter-case-sensitive' , 'filter-operator' , 'filter-logical-opertor' , 'filter-sort-key' , 'filter-sort-direction' , 'filter-search' , 'filter-limit' , 'filter-count' , 'filter-on' ]
47+ } ,
48+ "crdt" : {
49+ "functions" : [ "init" , "getText" , "updateText" , "replaceText" , "undoText" , "redoText" ] ,
50+ "data" : { array : "" , object : "_id" , key : "" , value : "" , attribute : "bold | italic" , start : 0 , length : 0 } ,
51+ "html-attributes" : [ 'crdt' ]
52+ } ,
53+ "cursors" : {
54+ "functions" : { sendPosition : "<data>" } ,
55+ "data" : { array : [ ] , object : "_id" , key : "" , start : 0 , end : 0 } ,
56+ "html-attributes" : [ 'cursors' ]
57+ } ,
58+ "events" : {
59+ "functions" : { init : "<data>" } ,
60+ "data" : { prefix : "" , events : [ ] } ,
61+ "predefined-prefixes" : [ 'click' , 'change' , 'input' , 'onload' , 'observer' , 'mousedown' , 'mousemove' , 'mouseup' , 'toggle' , 'hover' , 'selected' ] ,
62+ "html-attributes" : [ '<prefix>-selector' , '<prefix>-selector' , '<prefix>-closest' , '<prefix>-parent' , '<prefix>-previous' , '<prefix>-next' ]
63+ } ,
64+ "pass" : {
65+ "html-attributes" : [ 'pass_to' , 'pass_id' , 'pass-<attribute>' , 'pass-overwrite' ]
66+ } ,
67+ }
68+
69+ } ;
70+
71+ async function send ( form ) {
72+ let elements = form . querySelectorAll ( '[openai]' )
73+
74+ let conversation = forms . get ( form )
75+ // if (!conversation) {
76+ // const crudReference = {
77+ // data: {
78+ // method: "database.create | database.read | database.update | database.delete | array.create | array.read | array.update | array.delete | index.create | index.read | index.update | index.delete | object.create | object.read | object.update | object.delete",
79+ // storage: "" || [""],
80+ // database: "" || [""],
81+ // array: "" || [""],
82+ // index: "" || [""],
83+ // object: {} || [{}],
84+ // filter: {
85+ // query: [{ key: "", value: "", operator: "$eq | $ne | $includes", logicalOperator: "", caseSensitive: "true | false" }],
86+ // sort: [{ key: "", direction: "asc | desc" }],
87+ // search: [{ value: "", operator: "", caseSensitive: "true | false" }]
88+ // }
89+ // }
90+ // }
91+ // const crudObjectReference = {
92+ // data: {
93+ // method: " object.create | object.read | object.update | object.delete",
94+ // array: "" || [""],
95+ // object: {} || [{}],
96+ // filter: {
97+ // query: [{ key: "", value: "", operator: "$eq | $ne | $includes", logicalOperator: "", caseSensitive: "true | false" }],
98+ // sort: [{ key: "", direction: "asc | desc" }],
99+ // search: [{ value: "", operator: "", caseSensitive: "true | false" }],
100+ // limit: 0
101+ // }
102+ // }
103+ // }
104+
105+ // const filterObjectReference = {
106+ // data: {
107+ // method: " object.create | object.read | object.update | object.delete",
108+ // array: "files",
109+ // object: [{
110+ // "_id": "",
111+ // "name": "",
112+ // "src": "",
113+ // "host": [
114+ // "*",
115+ // ],
116+ // "directory": "/",
117+ // "path": "",
118+ // "content-type": "",
119+ // "public": "true"
120+ // }]
121+ // }
122+ // }
123+
124+ // const htmlAttributesReference = {
125+ // "socket-html-attributes": ['broadcast', 'broadcast-sender', 'broadcast-browser', 'namespace', 'room', 'balancer'],
126+ // "crud-html-attributes": ['storage', 'database', 'array', 'object', 'key', 'index', 'save', 'read', 'update', 'delete', 'realtime', 'crud', 'upsert', 'value-type', 'value-prefix', 'value-suffix', 'listen'],
127+ // "filter-html-attributes": ['filter-selector', 'filter-closest', 'filter-parent', 'filter-previous', 'filter-next', 'filter-key', 'filter-value', 'filter-value-type', 'filter-case-sensitive', 'filter-operator', 'filter-logical-opertor', 'filter-sort-key', 'filter-sort-direction', 'filter-search', 'filter-limit', 'filter-count', 'filter-on'],
128+ // "render-html-attributes": ['render', 'render-selector', 'render-closest', 'render-parent', 'render-previous', 'render-next', 'render-as']
129+ // }
130+
131+ // conversation = [
132+ // { role: 'system', content: 'If the users request seem to want to perform a CRUD operation, return a CoCreateJS CRUD data object as a response. Else reply as best you can to users queries' },
133+ // { role: 'system', content: 'data.method should default to "object.create", "object.read", "object.update", "object.delete"' },
134+ // { role: 'system', content: 'To perform CRUD operations on the objects contained within an array, use the following methods: "object.create" for creating objects, "object.read" for reading and returning one or more objects, "object.update" for updating objects, and "object.delete" for deleting objects. The array property must be defined to perform crud operations on objects' },
135+ // { role: 'system', content: 'data.storage and data.database is not required and should only be defined if the user specifically requests it. example: delete test database from indexeddb storage' },
136+ // { role: 'system', content: 'In the context of CoCreateJS, an "array" corresponds to a "table" in SQL databases or a "collection" in NoSQL databases.' },
137+ // { role: 'system', content: 'In the context of CoCreateJS, an "object" corresponds to a "row" in SQL databases or a "document" in NoSQL databases.' },
138+ // { role: 'system', content: 'crud reference' + JSON.stringify(crudReference) },
139+ // { role: 'system', content: 'crud object reference' + JSON.stringify(crudObjectReference) },
140+ // { role: 'system', content: 'When using object.update or object.delete methods the data.object._id should be defined or a filter used to return and excute on matches' },
141+ // { role: 'system', content: 'file object reference' + JSON.stringify(filterObjectReference) },
142+ // { role: 'system', content: 'If the users request seem to want to create a file or code return the code/source in the data.object.src . This will make the file available over network request using the defined path' },
143+ // { role: 'system', content: 'html attributes reference' + JSON.stringify(htmlAttributesReference) },
144+ // { role: 'system', content: 'component reference' + JSON.stringify(componentsReference) },
145+
146+ // ]
147+ if ( ! conversation )
148+ forms . set ( form , conversation = [ ] )
149+ // }
150+
151+ // 3 types avialable system, user, assistant
152+ for ( let element of elements ) {
153+ let role = element . getAttribute ( 'openai' )
154+ if ( ! [ 'system' , 'user' , 'assistant' ] . includes ( role ) )
155+ continue
156+ let content = await element . getValue ( )
157+ if ( typeof content === 'string' )
158+ conversation . push ( { role, content } )
159+ // if (Array.isArray(content))
160+ // conversation.push({ role, content })
161+ if ( typeof content === 'object' ) {
162+ if ( content . method ) {
163+ let type = content . method . split ( '.' ) [ 0 ]
164+ for ( let i = 0 ; i < content [ type ] . length ; i ++ ) {
165+ if ( typeof content [ type ] [ i ] . content === 'string' )
166+ conversation . push ( { role, content : content [ type ] [ i ] . content } )
167+ else
168+ conversation . push ( { role, content : JSON . stringify ( content [ type ] [ i ] ) } )
169+ }
170+ } else
171+ conversation . push ( { role, content : JSON . stringify ( content ) } )
172+ }
173+
174+ // if (element.hasAttribute('crud')) {
175+ // // let json = JSON.parse(element.getAttribute('crud'))
176+ // // content = await crud.send()
177+ // } else {
178+ // content = await element.getValue()
179+ // }
180+
181+ // if (role === 'system' && !systemMessages.has(content)) {
182+ // systemMessages.set(content, true)
183+
184+ // if (role === 'system') {
185+ // conversation.push({ role, content })
186+
187+ // // if (content === 'componentsReference')
188+ // // conversation.push({ role, content: JSON.stringify(componentsReference) })
189+ // // else
190+ // // conversation.push({ role, content })
191+ // } else if (role === 'user' && content) {
192+ // conversation.push({ role, content })
193+ // } else if (role === 'message' && content)
194+ // conversation.push({ role: 'user', content })
195+ }
196+
197+ if ( conversation . length )
198+ sendMessage ( conversation )
199+ }
200+
201+ async function sendMessage ( messages ) {
202+ try {
203+ const requestOptions = {
204+ method : 'POST' ,
205+ headers : {
206+ 'Authorization' : `Bearer ${ apiKey } ` ,
207+ 'Content-Type' : 'application/json' ,
208+ } ,
209+ body : JSON . stringify ( {
210+ messages,
211+ max_tokens,
212+ temperature,
213+ n,
214+ stop,
215+ model
216+ } ) ,
217+ } ;
218+
219+ const response = await fetch ( apiUrl , requestOptions ) ;
220+ const data = await response . json ( ) ;
221+
222+ // const content = JSON.parse(data.choices[0].message.content);
223+ const content = data . choices [ 0 ] . message . content ;
224+ if ( content ) {
225+ console . log ( content )
226+ let responseElement = document . querySelector ( '[openai="response"]' )
227+ if ( responseElement )
228+ responseElement . setValue ( content )
229+ }
230+ // const object = extractObjectFromCode(content);
231+ // if (object) {
232+ // const { component, action, data } = object;
233+ // if (CoCreate[component] && CoCreate[component][action]) {
234+ // CoCreate[component][action](data);
235+ // } else {
236+ // console.error('Invalid CoCreateJS API function:', component, action);
237+ // }
238+ // }
239+ document . dispatchEvent ( new CustomEvent ( 'openAi' , {
240+ detail : { }
241+ } ) ) ;
242+
243+ } catch ( error ) {
244+ console . error ( 'Error:' , error ) ;
245+ }
246+ }
247+
248+ // Call the async function
249+ // init();
250+
251+
252+ // Function to extract the object from the generated code
253+ function extractObjectFromCode ( code ) {
254+ try {
255+ const regex = / ( { [ \s \S ] * ?} ) / ;
256+ const matches = code . match ( regex ) ;
257+ if ( matches && matches . length === 1 ) {
258+ const object = JSON . parse ( matches [ 0 ] ) ;
259+ return object ;
260+ }
261+ return null ;
262+ } catch ( error ) {
263+ console . error ( 'Error extracting object from code:' , error ) ;
264+ return null ;
265+ }
266+ }
267+
268+
269+ Actions . init ( {
270+ name : "openAi" ,
271+ endEvent : "openAi" ,
272+ callback : ( action ) => {
273+ const form = action . element . closest ( "form" ) ;
274+ send ( form ) ;
275+ }
276+ } )
0 commit comments