@surph_ai/sdk 0.0.22 → 0.0.25
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/auth/index.js +15 -15
- package/deploy/index.js +0 -1
- package/deploy/tool-handler.js +3 -2
- package/index.js +51 -0
- package/package.json +1 -1
- package/scaffold/index.js +1 -15
- package/scaffold/tool/README.md +0 -3
- package/scaffold/tool/example.txt +1 -0
- package/scaffold/tool/package.json +1 -0
- package/scaffold/tool/tools/index.ts +1 -6
- package/toolserver/chat.js +3 -39
- package/toolserver/routes/tool.js +4 -0
package/auth/index.js
CHANGED
|
@@ -8,22 +8,22 @@ const utils = require('../utils')
|
|
|
8
8
|
module.exports = {
|
|
9
9
|
showPrompt: () => {
|
|
10
10
|
return new Promise((resolve, reject) => {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
11
|
+
const schema = {
|
|
12
|
+
properties: {
|
|
13
|
+
email: {
|
|
14
|
+
description: colors.cyan('\nEmail'),
|
|
15
|
+
required: true
|
|
16
|
+
},
|
|
17
|
+
password: {
|
|
18
|
+
description: colors.cyan('Password'),
|
|
19
|
+
required: true,
|
|
20
|
+
hidden: true
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
prompt.message = null
|
|
26
|
+
prompt.start()
|
|
27
27
|
|
|
28
28
|
// Get two properties from the user: username and email
|
|
29
29
|
prompt.get(schema, (err, result) => {
|
package/deploy/index.js
CHANGED
package/deploy/tool-handler.js
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import tool from './dist/tools/index.js';
|
|
2
2
|
|
|
3
3
|
export const handler = async (event) => {
|
|
4
|
-
const { args = {} } = event;
|
|
4
|
+
const { args = {}, context = null, user = null } = event;
|
|
5
5
|
let payload = null;
|
|
6
6
|
try {
|
|
7
|
-
payload = await tool(args);
|
|
7
|
+
payload = await tool({ args, context, user });
|
|
8
8
|
} catch (error) {
|
|
9
9
|
payload = error instanceof Error ? error.message : String(error);
|
|
10
10
|
}
|
|
11
|
+
|
|
11
12
|
return {
|
|
12
13
|
statusCode: 200,
|
|
13
14
|
body: JSON.stringify(payload),
|
package/index.js
CHANGED
|
@@ -171,6 +171,57 @@ program.command('tool <name>')
|
|
|
171
171
|
.description('create new Surph tool')
|
|
172
172
|
.action(name => scaffold(name, 'tool'))
|
|
173
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
|
+
|
|
174
225
|
/*
|
|
175
226
|
program.command('connect')
|
|
176
227
|
.description('Connect to Surph project')
|
package/package.json
CHANGED
package/scaffold/index.js
CHANGED
|
@@ -60,20 +60,6 @@ module.exports = (name, type = 'app') => {
|
|
|
60
60
|
shell.mkdir('-p', name)
|
|
61
61
|
shell.cd(name)
|
|
62
62
|
|
|
63
|
-
/*
|
|
64
|
-
shell.mkdir('-p', 'server')
|
|
65
|
-
shell.cp('-R', path.join(__dirname, 'tool/server/app.js'), 'server/app.js')
|
|
66
|
-
shell.cp('-R', path.join(__dirname, 'tool/package.json'), 'package.json')
|
|
67
|
-
|
|
68
|
-
// routes:
|
|
69
|
-
shell.mkdir('-p', 'server/routes')
|
|
70
|
-
shell.cp('-R', path.join(__dirname, `tool/server/routes/*`), 'server/routes/')
|
|
71
|
-
|
|
72
|
-
// views:
|
|
73
|
-
shell.mkdir('-p', 'server/templates')
|
|
74
|
-
shell.cp('-R', path.join(__dirname, `tool/server/templates/*`), 'server/templates/')
|
|
75
|
-
*/
|
|
76
|
-
|
|
77
63
|
const pkgJsonStr = utils.readFile(path.join(__dirname, 'tool/package.json'))
|
|
78
64
|
const pkgJson = JSON.parse(pkgJsonStr)
|
|
79
65
|
pkgJson.name = name
|
|
@@ -86,7 +72,7 @@ module.exports = (name, type = 'app') => {
|
|
|
86
72
|
name: 'youtube-transcript',
|
|
87
73
|
slug: 'y2script',
|
|
88
74
|
type: 'custom',
|
|
89
|
-
description: 'Fetch the plain-text transcript (spoken words) of a YouTube video. Use this whenever the user asks about, quotes from, summarizes, or wants to search inside the content of a YouTube video — including questions like "what does this video say about X", "summarize this video", "pull the transcript", or when the user pastes a YouTube URL and expects you to know its contents. Do NOT use this for
|
|
75
|
+
description: 'Fetch the plain-text transcript (spoken words) of a YouTube video. Use this whenever the user asks about, quotes from, summarizes, or wants to search inside the content of a YouTube video — including questions like "what does this video say about X", "summarize this video", "pull the transcript", or when the user pastes a YouTube URL and expects you to know its contents. Do NOT use this for non-YouTube videos (it will fail on other video sources).',
|
|
90
76
|
parameters: {
|
|
91
77
|
type: 'object',
|
|
92
78
|
properties: {
|
package/scaffold/tool/README.md
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
manifest.json is a tool summary for LLMs so they know when and how to invoke a tool. this tool, called "deal finder" scans a provided context for upcoming events, promotional sales, giveaways, specials etc and returns upcoming deals in the response. please fill out the manifest so LLM uses the tool at the appropriate time
|
|
@@ -1,14 +1,9 @@
|
|
|
1
|
-
// Your tools code goes here. When ready, export
|
|
2
|
-
// the tool name in exports at bottom of this file
|
|
3
|
-
// as shown in this demo code:
|
|
4
1
|
import type { ToolHandler, ToolContext, User } from '@surph_ai/sdk';
|
|
5
2
|
|
|
6
|
-
type
|
|
3
|
+
type ToolArgs = {
|
|
7
4
|
// your custom tool args goes here
|
|
8
5
|
};
|
|
9
6
|
|
|
10
|
-
type ToolArgs = YourToolArgs;
|
|
11
|
-
|
|
12
7
|
const handler: ToolHandler<ToolArgs> = async ({ args, user, context }) => {
|
|
13
8
|
// your custom tool code goes here
|
|
14
9
|
};
|
package/toolserver/chat.js
CHANGED
|
@@ -333,7 +333,7 @@ var require_main = __commonJS({
|
|
|
333
333
|
lastError = e;
|
|
334
334
|
}
|
|
335
335
|
}
|
|
336
|
-
|
|
336
|
+
_log(`injecting env (${keysCount}) from ${shortPaths.join(",")} ${dim(`-- tip: ${_getRandomTip()}`)}`);
|
|
337
337
|
}
|
|
338
338
|
if (lastError) {
|
|
339
339
|
return { parsed: parsedAll, error: lastError };
|
|
@@ -46362,7 +46362,6 @@ var require_executeDesktopTool = __commonJS({
|
|
|
46362
46362
|
try {
|
|
46363
46363
|
VectorDBManager = require_VectorDBManager();
|
|
46364
46364
|
} catch (err) {
|
|
46365
|
-
// console.log("[executeDesktopTool] VectorDBManager not available:", err.message);
|
|
46366
46365
|
VectorDBManager = null;
|
|
46367
46366
|
}
|
|
46368
46367
|
function resolvePath(filePath, projectPath) {
|
|
@@ -46497,33 +46496,6 @@ var require_customTool = __commonJS({
|
|
|
46497
46496
|
"server/shared/tools/customTool.js"(exports2, module2) {
|
|
46498
46497
|
var { SURPH_RPC_URL } = require_config();
|
|
46499
46498
|
var TOOL_TIMEOUT_MS = 60 * 1e3;
|
|
46500
|
-
var WEB_API_BASE = process.env.SURPH_ENV === "aws" ? "https://surph.ai" : "http://localhost:3000";
|
|
46501
|
-
async function refreshGoogleOauthViaWeb(userId) {
|
|
46502
|
-
const internalToken = process.env.SURPH_INTERNAL_TOKEN;
|
|
46503
|
-
if (!internalToken) {
|
|
46504
|
-
console.warn("[customTool] SURPH_INTERNAL_TOKEN not set; skipping Google token refresh");
|
|
46505
|
-
return null;
|
|
46506
|
-
}
|
|
46507
|
-
try {
|
|
46508
|
-
const res = await fetch(`${WEB_API_BASE}/api/oauth/google/refresh`, {
|
|
46509
|
-
method: "POST",
|
|
46510
|
-
headers: {
|
|
46511
|
-
"Content-Type": "application/json",
|
|
46512
|
-
"X-Internal-Token": internalToken
|
|
46513
|
-
},
|
|
46514
|
-
body: JSON.stringify({ userId })
|
|
46515
|
-
});
|
|
46516
|
-
if (!res.ok) {
|
|
46517
|
-
console.warn(`[customTool] refresh endpoint returned HTTP ${res.status}`);
|
|
46518
|
-
return null;
|
|
46519
|
-
}
|
|
46520
|
-
const json2 = await res.json().catch(() => null);
|
|
46521
|
-
return json2?.oauth || null;
|
|
46522
|
-
} catch (err) {
|
|
46523
|
-
console.warn("[customTool] refresh endpoint call failed:", err.message);
|
|
46524
|
-
return null;
|
|
46525
|
-
}
|
|
46526
|
-
}
|
|
46527
46499
|
function validateCustomTool(entry) {
|
|
46528
46500
|
if (!entry || typeof entry !== "object") {
|
|
46529
46501
|
return { ok: false, reason: "not an object" };
|
|
@@ -46588,14 +46560,6 @@ var require_customTool = __commonJS({
|
|
|
46588
46560
|
if (!definition) {
|
|
46589
46561
|
return { error: `Custom tool '${name}' not found on user profile` };
|
|
46590
46562
|
}
|
|
46591
|
-
let effectiveOauth = user?.oauth || null;
|
|
46592
|
-
if (user?.oauth?.google?.refreshToken) {
|
|
46593
|
-
const userId = user.id || user._id;
|
|
46594
|
-
if (userId) {
|
|
46595
|
-
const fresh = await refreshGoogleOauthViaWeb(userId);
|
|
46596
|
-
if (fresh) effectiveOauth = fresh;
|
|
46597
|
-
}
|
|
46598
|
-
}
|
|
46599
46563
|
const controller = new AbortController();
|
|
46600
46564
|
const timer = setTimeout(() => controller.abort(), TOOL_TIMEOUT_MS);
|
|
46601
46565
|
try {
|
|
@@ -46608,7 +46572,7 @@ var require_customTool = __commonJS({
|
|
|
46608
46572
|
tool: definition,
|
|
46609
46573
|
context: contextSlug || null,
|
|
46610
46574
|
args: args || {},
|
|
46611
|
-
user: user ? { id: user.id || user._id, username: user.username, oauth:
|
|
46575
|
+
user: user ? { id: user.id || user._id, username: user.username, oauth: user.oauth || {} } : null
|
|
46612
46576
|
}),
|
|
46613
46577
|
signal: controller.signal
|
|
46614
46578
|
});
|
|
@@ -94809,7 +94773,7 @@ ${STREAM_LABEL} provider:${provider} tide:${params?.tide ? "present" : "none"} s
|
|
|
94809
94773
|
});
|
|
94810
94774
|
|
|
94811
94775
|
// server/sdk.js
|
|
94812
|
-
require_main().config();
|
|
94776
|
+
require_main().config({ quiet: true });
|
|
94813
94777
|
process.env.SURPH_CUSTOM_TOOL_RPC = "http://localhost:5000";
|
|
94814
94778
|
var express = require_express2();
|
|
94815
94779
|
var cors = require_lib3();
|
|
@@ -96,6 +96,10 @@ router.post('/custom', async (req, res, next) => {
|
|
|
96
96
|
|
|
97
97
|
const tools = await loadTool()
|
|
98
98
|
const response = await handler({ args, context, user }, tools)
|
|
99
|
+
if (resp.error) {
|
|
100
|
+
throw new Error(resp.error);
|
|
101
|
+
}
|
|
102
|
+
|
|
99
103
|
res.json({ response })
|
|
100
104
|
} catch (error) {
|
|
101
105
|
res.json({
|