@surph_ai/cli 0.0.16 → 0.0.19
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/package.json +1 -1
- package/scaffold/index.js +4 -1
- package/scaffold/tool/examples/dealfinder/index.ts +1 -1
- package/scaffold/tool/examples/population/index.ts +1 -1
- package/scaffold/tool/examples/weather/index.ts +3 -1
- package/scaffold/tool/package.json +0 -2
- package/scaffold/tool/tools/index.ts +27 -3
- package/toolserver/app.js +2 -1
- package/toolserver/middleware/board.js +66 -0
- package/toolserver/middleware/index.js +2 -0
- package/toolserver/routes/index.js +28 -5
- package/toolserver/routes/tool.js +4 -4
- package/utils/boardConfiguration.js +45 -0
- package/utils/constants.js +9 -0
package/package.json
CHANGED
package/scaffold/index.js
CHANGED
|
@@ -44,7 +44,7 @@ const nextSteps = function(name){
|
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
|
|
47
|
-
module.exports = (name, type = 'app') => {
|
|
47
|
+
module.exports = async (name, type = 'app') => {
|
|
48
48
|
/*
|
|
49
49
|
https://stackoverflow.com/questions/8683895/how-do-i-determine-the-current-operating-system-with-node-js
|
|
50
50
|
Returns the operating system platform. Possible values are 'darwin', 'freebsd', 'linux',
|
|
@@ -142,6 +142,9 @@ module.exports = (name, type = 'app') => {
|
|
|
142
142
|
|
|
143
143
|
utils.write('tsconfig.json', JSON.stringify(tsConfig, null, 2) + '\n')
|
|
144
144
|
|
|
145
|
+
const cheatsheetResp = await fetch('https://surph.s3.us-east-1.amazonaws.com/tools/cli/CHEATSHEET.md')
|
|
146
|
+
utils.write('CHEATSHEET.md', await cheatsheetResp.text())
|
|
147
|
+
|
|
145
148
|
console.log('\n- - - - - Next Steps - - - - - ')
|
|
146
149
|
console.log('1. $ cd ' + name)
|
|
147
150
|
console.log('2. $ npm install or $ yarn install')
|
|
@@ -6,7 +6,7 @@ type ToolArgs = {
|
|
|
6
6
|
preferences: string[]
|
|
7
7
|
};
|
|
8
8
|
|
|
9
|
-
const handler: ToolHandler<ToolArgs> = async ({ args, user, context }: Record<string, any>) => {
|
|
9
|
+
const handler: ToolHandler<ToolArgs> = async ({ args, user, context = null, board = null }: Record<string, any>) => {
|
|
10
10
|
try {
|
|
11
11
|
if (!args) {
|
|
12
12
|
throw new Error('Args required.')
|
|
@@ -11,7 +11,7 @@ type ToolArgs = {
|
|
|
11
11
|
city: string
|
|
12
12
|
};
|
|
13
13
|
|
|
14
|
-
const handler: ToolHandler<ToolArgs> = async ({ args, user, context }: Record<string, any>) => {
|
|
14
|
+
const handler: ToolHandler<ToolArgs> = async ({ args, user, context = null, board = null }: Record<string, any>) => {
|
|
15
15
|
try {
|
|
16
16
|
// your custom tool code goes here
|
|
17
17
|
const { city } = args
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
// This example shows how to connect a custom tool to an API and make API calls.
|
|
2
|
+
|
|
1
3
|
import type { ToolHandler } from '@surph_ai/sdk';
|
|
2
4
|
|
|
3
5
|
// Define interfaces for API responses
|
|
@@ -109,7 +111,7 @@ type ToolArgs = {
|
|
|
109
111
|
location: string
|
|
110
112
|
};
|
|
111
113
|
|
|
112
|
-
const handler: ToolHandler<ToolArgs> = async ({ args, user, context }: Record<string, any>) => {
|
|
114
|
+
const handler: ToolHandler<ToolArgs> = async ({ args, user, context = null, board = null }: Record<string, any>) => {
|
|
113
115
|
try {
|
|
114
116
|
const { location } = args;
|
|
115
117
|
if (!location) {
|
|
@@ -1,13 +1,37 @@
|
|
|
1
1
|
import type { ToolHandler, ToolContext, User } from '@surph_ai/sdk';
|
|
2
|
-
import { surph } from '@surph_ai/sdk';
|
|
2
|
+
import { surph, SurphContext, SurphBoard } from '@surph_ai/sdk';
|
|
3
3
|
|
|
4
4
|
type ToolArgs = {
|
|
5
5
|
// your custom tool args goes here
|
|
6
6
|
};
|
|
7
7
|
|
|
8
|
-
const handler: ToolHandler<ToolArgs> = async ({ args, user, context }: Record<string, any>) => {
|
|
9
|
-
|
|
8
|
+
const handler: ToolHandler<ToolArgs> = async ({ args, user, context = null, board = null }: Record<string, any>) => {
|
|
9
|
+
try {
|
|
10
|
+
|
|
11
|
+
// your custom tool code goes here.
|
|
12
|
+
//
|
|
13
|
+
// pro tip: tell your coding agent to use "CHEATSHEET.md"
|
|
14
|
+
// as a guide for working with this sdk. for example, tell
|
|
15
|
+
// your coding agent "use CHEATSHEET.md to set up a fetch
|
|
16
|
+
// request for most recent context items."
|
|
17
|
+
//
|
|
18
|
+
// IMPORTANT: before testing your custom tool, remember to
|
|
19
|
+
// populate the "manifest.json" file so surph knows when to
|
|
20
|
+
// use it. To do so, run:
|
|
21
|
+
//
|
|
22
|
+
// npx @surph_ai/cli manifest
|
|
23
|
+
|
|
24
|
+
// this is your tool final payload:
|
|
25
|
+
return {}
|
|
26
|
+
} catch (error: any) {
|
|
27
|
+
throw error
|
|
28
|
+
}
|
|
10
29
|
};
|
|
11
30
|
|
|
12
31
|
export default handler;
|
|
13
32
|
|
|
33
|
+
// some fake api services to get you started:
|
|
34
|
+
// https://www.mydummyapi.com/
|
|
35
|
+
// https://dummyjson.com/
|
|
36
|
+
// https://jsonplaceholder.typicode.com/
|
|
37
|
+
//
|
package/toolserver/app.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const express = require('express')
|
|
2
2
|
const path = require('path')
|
|
3
3
|
const vinely = require('@vinely-ai/sdk')
|
|
4
|
-
const { config, configureApp } = require('./middleware/index.js')
|
|
4
|
+
const { config, configureApp, board } = require('./middleware/index.js')
|
|
5
5
|
|
|
6
6
|
const app = express()
|
|
7
7
|
|
|
@@ -11,6 +11,7 @@ configureApp(app, {
|
|
|
11
11
|
})
|
|
12
12
|
|
|
13
13
|
app.use(config)
|
|
14
|
+
app.use(board)
|
|
14
15
|
|
|
15
16
|
const rpc = require('./routes/rpc')
|
|
16
17
|
const api = require('./routes/api')
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
const { SURPH_S3_URL } = require('../../utils/constants.js')
|
|
2
|
+
const boardConfiguration = require('../../utils/boardConfiguration.js')
|
|
3
|
+
|
|
4
|
+
module.exports = async (req, res, next) => {
|
|
5
|
+
const headers = req.headers;
|
|
6
|
+
const host = headers.host; // "beltwaybits.surph.ai"
|
|
7
|
+
// console.log('SURPH HOST = = = = = ' + host)
|
|
8
|
+
|
|
9
|
+
if (host === 'surph.ai' || host === 'www.surph.ai') {
|
|
10
|
+
return next();
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
let surphBoard = process.env.SURPH_BOARD;
|
|
14
|
+
|
|
15
|
+
// if (host.includes('surph.ai')) {
|
|
16
|
+
// const parts = host.split('.');
|
|
17
|
+
// surphBoard = parts[0];
|
|
18
|
+
// } else {
|
|
19
|
+
// surphBoard = process.env.SURPH_BOARD;
|
|
20
|
+
// }
|
|
21
|
+
|
|
22
|
+
// console.log('SURPH_BOARD_ENV: ', surphBoard);
|
|
23
|
+
if (!surphBoard) {
|
|
24
|
+
return next();
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (req.surph_board) {
|
|
28
|
+
return next();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// const surph_board = await boardConfiguration(surphBoard);
|
|
32
|
+
const { board, contexts, tides, tools } = await boardConfiguration(surphBoard);
|
|
33
|
+
|
|
34
|
+
const tideTools = []
|
|
35
|
+
tides.forEach(t => {
|
|
36
|
+
t.tools.forEach(toolSlug => {
|
|
37
|
+
if (tideTools.indexOf(toolSlug) === -1)
|
|
38
|
+
tideTools.push(toolSlug)
|
|
39
|
+
})
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
// console.log('TIDE TOLS: ' + JSON.stringify(tideTools))
|
|
43
|
+
|
|
44
|
+
const _tools = []
|
|
45
|
+
tools.forEach(t => {
|
|
46
|
+
if (tideTools.indexOf(t.slug) === -1) {
|
|
47
|
+
_tools.push({ ...t })
|
|
48
|
+
} else {
|
|
49
|
+
_tools.push({ ...t, origin: 'tide' })
|
|
50
|
+
}
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
req.surph_board = {
|
|
55
|
+
// ...surph_board,
|
|
56
|
+
...board,
|
|
57
|
+
contexts,
|
|
58
|
+
tides,
|
|
59
|
+
// tools,
|
|
60
|
+
tools: _tools,
|
|
61
|
+
relativePath: `${SURPH_S3_URL}/boards/${surphBoard}/`
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
// console.log('\n\nSURPH_BOARD: ', JSON.stringify(req.surph_board));
|
|
65
|
+
next();
|
|
66
|
+
}
|
|
@@ -3,6 +3,7 @@ const os = require('os')
|
|
|
3
3
|
const path = require('path')
|
|
4
4
|
const fs = require('fs')
|
|
5
5
|
const userConfiguration = require('../../utils/userConfiguration')
|
|
6
|
+
const boardConfiguration = require('../../utils/boardConfiguration')
|
|
6
7
|
const manifest = require('../../../../../manifest.json')
|
|
7
8
|
|
|
8
9
|
const SURPH_S3_URL = 'https://surph.s3.us-east-1.amazonaws.com'
|
|
@@ -34,13 +35,32 @@ router.get('/', async (req, res, next) => {
|
|
|
34
35
|
// production shape the web app consumes — useSettings.js reads
|
|
35
36
|
// `preloaded.user` and downstream code branches on `_id`.
|
|
36
37
|
const session = readSurphSession()
|
|
37
|
-
const { user, contexts, tides, tools } = session?.userId? await userConfiguration({ id: session.userId }) : null
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
38
|
+
// const { user, contexts, tides, tools } = session?.userId? await userConfiguration({ id: session.userId }) : null
|
|
39
|
+
const userConfig = session?.userId? await userConfiguration({ id: session.userId }) : null
|
|
40
|
+
|
|
41
|
+
let title = 'Surph AI'
|
|
42
|
+
let ctx = null
|
|
43
|
+
let board = null
|
|
44
|
+
let tools = null
|
|
45
|
+
let tides = null
|
|
46
|
+
let contexts = null
|
|
47
|
+
|
|
48
|
+
if (req.surph_board) {
|
|
49
|
+
ctx = req.surph_board.contexts[0] // change this to "defaultContext"
|
|
50
|
+
board = req.surph_board
|
|
51
|
+
title = req.surph_board.name
|
|
52
|
+
|
|
53
|
+
tools = req.surph_board.tools
|
|
54
|
+
tides = req.surph_board.tides
|
|
55
|
+
contexts = req.surph_board.contexts
|
|
56
|
+
} else {
|
|
57
|
+
tools = userConfig.tools
|
|
58
|
+
tides = userConfig.tides
|
|
59
|
+
contexts = userConfig.contexts
|
|
42
60
|
}
|
|
43
61
|
|
|
62
|
+
const user = userConfig.user
|
|
63
|
+
const creator = { _id: user._id, username: user.username, avatar: user.avatar }
|
|
44
64
|
const localTools = toolSlugs.map(slug => {
|
|
45
65
|
const tool = manifest[slug]
|
|
46
66
|
let isTideTool = false
|
|
@@ -59,6 +79,9 @@ router.get('/', async (req, res, next) => {
|
|
|
59
79
|
const context = {
|
|
60
80
|
env: 'sandbox',
|
|
61
81
|
mode: 'desktop',
|
|
82
|
+
title,
|
|
83
|
+
board,
|
|
84
|
+
context: ctx,
|
|
62
85
|
user,
|
|
63
86
|
config: { ...req.config, entry: 'web' },
|
|
64
87
|
contexts,
|
|
@@ -17,11 +17,11 @@ const loadTool = () => import(toolsPath).then((mod) => mod.default)
|
|
|
17
17
|
const router = Router()
|
|
18
18
|
|
|
19
19
|
const handler = async (event, tool) => {
|
|
20
|
-
const { args, context, user } = event
|
|
20
|
+
const { args, context, user, board } = event
|
|
21
21
|
let payload = null
|
|
22
22
|
let errorMsg = null
|
|
23
23
|
try {
|
|
24
|
-
payload = await tool({ args, context, user })
|
|
24
|
+
payload = await tool({ args, context, user, board })
|
|
25
25
|
} catch (error) {
|
|
26
26
|
errorMsg = error instanceof Error ? error.message : String(error)
|
|
27
27
|
} finally {
|
|
@@ -94,13 +94,13 @@ router.get('/test', async (req, res, next) => {
|
|
|
94
94
|
|
|
95
95
|
router.post('/custom', async (req, res, next) => {
|
|
96
96
|
try {
|
|
97
|
-
const { name, args, tool, user = null, context = null } = req.body;
|
|
97
|
+
const { name, args, tool, user = null, context = null, board = null } = req.body;
|
|
98
98
|
// if (process.env.SURPH_TOOL !== tool.slug) {
|
|
99
99
|
// throw new Error(`Invalid tool ${tool.slug}. Check .env file.`)
|
|
100
100
|
// }
|
|
101
101
|
|
|
102
102
|
const toolRunner = await loadTool()
|
|
103
|
-
const response = await handler({ args, context, user }, toolRunner)
|
|
103
|
+
const response = await handler({ args, context, user, board }, toolRunner)
|
|
104
104
|
if (response.error) {
|
|
105
105
|
throw new Error(response.error);
|
|
106
106
|
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
const { REST_API_URL } = require('./constants.js')
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
const BOARD_CACHE = {};
|
|
5
|
+
// testing for https://beltwaybits.surph.ai/:
|
|
6
|
+
// const testBoard = 'beltwaybits'
|
|
7
|
+
// const resp = await fetch(`${REST_API_URL}/rest/context?boards.slug=${testBoard}`)
|
|
8
|
+
// const { payload } = await resp.json();
|
|
9
|
+
// ctx = Array.isArray(payload) ? payload[0] || null : payload;
|
|
10
|
+
// board = ctx.boards.find((b: any) => b.slug === testBoard)
|
|
11
|
+
// board.relativePath = `${SURPH_S3_URL}/boards/${testBoard}/`
|
|
12
|
+
// title = board.name
|
|
13
|
+
const boardConfiguration = async (boardSlug) => {
|
|
14
|
+
try {
|
|
15
|
+
if (!boardSlug)
|
|
16
|
+
return null;
|
|
17
|
+
if (BOARD_CACHE[boardSlug]) {
|
|
18
|
+
if (BOARD_CACHE[boardSlug] === 'pending') {
|
|
19
|
+
// console.log('PENDING')
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
return BOARD_CACHE[boardSlug];
|
|
23
|
+
}
|
|
24
|
+
BOARD_CACHE[boardSlug] = 'pending';
|
|
25
|
+
const response = await fetch(`${REST_API_URL}/queries/board_configuration`, {
|
|
26
|
+
method: 'POST',
|
|
27
|
+
body: JSON.stringify({ board: boardSlug }),
|
|
28
|
+
headers: {
|
|
29
|
+
'Accept': 'application/json',
|
|
30
|
+
'Content-type': 'application/json',
|
|
31
|
+
'x-surph-client': 'surph-webapp',
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
const { payload } = await response.json();
|
|
35
|
+
BOARD_CACHE[boardSlug] = payload;
|
|
36
|
+
// console.log('PAYLOAD: ' + JSON.stringify(payload));
|
|
37
|
+
const { board, contexts, tides, tools } = payload;
|
|
38
|
+
return { board, contexts, tides, tools };
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
console.error('Error fetching board: ', error.message);
|
|
42
|
+
throw error;
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
module.exports = boardConfiguration;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
const SURPH_S3_URL = 'https://surph.s3.us-east-1.amazonaws.com'
|
|
2
|
+
const REST_API_URL = 'https://surph-mongo-http-19075ff8d93f.herokuapp.com';
|
|
3
|
+
const S3_BUCKET = 'https://surph.s3.us-east-1.amazonaws.com';
|
|
4
|
+
|
|
5
|
+
module.exports = {
|
|
6
|
+
SURPH_S3_URL,
|
|
7
|
+
REST_API_URL,
|
|
8
|
+
S3_BUCKET
|
|
9
|
+
}
|