Skip to content

Commit eaf26bd

Browse files
committed
✨ feat: 先使用最简单的方式迁移插件服务端
1 parent d8bb922 commit eaf26bd

File tree

16 files changed

+422
-3
lines changed

16 files changed

+422
-3
lines changed

api/v1/runner.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { PluginsMap } from '../../plugins';
12
import { OpenAIPluginPayload } from '../../types/plugins';
23

34
export const runtime = 'edge';
@@ -9,7 +10,7 @@ export default async (req: Request) => {
910

1011
console.log(`检测到 functionCall: ${name}`);
1112

12-
const func = { runner: (params: any) => params };
13+
const func = PluginsMap[name];
1314

1415
if (func) {
1516
const data = JSON.parse(args);

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@
3030
"last 2 versions",
3131
"not ie <= 10"
3232
],
33+
"dependencies": {
34+
"query-string": "^8"
35+
},
3336
"devDependencies": {
3437
"@lobehub/lint": "latest",
3538
"@vercel/node": "^2",

plugins/index.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { PluginItem } from '../types/pluginItem';
2+
import searchEngine from './searchEngine';
3+
import getWeather from './weather';
4+
import webCrawler from './webCrawler';
5+
6+
export const PluginsMap: Record<string, PluginItem> = {
7+
[getWeather.name]: getWeather,
8+
[searchEngine.name]: searchEngine,
9+
[webCrawler.name]: webCrawler,
10+
};

plugins/searchEngine/index.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { PluginItem } from '../../types/pluginItem';
2+
import runner from './runner';
3+
import { Result } from './type';
4+
5+
const schema: PluginItem['schema'] = {
6+
description: '查询搜索引擎获取信息',
7+
name: 'searchEngine',
8+
parameters: {
9+
properties: {
10+
keywords: {
11+
description: '关键词',
12+
type: 'string',
13+
},
14+
},
15+
required: ['keywords'],
16+
type: 'object',
17+
},
18+
};
19+
20+
const searchEngine: PluginItem<Result> = {
21+
avatar: '🔍',
22+
name: 'searchEngine',
23+
runner,
24+
schema,
25+
};
26+
27+
export default searchEngine;

plugins/searchEngine/runner.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import querystring from 'query-string';
2+
3+
import { PluginRunner } from '../../types/pluginItem';
4+
import { OrganicResults, Result } from './type';
5+
6+
const BASE_URL = 'https://serpapi.com/search';
7+
8+
const API_KEY = process.env.SERPAI_API_KEY;
9+
10+
const fetchResult: PluginRunner<{ keywords: string }, Result> = async ({ keywords }) => {
11+
const params = {
12+
api_key: API_KEY,
13+
engine: 'google',
14+
gl: 'cn',
15+
google_domain: 'google.com',
16+
hl: 'zh-cn',
17+
location: 'China',
18+
q: keywords,
19+
};
20+
21+
const query = querystring.stringify(params);
22+
23+
const res = await fetch(`${BASE_URL}?${query}`);
24+
25+
const data = await res.json();
26+
27+
const results = data.organic_results as OrganicResults;
28+
29+
return results.map((r) => ({
30+
content: r.snippet,
31+
date: r.date,
32+
displayed_link: r.displayed_link,
33+
favicon: r.favicon,
34+
link: r.link,
35+
source: r.source,
36+
title: r.title,
37+
}));
38+
};
39+
40+
export default fetchResult;

plugins/searchEngine/type.ts

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
export type OrganicResults = OrganicResult[];
2+
3+
export interface SearchItem {
4+
content: string;
5+
date?: string;
6+
displayed_link?: string;
7+
favicon?: string;
8+
link: string;
9+
source?: string;
10+
title: string;
11+
}
12+
export type Result = SearchItem[];
13+
14+
interface OrganicResult {
15+
about_page_link: string;
16+
about_page_serpapi_link: string;
17+
about_this_result: AboutThisResult;
18+
cached_page_link?: string;
19+
date?: string;
20+
displayed_link: string;
21+
favicon?: string;
22+
link: string;
23+
position: number;
24+
related_results?: RelatedResult[];
25+
rich_snippet?: RichSnippet;
26+
snippet: string;
27+
snippet_highlighted_words?: string[];
28+
source: string;
29+
thumbnail?: string;
30+
title: string;
31+
}
32+
33+
interface AboutThisResult {
34+
languages: string[];
35+
regions: string[];
36+
source: Source;
37+
}
38+
39+
interface Source {
40+
description: string;
41+
icon: string;
42+
security?: string;
43+
source_info_link?: string;
44+
}
45+
46+
interface RelatedResult {
47+
about_page_link: string;
48+
about_page_serpapi_link: string;
49+
about_this_result: AboutThisResult2;
50+
cached_page_link: string;
51+
date: string;
52+
displayed_link: string;
53+
link: string;
54+
position: number;
55+
snippet: string;
56+
snippet_highlighted_words: string[];
57+
title: string;
58+
}
59+
60+
interface AboutThisResult2 {
61+
languages: string[];
62+
regions: string[];
63+
source: Source2;
64+
}
65+
66+
interface Source2 {
67+
description: string;
68+
icon: string;
69+
}
70+
71+
interface RichSnippet {
72+
top: Top;
73+
}
74+
75+
interface Top {
76+
detected_extensions: DetectedExtensions;
77+
extensions: string[];
78+
}
79+
80+
interface DetectedExtensions {
81+
month_ago: number;
82+
}

plugins/weather/index.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { PluginItem } from '../../types/pluginItem';
2+
import runner from './runner';
3+
import { WeatherResult } from './type';
4+
5+
const schema: PluginItem['schema'] = {
6+
description: '获取当前天气情况',
7+
name: 'realtimeWeather',
8+
parameters: {
9+
properties: {
10+
city: {
11+
description: '城市名称',
12+
type: 'string',
13+
},
14+
},
15+
required: ['city'],
16+
type: 'object',
17+
},
18+
};
19+
20+
const getWeather: PluginItem<WeatherResult> = {
21+
avatar: '☂️',
22+
name: 'realtimeWeather',
23+
runner,
24+
schema,
25+
};
26+
27+
export default getWeather;

plugins/weather/runner.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { PluginRunner } from '../../types/pluginItem';
2+
import { Response, WeatherParams, WeatherResult } from './type';
3+
4+
const weatherBaseURL = 'https://restapi.amap.com/v3/weather/weatherInfo';
5+
6+
const citySearchURL = 'https://restapi.amap.com/v3/config/district';
7+
8+
const KEY = process.env.GAODE_WEATHER_KEY;
9+
10+
const fetchCityCode = async (keywords: string): Promise<string> => {
11+
const URL = `${citySearchURL}?keywords=${keywords}&subdistrict=0&extensions=base&key=${KEY}`;
12+
const res = await fetch(URL);
13+
14+
const data = await res.json();
15+
console.log(data);
16+
17+
return data.districts[0].adcode;
18+
};
19+
20+
const fetchWeather: PluginRunner<WeatherParams, WeatherResult> = async ({
21+
city,
22+
extensions = 'all',
23+
}) => {
24+
const cityCode = await fetchCityCode(city);
25+
26+
const URL = `${weatherBaseURL}?city=${cityCode}&extensions=${extensions}&key=${KEY}`;
27+
const res = await fetch(URL);
28+
29+
const data: Response = await res.json();
30+
31+
return data.forecasts;
32+
};
33+
34+
export default fetchWeather;

plugins/weather/type.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
export interface WeatherParams {
2+
city: string;
3+
extensions?: 'base' | 'all';
4+
}
5+
export type WeatherResult = Forecast[];
6+
7+
export interface Response {
8+
count: string;
9+
forecasts: Forecast[];
10+
info: string;
11+
infocode: string;
12+
status: string;
13+
}
14+
15+
export interface Forecast {
16+
adcode: string;
17+
casts: Cast[];
18+
city: string;
19+
province: string;
20+
reporttime: string;
21+
}
22+
23+
export interface Cast {
24+
date: string;
25+
daypower: string;
26+
daytemp: string;
27+
daytemp_float: string;
28+
dayweather: string;
29+
daywind: string;
30+
nightpower: string;
31+
nighttemp: string;
32+
nighttemp_float: string;
33+
nightweather: string;
34+
nightwind: string;
35+
week: string;
36+
}

plugins/webCrawler/index.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { PluginItem } from '../../types/pluginItem';
2+
import runner from './runner';
3+
import { Result } from './type';
4+
5+
const schema = {
6+
description: '提取网页内容并总结',
7+
name: 'websiteCrawler',
8+
parameters: {
9+
properties: {
10+
url: {
11+
description: '网页内容',
12+
type: 'string',
13+
},
14+
},
15+
required: ['url'],
16+
type: 'object',
17+
},
18+
};
19+
20+
const getWeather: PluginItem<Result> = { avatar: '🕸', name: 'websiteCrawler', runner, schema };
21+
22+
export default getWeather;

0 commit comments

Comments
 (0)