@surph_ai/sdk 0.0.25 → 0.0.27

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 ADDED
@@ -0,0 +1,449 @@
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
+ const updated = { ...manifest, ...response }
216
+
217
+ utils.write('manifest.json', JSON.stringify({[slug]: updated}, null, 2) + '\n')
218
+ console.log(colors.white('\n\nManifest updated. Check manifest.json for changes.\n'))
219
+ } catch (error) {
220
+ utils.printError(error)
221
+ }
222
+ })
223
+
224
+
225
+ /*
226
+ program.command('connect')
227
+ .description('Connect to Surph project')
228
+ .action(async (cmd, options) => {
229
+ try {
230
+ const user = await auth.currentUser() // must be logged in.
231
+ if (user === false) {
232
+ program.error(`${colors.cyan('\nNot logged in. To log in:')}\n\n${colors.white('$ vly login')}`,
233
+ ERRORS.NOT_LOGGED_IN);
234
+ }
235
+
236
+ const projects = await Realm.restQuery('project', 'get', { 'members.id': user.id })
237
+ if (projects.length === 0) {
238
+ throw new Error(`No Projects not found.`)
239
+ }
240
+
241
+ // console.log('PROJECTS: ' + JSON.stringify(projects))
242
+
243
+ const _projects = projects.map(({ name }, idx) => `${idx + 1}. ${name}`)
244
+
245
+ const schema = {
246
+ properties: {
247
+ framework: {
248
+ message: `\n\n${_projects.join('\n')}\n\nSelect project number then press "enter"\n`,
249
+ required: true
250
+ }
251
+ }
252
+ }
253
+
254
+ prompt.start()
255
+
256
+ prompt.get(schema, (err, result) => {
257
+ if (err) {
258
+ console.log('\n')
259
+ return
260
+ }
261
+
262
+ const selected = result.framework.trim()
263
+ const index = parseInt(selected - 1)
264
+
265
+ if (index < 0) {
266
+ utils.printError(new Error('Invalid entry.'))
267
+ return
268
+ }
269
+
270
+ if (_projects.length < (index + 1)) {
271
+ utils.printError(new Error('Invalid entry.'))
272
+ return
273
+ }
274
+
275
+ const selectedApp = projects[index]
276
+ if (!selectedApp) {
277
+ utils.printError(new Error('Invalid entry.'))
278
+ return
279
+ }
280
+
281
+ // console.log('SELECTED: ' + JSON.stringify(selectedApp))
282
+ const { name, slug } = selectedApp
283
+ const envFile = utils.readFile('.env') || '{}'
284
+ const envJson = dotenv.parse(envFile)
285
+
286
+ const env = {
287
+ ...envJson,
288
+ 'TURBO_PROJECT': name,
289
+ 'TURBO_PROJECT_SLUG': slug
290
+ }
291
+
292
+ let envString = ''
293
+ Object.keys(env).forEach((key, i) => {
294
+ if (env[key] !== null) {
295
+ envString += key+'='+env[key]+'\n'
296
+ }
297
+ })
298
+
299
+ utils.write('.env', envString)
300
+ console.log('\nApp Connected!\nto deploy:\n\n$ vly deploy\n\n')
301
+ })
302
+ } catch (error) {
303
+ utils.printError(error)
304
+ }
305
+ })
306
+ */
307
+
308
+ program.command('publish')
309
+ .description('Publish Surph tool')
310
+ .action(async (cmd, options) => {
311
+ try {
312
+ const manifest = require('../../../manifest.json')
313
+ if (!manifest) {
314
+ throw new Error('manifest.json not found')
315
+ }
316
+
317
+ const keys = Object.keys(manifest)
318
+ if (keys.length === 0) {
319
+ throw new Error('invalid manifest.json')
320
+ }
321
+
322
+ const session = await surphSession()
323
+ if (!session) {
324
+ throw new Error('Not logged in.')
325
+ }
326
+
327
+ // console.log('SESSION: ' + JSON.stringify(session))
328
+ const userId = session?.userId
329
+
330
+ let resp = await fetch(`${SURPH_REST_URL}/rest/user/${userId}`, {
331
+ method: 'GET',
332
+ headers: {
333
+ Accept: 'application/json',
334
+ 'x-surph-client': 'surph-sdk'
335
+ }
336
+ })
337
+
338
+ const { payload: user } = await resp.json()
339
+ // console.log('USER: ' + JSON.stringify(user))
340
+
341
+
342
+ const slug = keys[0]
343
+ resp = await fetch(`${SURPH_REST_URL}/rest/tool?slug=${slug}`, {
344
+ method: 'GET',
345
+ headers: {
346
+ Accept: 'application/json',
347
+ 'x-surph-client': 'surph-sdk'
348
+ }
349
+ })
350
+
351
+ const { payload } = await resp.json()
352
+
353
+ const toolJson = manifest[slug]
354
+
355
+ // tool not registered yet, create:
356
+ if (payload.length === 0) {
357
+ const resp = await fetch(`${SURPH_REST_URL}/rest/tool`, {
358
+ method: 'POST',
359
+ body: JSON.stringify({
360
+ ...toolJson,
361
+ creator: {
362
+ _id: user._id,
363
+ username: user.username,
364
+ avatar: user.avatar
365
+ }
366
+ }),
367
+ headers: {
368
+ Accept: 'application/json',
369
+ 'Content-Type': 'application/json',
370
+ 'x-surph-client': 'surph-sdk'
371
+ }
372
+ })
373
+
374
+ const { payload } = await resp.json()
375
+ console.log(`\nSurph tool registered. To view, visit:\n\nhttps://surph.ai/tool/${slug}\n`)
376
+ return
377
+ }
378
+
379
+ resp = await fetch(`${SURPH_REST_URL}/rest/tool/${payload[0]._id}`, {
380
+ method: 'PUT',
381
+ body: JSON.stringify({
382
+ ...toolJson,
383
+ creator: {
384
+ _id: user._id,
385
+ username: user.username,
386
+ avatar: user.avatar
387
+ }
388
+ }),
389
+ headers: {
390
+ Accept: 'application/json',
391
+ 'Content-Type': 'application/json',
392
+ 'x-surph-client': 'surph-sdk'
393
+ }
394
+ })
395
+
396
+ const data = await resp.json()
397
+ console.log('\nSurph tool updated.')
398
+ } catch (error) {
399
+ console.log(colors.red('\nError: '+error.message+'\n'))
400
+ }
401
+ })
402
+
403
+
404
+ program.command('deploy')
405
+ .description('Deploy to Surph')
406
+ .action(async (cmd, options) => {
407
+ try {
408
+ /*
409
+ const { type } = cmd
410
+ if (type !== 'default' && type !== 'static') {
411
+ const msg = colors.red(`\nError: Invalid deployment type ${type}.\n`) +
412
+ colors.white(`Please select type "static" or omit type flag.\n`);
413
+ program.error(msg, ERRORS.INVALID_PARAMS)
414
+ }
415
+
416
+ const user = await auth.currentUser() // must be logged in.
417
+ if (user === false) {
418
+ program.error(`${colors.cyan('\nNot logged in. To log in:')}\n\n${colors.white('$ vly login')}`,
419
+ ERRORS.NOT_LOGGED_IN);
420
+ }
421
+
422
+ */
423
+
424
+ /*
425
+ const apps = await Realm.restQuery('project', 'get', { slug: TURBO_PROJECT_SLUG })
426
+ if (apps.length === 0) {
427
+ program.error(`App ${TURBO_PROJECT} not found.`, ERRORS.PROJECT_NOT_FOUND)
428
+ }
429
+
430
+ const { members } = apps[0]
431
+ if (!members.find(member => (member.id === user.id))) {
432
+ program.error('Unauthorized', ERRORS.NOT_AUTHORIZED)
433
+ }
434
+ */
435
+
436
+ const { SURPH_TOOL = null } = dotenv.parse(utils.readFile('.env') ?? '')
437
+
438
+ if (SURPH_TOOL === null) {
439
+ program.error('Surph project not connected. To connect, run:\n\n$ surph connect', ERRORS.PROJECT_NOT_CONNECTED)
440
+ }
441
+
442
+ await deploy.tool({ SURPH_TOOL_SLUG: SURPH_TOOL })
443
+ } catch (error) {
444
+ utils.printError(error)
445
+ program.error(`Unexpected error: ${error}`, ERRORS.UNSPECIFIED)
446
+ }
447
+ })
448
+
449
+ program.parse(process.argv)
package/deploy/index.js CHANGED
File without changes