@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 +449 -0
- package/deploy/index.js +0 -0
- package/index.js +3 -447
- package/package.json +2 -2
- package/platform/constants.js +4 -0
- package/platform/context.js +44 -0
- package/platform/index.js +27 -0
- package/platform/tools.js +29 -0
- package/platform/user.js +24 -0
- package/scaffold/index.js +0 -0
- package/scaffold/tool/tools/index.ts +3 -1
- package/toolserver/chat.js +56 -15
- package/toolserver/routes/tool.js +2 -2
- package/types.d.ts +9 -0
- package/utils/index.js +0 -0
- package/auth/index.js +0 -147
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
|