@surph_ai/cli 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cli.js +447 -0
- package/deploy/index.js +153 -0
- package/deploy/tool-handler.js +16 -0
- package/index.js +3 -0
- package/package.json +35 -0
- package/scaffold/index.js +137 -0
- package/scaffold/project/README.md +28 -0
- package/scaffold/project/app.js +20 -0
- package/scaffold/project/apps/README.md +1 -0
- package/scaffold/project/env.txt +4 -0
- package/scaffold/project/package-lock.json +2459 -0
- package/scaffold/project/package.json +21 -0
- package/scaffold/project/public/css/bootstrap.css +5926 -0
- package/scaffold/project/public/js/app.js +1 -0
- package/scaffold/project/public/js/jquery.js +2 -0
- package/scaffold/project/routes/index.js +8 -0
- package/scaffold/project/templates/index.mustache +20 -0
- package/scaffold/tool/README.md +25 -0
- package/scaffold/tool/env.txt +2 -0
- package/scaffold/tool/example.txt +1 -0
- package/scaffold/tool/package.json +27 -0
- package/scaffold/tool/tools/index.ts +13 -0
- package/toolserver/app.js +25 -0
- package/toolserver/chat.js +95222 -0
- package/toolserver/routes/index.js +8 -0
- package/toolserver/routes/tool.js +118 -0
- package/toolserver/templates/index.html +20 -0
- package/types.d.ts +73 -0
- package/utils/index.js +275 -0
package/cli.js
ADDED
|
@@ -0,0 +1,447 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// REFERENCE:
|
|
4
|
+
// https://developer.atlassian.com/blog/2015/11/scripting-with-node/
|
|
5
|
+
// https://www.npmjs.com/package/shelljs
|
|
6
|
+
// https://github.com/expressjs/generator/blob/master/bin/express-cli.js
|
|
7
|
+
// https://developer.atlassian.com/blog/2015/11/scripting-with-node/
|
|
8
|
+
|
|
9
|
+
const { Command } = require('commander')
|
|
10
|
+
const path = require('path')
|
|
11
|
+
const fs = require('fs')
|
|
12
|
+
const dotenv = require('dotenv')
|
|
13
|
+
const prompt = require('prompt')
|
|
14
|
+
const shell = require('shelljs')
|
|
15
|
+
const colors = require('colors/safe')
|
|
16
|
+
const AdmZip = require('adm-zip')
|
|
17
|
+
// const auth = require('./auth')
|
|
18
|
+
const deploy = require('./deploy')
|
|
19
|
+
const scaffold = require('./scaffold')
|
|
20
|
+
const utils = require('./utils')
|
|
21
|
+
const packageJson = require('./package.json')
|
|
22
|
+
|
|
23
|
+
const VERSION = packageJson.version
|
|
24
|
+
const SURPH_REST_URL = 'https://surph-mongo-http-19075ff8d93f.herokuapp.com'
|
|
25
|
+
// const RPC_URL = 'https://e3lunom2hka3u6iiotrlzrcez40uwdnk.lambda-url.us-east-1.on.aws'
|
|
26
|
+
|
|
27
|
+
// FUTURE: Export as a referenceable type
|
|
28
|
+
const ERRORS = {
|
|
29
|
+
// General errors
|
|
30
|
+
UNSPECIFIED: { exitCode: 1 },
|
|
31
|
+
INVALID_PARAMS: { exitCode: 2 },
|
|
32
|
+
NOT_LOGGED_IN: { exitCode: 3 },
|
|
33
|
+
|
|
34
|
+
// Deploy-specific errors
|
|
35
|
+
PROJECT_NOT_CONNECTED: { exitCode: 100 },
|
|
36
|
+
PROJECT_NOT_FOUND: { exitCode: 101 },
|
|
37
|
+
NOT_AUTHORIZED: { exitCode: 102 },
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const surphSession = async () => {
|
|
41
|
+
try {
|
|
42
|
+
const userSessionPath = path.resolve(__dirname, '../../../.surph/session.json')
|
|
43
|
+
if (!fs.existsSync(userSessionPath)) {
|
|
44
|
+
console.log('Not logged in.')
|
|
45
|
+
return null
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const file = fs.readFileSync(userSessionPath, 'utf-8')
|
|
49
|
+
const session = JSON.parse(file)
|
|
50
|
+
return session
|
|
51
|
+
} catch (error) {
|
|
52
|
+
console.log('Not logged in.')
|
|
53
|
+
return null
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const program = new Command()
|
|
58
|
+
|
|
59
|
+
program.version(VERSION, '-v, --version', 'output the current version')
|
|
60
|
+
|
|
61
|
+
program.command('help')
|
|
62
|
+
.description('help')
|
|
63
|
+
.action(() => {
|
|
64
|
+
console.log('HELP!')
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
program.command('version')
|
|
68
|
+
.description('show current version')
|
|
69
|
+
.action((cmd, options) => {
|
|
70
|
+
try {
|
|
71
|
+
const text = `${colors.cyan(`\nSurph Version: `)} ${colors.brightGreen(`${VERSION}`)}\n`
|
|
72
|
+
console.log(text)
|
|
73
|
+
} catch (error) {
|
|
74
|
+
// console.log(colors.red('\nError: '+err.message+'\n'))
|
|
75
|
+
utils.printError(error)
|
|
76
|
+
}
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
program.command('profile')
|
|
80
|
+
.description('Current Surph user')
|
|
81
|
+
.action(async (cmd, options) => {
|
|
82
|
+
// const userSessionPath = path.resolve(__dirname, '../../../.surph/session.json')
|
|
83
|
+
// if (!fs.existsSync(userSessionPath)) {
|
|
84
|
+
// console.log('SESSION NOT FOUND:')
|
|
85
|
+
// return
|
|
86
|
+
// }
|
|
87
|
+
|
|
88
|
+
// const file = fs.readFileSync(userSessionPath, 'utf-8')
|
|
89
|
+
// const data = JSON.parse(file)
|
|
90
|
+
// console.log('SESSION FOUND:' + JSON.stringify(data))
|
|
91
|
+
|
|
92
|
+
// const user = await auth.currentUser()
|
|
93
|
+
// if (user === false) {
|
|
94
|
+
// program.error(`${colors.cyan('\nNot logged in. To log in:')}\n\n${colors.white('$ vly login')}`,
|
|
95
|
+
// ERRORS.NOT_LOGGED_IN);
|
|
96
|
+
// }
|
|
97
|
+
|
|
98
|
+
// const text = `${colors.cyan(`\nLogged in as: `)} ${colors.brightGreen(`${user.username}`)}\n`
|
|
99
|
+
// console.log(text)
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
/*
|
|
103
|
+
program.command('login')
|
|
104
|
+
.description('login to Surph')
|
|
105
|
+
.action(async (cmd, options) => {
|
|
106
|
+
try {
|
|
107
|
+
const credentials = await auth.showPrompt()
|
|
108
|
+
|
|
109
|
+
const resp = await axios({
|
|
110
|
+
url: `${PORTAL_URL}/auth/login`,
|
|
111
|
+
method: 'post',
|
|
112
|
+
data: credentials,
|
|
113
|
+
headers: { Accept: 'application/json'}
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
const { data } = resp.data
|
|
117
|
+
const user = { id: data._id, username: data.username }
|
|
118
|
+
|
|
119
|
+
shell.cd('')
|
|
120
|
+
utils.write('.Surph_user', JSON.stringify(user, null, 2) + '\n')
|
|
121
|
+
|
|
122
|
+
const successText = `${colors.cyan(`\nSuccess! `)} ${colors.brightGreen(`Currently Logged In As ${user.username}\n`)}`
|
|
123
|
+
console.log(successText)
|
|
124
|
+
} catch (error) {
|
|
125
|
+
utils.printError(error)
|
|
126
|
+
}
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
program.command('dev')
|
|
130
|
+
.description('run dev server')
|
|
131
|
+
.action(async (cmd, options) => {
|
|
132
|
+
try {
|
|
133
|
+
// shell.cp('-R', path.join(__dirname, '../default/lambda/js/index.js'), 'vectors/js/index.js')
|
|
134
|
+
shell.cd(path.join(__dirname, 'base/Surph-base'))
|
|
135
|
+
shell.exec('npm run dev')
|
|
136
|
+
// shell.cd('Surph-base')
|
|
137
|
+
|
|
138
|
+
// shell.exec('gulp build --gulpfile node_modules/@turbo360/turbo-sdk/src/gulpfile.js --silent')
|
|
139
|
+
|
|
140
|
+
} catch (error) {
|
|
141
|
+
utils.printError(error)
|
|
142
|
+
}
|
|
143
|
+
})
|
|
144
|
+
*/
|
|
145
|
+
|
|
146
|
+
program.command('new <name>')
|
|
147
|
+
.description('create new Surph app')
|
|
148
|
+
.action(name => scaffold(name, 'project'))
|
|
149
|
+
|
|
150
|
+
program.command('toolserver')
|
|
151
|
+
.description('run tool server')
|
|
152
|
+
.action(async (cmd, options) => {
|
|
153
|
+
try {
|
|
154
|
+
shell.exec('nodemon --quiet ./node_modules/@surph_ai/sdk/toolserver/app')
|
|
155
|
+
} catch (error) {
|
|
156
|
+
utils.printError(error)
|
|
157
|
+
}
|
|
158
|
+
})
|
|
159
|
+
|
|
160
|
+
program.command('chatserver')
|
|
161
|
+
.description('run chat server')
|
|
162
|
+
.action(async (cmd, options) => {
|
|
163
|
+
try {
|
|
164
|
+
shell.exec('nodemon --quiet ./node_modules/@surph_ai/sdk/toolserver/chat')
|
|
165
|
+
} catch (error) {
|
|
166
|
+
utils.printError(error)
|
|
167
|
+
}
|
|
168
|
+
})
|
|
169
|
+
|
|
170
|
+
program.command('tool <name>')
|
|
171
|
+
.description('create new Surph tool')
|
|
172
|
+
.action(name => scaffold(name, 'tool'))
|
|
173
|
+
|
|
174
|
+
program.command('manifest')
|
|
175
|
+
.description('update manifest for Surph tool')
|
|
176
|
+
.action(async (cmd, options) => {
|
|
177
|
+
try {
|
|
178
|
+
const manifestJson = require('../../../manifest.json')
|
|
179
|
+
const slug = Object.keys(manifestJson)[0]
|
|
180
|
+
const manifest = manifestJson[slug]
|
|
181
|
+
if (!manifest) {
|
|
182
|
+
throw new Error('manifest.json not found')
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const schema = {
|
|
186
|
+
properties: {
|
|
187
|
+
description: {
|
|
188
|
+
description: colors.cyan('\nWhat does your tool do?'),
|
|
189
|
+
required: true
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
prompt.message = null
|
|
195
|
+
prompt.start()
|
|
196
|
+
|
|
197
|
+
const { description } = await prompt.get(schema)
|
|
198
|
+
// console.log('ARGS: ' + JSON.stringify(args))
|
|
199
|
+
|
|
200
|
+
const resp = await fetch('https://rpc.surph.ai/tools/manifest', {
|
|
201
|
+
method: "POST",
|
|
202
|
+
body: JSON.stringify({
|
|
203
|
+
description,
|
|
204
|
+
name: manifest.name,
|
|
205
|
+
slug: manifest.slug
|
|
206
|
+
}),
|
|
207
|
+
headers: {
|
|
208
|
+
'Accept': 'application/json',
|
|
209
|
+
'Content-type': 'application/json',
|
|
210
|
+
'x-surph-client': 'surph-sdk'
|
|
211
|
+
}
|
|
212
|
+
})
|
|
213
|
+
|
|
214
|
+
const { response } = await resp.json()
|
|
215
|
+
utils.write('manifest.json', JSON.stringify({[slug]: response}, null, 2) + '\n')
|
|
216
|
+
console.log(colors.white('\n\nManifest updated. Check manifest.json for changes.\n'))
|
|
217
|
+
} catch (error) {
|
|
218
|
+
utils.printError(error)
|
|
219
|
+
}
|
|
220
|
+
})
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
/*
|
|
224
|
+
program.command('connect')
|
|
225
|
+
.description('Connect to Surph project')
|
|
226
|
+
.action(async (cmd, options) => {
|
|
227
|
+
try {
|
|
228
|
+
const user = await auth.currentUser() // must be logged in.
|
|
229
|
+
if (user === false) {
|
|
230
|
+
program.error(`${colors.cyan('\nNot logged in. To log in:')}\n\n${colors.white('$ vly login')}`,
|
|
231
|
+
ERRORS.NOT_LOGGED_IN);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
const projects = await Realm.restQuery('project', 'get', { 'members.id': user.id })
|
|
235
|
+
if (projects.length === 0) {
|
|
236
|
+
throw new Error(`No Projects not found.`)
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// console.log('PROJECTS: ' + JSON.stringify(projects))
|
|
240
|
+
|
|
241
|
+
const _projects = projects.map(({ name }, idx) => `${idx + 1}. ${name}`)
|
|
242
|
+
|
|
243
|
+
const schema = {
|
|
244
|
+
properties: {
|
|
245
|
+
framework: {
|
|
246
|
+
message: `\n\n${_projects.join('\n')}\n\nSelect project number then press "enter"\n`,
|
|
247
|
+
required: true
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
prompt.start()
|
|
253
|
+
|
|
254
|
+
prompt.get(schema, (err, result) => {
|
|
255
|
+
if (err) {
|
|
256
|
+
console.log('\n')
|
|
257
|
+
return
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
const selected = result.framework.trim()
|
|
261
|
+
const index = parseInt(selected - 1)
|
|
262
|
+
|
|
263
|
+
if (index < 0) {
|
|
264
|
+
utils.printError(new Error('Invalid entry.'))
|
|
265
|
+
return
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
if (_projects.length < (index + 1)) {
|
|
269
|
+
utils.printError(new Error('Invalid entry.'))
|
|
270
|
+
return
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
const selectedApp = projects[index]
|
|
274
|
+
if (!selectedApp) {
|
|
275
|
+
utils.printError(new Error('Invalid entry.'))
|
|
276
|
+
return
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// console.log('SELECTED: ' + JSON.stringify(selectedApp))
|
|
280
|
+
const { name, slug } = selectedApp
|
|
281
|
+
const envFile = utils.readFile('.env') || '{}'
|
|
282
|
+
const envJson = dotenv.parse(envFile)
|
|
283
|
+
|
|
284
|
+
const env = {
|
|
285
|
+
...envJson,
|
|
286
|
+
'TURBO_PROJECT': name,
|
|
287
|
+
'TURBO_PROJECT_SLUG': slug
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
let envString = ''
|
|
291
|
+
Object.keys(env).forEach((key, i) => {
|
|
292
|
+
if (env[key] !== null) {
|
|
293
|
+
envString += key+'='+env[key]+'\n'
|
|
294
|
+
}
|
|
295
|
+
})
|
|
296
|
+
|
|
297
|
+
utils.write('.env', envString)
|
|
298
|
+
console.log('\nApp Connected!\nto deploy:\n\n$ vly deploy\n\n')
|
|
299
|
+
})
|
|
300
|
+
} catch (error) {
|
|
301
|
+
utils.printError(error)
|
|
302
|
+
}
|
|
303
|
+
})
|
|
304
|
+
*/
|
|
305
|
+
|
|
306
|
+
program.command('publish')
|
|
307
|
+
.description('Publish Surph tool')
|
|
308
|
+
.action(async (cmd, options) => {
|
|
309
|
+
try {
|
|
310
|
+
const manifest = require('../../../manifest.json')
|
|
311
|
+
if (!manifest) {
|
|
312
|
+
throw new Error('manifest.json not found')
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
const keys = Object.keys(manifest)
|
|
316
|
+
if (keys.length === 0) {
|
|
317
|
+
throw new Error('invalid manifest.json')
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
const session = await surphSession()
|
|
321
|
+
if (!session) {
|
|
322
|
+
throw new Error('Not logged in.')
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
// console.log('SESSION: ' + JSON.stringify(session))
|
|
326
|
+
const userId = session?.userId
|
|
327
|
+
|
|
328
|
+
let resp = await fetch(`${SURPH_REST_URL}/rest/user/${userId}`, {
|
|
329
|
+
method: 'GET',
|
|
330
|
+
headers: {
|
|
331
|
+
Accept: 'application/json',
|
|
332
|
+
'x-surph-client': 'surph-sdk'
|
|
333
|
+
}
|
|
334
|
+
})
|
|
335
|
+
|
|
336
|
+
const { payload: user } = await resp.json()
|
|
337
|
+
// console.log('USER: ' + JSON.stringify(user))
|
|
338
|
+
|
|
339
|
+
|
|
340
|
+
const slug = keys[0]
|
|
341
|
+
resp = await fetch(`${SURPH_REST_URL}/rest/tool?slug=${slug}`, {
|
|
342
|
+
method: 'GET',
|
|
343
|
+
headers: {
|
|
344
|
+
Accept: 'application/json',
|
|
345
|
+
'x-surph-client': 'surph-sdk'
|
|
346
|
+
}
|
|
347
|
+
})
|
|
348
|
+
|
|
349
|
+
const { payload } = await resp.json()
|
|
350
|
+
|
|
351
|
+
const toolJson = manifest[slug]
|
|
352
|
+
|
|
353
|
+
// tool not registered yet, create:
|
|
354
|
+
if (payload.length === 0) {
|
|
355
|
+
const resp = await fetch(`${SURPH_REST_URL}/rest/tool`, {
|
|
356
|
+
method: 'POST',
|
|
357
|
+
body: JSON.stringify({
|
|
358
|
+
...toolJson,
|
|
359
|
+
creator: {
|
|
360
|
+
_id: user._id,
|
|
361
|
+
username: user.username,
|
|
362
|
+
avatar: user.avatar
|
|
363
|
+
}
|
|
364
|
+
}),
|
|
365
|
+
headers: {
|
|
366
|
+
Accept: 'application/json',
|
|
367
|
+
'Content-Type': 'application/json',
|
|
368
|
+
'x-surph-client': 'surph-sdk'
|
|
369
|
+
}
|
|
370
|
+
})
|
|
371
|
+
|
|
372
|
+
const { payload } = await resp.json()
|
|
373
|
+
console.log(`\nSurph tool registered. To view, visit:\n\nhttps://surph.ai/tool/${slug}\n`)
|
|
374
|
+
return
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
resp = await fetch(`${SURPH_REST_URL}/rest/tool/${payload[0]._id}`, {
|
|
378
|
+
method: 'PUT',
|
|
379
|
+
body: JSON.stringify({
|
|
380
|
+
...toolJson,
|
|
381
|
+
creator: {
|
|
382
|
+
_id: user._id,
|
|
383
|
+
username: user.username,
|
|
384
|
+
avatar: user.avatar
|
|
385
|
+
}
|
|
386
|
+
}),
|
|
387
|
+
headers: {
|
|
388
|
+
Accept: 'application/json',
|
|
389
|
+
'Content-Type': 'application/json',
|
|
390
|
+
'x-surph-client': 'surph-sdk'
|
|
391
|
+
}
|
|
392
|
+
})
|
|
393
|
+
|
|
394
|
+
const data = await resp.json()
|
|
395
|
+
console.log('\nSurph tool updated.')
|
|
396
|
+
} catch (error) {
|
|
397
|
+
console.log(colors.red('\nError: '+error.message+'\n'))
|
|
398
|
+
}
|
|
399
|
+
})
|
|
400
|
+
|
|
401
|
+
|
|
402
|
+
program.command('deploy')
|
|
403
|
+
.description('Deploy to Surph')
|
|
404
|
+
.action(async (cmd, options) => {
|
|
405
|
+
try {
|
|
406
|
+
/*
|
|
407
|
+
const { type } = cmd
|
|
408
|
+
if (type !== 'default' && type !== 'static') {
|
|
409
|
+
const msg = colors.red(`\nError: Invalid deployment type ${type}.\n`) +
|
|
410
|
+
colors.white(`Please select type "static" or omit type flag.\n`);
|
|
411
|
+
program.error(msg, ERRORS.INVALID_PARAMS)
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
const user = await auth.currentUser() // must be logged in.
|
|
415
|
+
if (user === false) {
|
|
416
|
+
program.error(`${colors.cyan('\nNot logged in. To log in:')}\n\n${colors.white('$ vly login')}`,
|
|
417
|
+
ERRORS.NOT_LOGGED_IN);
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
*/
|
|
421
|
+
|
|
422
|
+
/*
|
|
423
|
+
const apps = await Realm.restQuery('project', 'get', { slug: TURBO_PROJECT_SLUG })
|
|
424
|
+
if (apps.length === 0) {
|
|
425
|
+
program.error(`App ${TURBO_PROJECT} not found.`, ERRORS.PROJECT_NOT_FOUND)
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
const { members } = apps[0]
|
|
429
|
+
if (!members.find(member => (member.id === user.id))) {
|
|
430
|
+
program.error('Unauthorized', ERRORS.NOT_AUTHORIZED)
|
|
431
|
+
}
|
|
432
|
+
*/
|
|
433
|
+
|
|
434
|
+
const { SURPH_TOOL = null } = dotenv.parse(utils.readFile('.env') ?? '')
|
|
435
|
+
|
|
436
|
+
if (SURPH_TOOL === null) {
|
|
437
|
+
program.error('Surph project not connected. To connect, run:\n\n$ surph connect', ERRORS.PROJECT_NOT_CONNECTED)
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
await deploy.tool({ SURPH_TOOL_SLUG: SURPH_TOOL })
|
|
441
|
+
} catch (error) {
|
|
442
|
+
utils.printError(error)
|
|
443
|
+
program.error(`Unexpected error: ${error}`, ERRORS.UNSPECIFIED)
|
|
444
|
+
}
|
|
445
|
+
})
|
|
446
|
+
|
|
447
|
+
program.parse(process.argv)
|
package/deploy/index.js
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
const path = require('path')
|
|
2
|
+
const fs = require('fs')
|
|
3
|
+
const shell = require('shelljs')
|
|
4
|
+
const colors = require('colors/safe') // https://www.npmjs.com/package/colors
|
|
5
|
+
const bestzip = require('bestzip')
|
|
6
|
+
|
|
7
|
+
// const RPC_URL = 'https://e3lunom2hka3u6iiotrlzrcez40uwdnk.lambda-url.us-east-1.on.aws'
|
|
8
|
+
const RPC_URL = 'https://rpc.surph.ai'
|
|
9
|
+
const ZIP_NAME = 'LATEST.zip'
|
|
10
|
+
const STATIC_ARCHIVE_NAME = 'Archive.zip'
|
|
11
|
+
const DEFAULT_HEADERS = {
|
|
12
|
+
'Content-Type': 'application/json',
|
|
13
|
+
'Accept': 'application/json'
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const rpcCall = async (action, args, headers = DEFAULT_HEADERS) => {
|
|
17
|
+
let path = null
|
|
18
|
+
if (action === 'uploadUrl') {
|
|
19
|
+
path = 's3/upload_url'
|
|
20
|
+
}
|
|
21
|
+
if (action === 'deployTool') {
|
|
22
|
+
path = 'tools/deploy'
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
try {
|
|
26
|
+
if (action === null) {
|
|
27
|
+
throw new Error(`Invalid action: ${action}`)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const resp = await fetch(`${RPC_URL}/${path}`, {
|
|
31
|
+
method: 'POST',
|
|
32
|
+
body: JSON.stringify(args),
|
|
33
|
+
headers: {
|
|
34
|
+
'Accept': 'application/json',
|
|
35
|
+
'Content-Type': 'application/json',
|
|
36
|
+
'x-surph-client': 'surph-sdk'
|
|
37
|
+
}
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
const { response } = await resp.json()
|
|
41
|
+
if (response.error) {
|
|
42
|
+
throw new Error(response.error)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return response
|
|
46
|
+
} catch (error) {
|
|
47
|
+
throw error
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/*
|
|
52
|
+
// 09/17/2019 - this did not cover all scenarios. Windows worked fine (confirmed
|
|
53
|
+
// by Marianne) but if on a funky linux distro, the "else" block failed.
|
|
54
|
+
var zipDirectory = function(){
|
|
55
|
+
// console.log('PLT == ' + process.platform)
|
|
56
|
+
if (process.platform == 'win32'){ // fuck windows:
|
|
57
|
+
return bestzip.nodeZip({source:'*', destination: '../package.zip'})
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
return new Promise(function(resolve, reject){
|
|
61
|
+
shell.exec('zip -r -q package.zip *')
|
|
62
|
+
resolve(true)
|
|
63
|
+
})
|
|
64
|
+
}
|
|
65
|
+
} */
|
|
66
|
+
|
|
67
|
+
const zipDirectory = (name = 'package.zip') => {
|
|
68
|
+
// the package.zip file has to be created in another directory
|
|
69
|
+
// otherwise it will include "package.zip" itself with nothing
|
|
70
|
+
// inside. This is sloppy so we create the package.zip file in
|
|
71
|
+
// one level up then bring it back into the deploy folder
|
|
72
|
+
|
|
73
|
+
if (process.platform === 'win32'){ // fuck windows:
|
|
74
|
+
return bestzip.nodeZip({
|
|
75
|
+
source: '*',
|
|
76
|
+
destination: `../${name}`
|
|
77
|
+
})
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
return bestzip.nodeZip({
|
|
81
|
+
source: '*',
|
|
82
|
+
destination: `../${name}`
|
|
83
|
+
})
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const compile = async (deployDir, name = 'package.zip', dir = null) => {
|
|
88
|
+
shell.mkdir('-p', `${deployDir}/`)
|
|
89
|
+
shell.cp('-R', `node_modules/@surph_ai/sdk/deploy/tool-handler.js`, `${deployDir}/main.js`)
|
|
90
|
+
|
|
91
|
+
if (dir === null) {
|
|
92
|
+
shell.cp('-R', '!(node_modules|deploy)', `${deployDir}/`) // copy everything but node_modules and deploy
|
|
93
|
+
} else {
|
|
94
|
+
// compress contents of specified directory:
|
|
95
|
+
shell.cd(dir)
|
|
96
|
+
shell.cp('-R', '!(node_modules|deploy)', `../${deployDir}/`)
|
|
97
|
+
shell.cd('..')
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
shell.cd(deployDir)
|
|
101
|
+
shell.exec('npm install --production --silent')
|
|
102
|
+
|
|
103
|
+
await zipDirectory(name) // package it up!
|
|
104
|
+
|
|
105
|
+
// the zip file has to be created in another directory
|
|
106
|
+
// otherwise it will include "*.zip" itself with nothing
|
|
107
|
+
// inside. This is sloppy so we create the zip file in
|
|
108
|
+
// one level up then bring it back into the deploy folder
|
|
109
|
+
shell.cd('..')
|
|
110
|
+
shell.mv([name], `${deployDir}/`)
|
|
111
|
+
shell.cd(deployDir)
|
|
112
|
+
|
|
113
|
+
shell.mv([name], '..') // place package in root directory
|
|
114
|
+
shell.cd('..')
|
|
115
|
+
shell.rm('-rf', deployDir) // remove hidden deploy dir
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
module.exports = {
|
|
119
|
+
tool: async ({ SURPH_TOOL_SLUG }) => {
|
|
120
|
+
if (!SURPH_TOOL_SLUG) {
|
|
121
|
+
throw new Error(colors.white('Tool undefined. Please check .env file.'))
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const { uploadUrl } = await rpcCall('uploadUrl', {
|
|
125
|
+
collection: 'tools',
|
|
126
|
+
folder: SURPH_TOOL_SLUG,
|
|
127
|
+
filename: `uploads/${ZIP_NAME}`,
|
|
128
|
+
filetype: 'application/zip'
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
// console.log('UPLOAD URL: ' + uploadUrl)
|
|
132
|
+
console.log(`\n${colors.white('Deploying tool. This usually takes a few minutes...')}\n`)
|
|
133
|
+
|
|
134
|
+
await compile('.deploy', ZIP_NAME)
|
|
135
|
+
|
|
136
|
+
await fetch(uploadUrl, {
|
|
137
|
+
method: 'PUT',
|
|
138
|
+
body: fs.readFileSync(ZIP_NAME),
|
|
139
|
+
headers: {
|
|
140
|
+
'Accept': 'application/json',
|
|
141
|
+
'Content-Type': 'application/zip'
|
|
142
|
+
}
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
shell.rm('-rf', ZIP_NAME)
|
|
146
|
+
|
|
147
|
+
// connect container image to function:
|
|
148
|
+
await rpcCall('deployTool', { tool: SURPH_TOOL_SLUG })
|
|
149
|
+
|
|
150
|
+
console.log(colors.white('\nDeploy complete! To view your tool, navigate to\n'))
|
|
151
|
+
console.log(colors.white(`https://surph.ai/tool/${SURPH_TOOL_SLUG}\n\n`))
|
|
152
|
+
}
|
|
153
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import tool from './dist/tools/index.js';
|
|
2
|
+
|
|
3
|
+
export const handler = async (event) => {
|
|
4
|
+
const { args = {}, context = null, user = null } = event;
|
|
5
|
+
let payload = null;
|
|
6
|
+
try {
|
|
7
|
+
payload = await tool({ args, context, user });
|
|
8
|
+
} catch (error) {
|
|
9
|
+
payload = error instanceof Error ? error.message : String(error);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
return {
|
|
13
|
+
statusCode: 200,
|
|
14
|
+
body: JSON.stringify(payload),
|
|
15
|
+
};
|
|
16
|
+
};
|
package/index.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@surph_ai/cli",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"types": "./types.d.ts",
|
|
7
|
+
"publishConfig": {
|
|
8
|
+
"access": "public"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
12
|
+
},
|
|
13
|
+
"bin": {
|
|
14
|
+
"surph": "./cli.js"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [],
|
|
17
|
+
"author": "SurphAI",
|
|
18
|
+
"license": "ISC",
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"@aws-sdk/client-bedrock-runtime": "^3.1096.0",
|
|
21
|
+
"adm-zip": "^0.5.10",
|
|
22
|
+
"bestzip": "^2.2.1",
|
|
23
|
+
"cheerio": "^1.2.0",
|
|
24
|
+
"colors": "^1.4.0",
|
|
25
|
+
"commander": "^14.0.1",
|
|
26
|
+
"cookie": "^0.5.0",
|
|
27
|
+
"cors": "^2.8.6",
|
|
28
|
+
"dotenv": "^16.0.3",
|
|
29
|
+
"express": "^4.18.1",
|
|
30
|
+
"impit": "^0.14.0",
|
|
31
|
+
"mustache": "^4.2.0",
|
|
32
|
+
"prompt": "^1.3.0",
|
|
33
|
+
"shelljs": "^0.8.5"
|
|
34
|
+
}
|
|
35
|
+
}
|