Skip to content

Commit 11d0615

Browse files
committed
Support OpenAI-style plugins by default
1 parent 68b3b7e commit 11d0615

File tree

2 files changed

+99
-4
lines changed

2 files changed

+99
-4
lines changed

lib/gateway.js

Lines changed: 92 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const uuid = require('uuid');
1111

1212
const backgroundValidator = require('./background_validator.js');
1313
const types = require('./types.js');
14+
const wellKnowns = require('./well-knowns.js');
1415

1516
const AsyncFunction = Object.getPrototypeOf(async function () {}).constructor;
1617

@@ -212,6 +213,19 @@ class Gateway extends EventEmitter {
212213
this._serverSentEvents[req._uuid] = sseInstance;
213214
}
214215

216+
__wellKnownResponse__ (req, res, body, headers) {
217+
headers = headers || {};
218+
headers = this.__createHeaders__(req, headers);
219+
headers['content-type'] = 'application/json';
220+
return this.__endRequest__(
221+
200,
222+
this.__formatHeaders__(headers),
223+
req,
224+
res,
225+
body
226+
);
227+
}
228+
215229
__clientError__ (req, res, message, status, headers) {
216230
headers = headers || {};
217231
headers = this.__createHeaders__(req, headers);
@@ -1298,6 +1312,26 @@ class Gateway extends EventEmitter {
12981312
return this.__clientError__(req, res, err.message, err.statusCode || 400);
12991313
}
13001314

1315+
if (definition.hasOwnProperty('wellKnown')) {
1316+
const wellKnown = definition.wellKnown;
1317+
const definitions = definition.definitions;
1318+
let httpResponse;
1319+
try {
1320+
if (wellKnown === 'ai-plugin') {
1321+
httpResponse = this.wellKnownAIPlugin(definitions, data);
1322+
} else if (wellKnown === 'api') {
1323+
httpResponse = this.wellKnownAPIDefinition(definitions, data);
1324+
} else if (wellKnown === 'openapi') {
1325+
httpResponse = this.wellKnownOpenAPIDefinition(definitions, data);
1326+
} else {
1327+
return this.__fatalError__(req, res, `No .well-known handler for "${wellKnown}"`);
1328+
}
1329+
} catch (e) {
1330+
return this.__fatalError__(req, res, `Error running .well-known handler for "${wellKnown}"`, e.stack);
1331+
}
1332+
return this.__wellKnownResponse__(req, res, httpResponse.body, httpResponse.headers);
1333+
}
1334+
13011335
let headers = {};
13021336
headers['x-execution-uuid'] = req._uuid;
13031337
if (definition.origins) {
@@ -1634,11 +1668,18 @@ class Gateway extends EventEmitter {
16341668
name = name.replace(/^\/?(.*?)\/?$/gi, '$1');
16351669
let definition = definitions[name];
16361670
if (!definition) {
1637-
let subname = name;
1638-
definition = definitions[`${subname}:notfound`];
1639-
while (subname && !definition) {
1640-
subname = subname.substr(0, subname.lastIndexOf('/'));
1671+
if (wellKnowns[name]) {
1672+
return {
1673+
wellKnown: wellKnowns[name],
1674+
definitions: definitions
1675+
};
1676+
} else {
1677+
let subname = name;
16411678
definition = definitions[`${subname}:notfound`];
1679+
while (subname && !definition) {
1680+
subname = subname.substr(0, subname.lastIndexOf('/'));
1681+
definition = definitions[`${subname}:notfound`];
1682+
}
16421683
}
16431684
}
16441685
if (!definition) {
@@ -2119,6 +2160,53 @@ class Gateway extends EventEmitter {
21192160
}
21202161
}
21212162

2163+
wellKnownAIPlugin (definitions, data) {
2164+
return {
2165+
headers: {},
2166+
body: Buffer.from(
2167+
JSON.stringify(
2168+
{
2169+
"schema_version": "v1",
2170+
"name_for_human": "TODO List (service auth)",
2171+
"name_for_model": "todo",
2172+
"description_for_human": "Manage your TODO list. You can add, remove and view your TODOs.",
2173+
"description_for_model": "Plugin for managing a TODO list, you can add, remove and view your TODOs.",
2174+
"auth": {
2175+
"type": "service_http",
2176+
"authorization_type": "bearer",
2177+
"verification_tokens": {
2178+
"openai": "Replace_this_string_with_the_verification_token_generated_in_the_ChatGPT_UI"
2179+
}
2180+
},
2181+
"api": {
2182+
"type": "openapi",
2183+
"url": "https://example.com/openapi.yaml"
2184+
},
2185+
"logo_url": "https://example.com/logo.png",
2186+
"contact_email": "support@example.com",
2187+
"legal_info_url": "https://example.com/legal"
2188+
},
2189+
null,
2190+
2
2191+
)
2192+
)
2193+
};
2194+
}
2195+
2196+
wellKnownAPIDefinition (definitions, data) {
2197+
return {
2198+
headers: {},
2199+
body: Buffer.from(JSON.stringify(definitions, null, 2))
2200+
}
2201+
}
2202+
2203+
wellKnownOpenAPIDefinition (definitions, data) {
2204+
return {
2205+
headers: {},
2206+
body: Buffer.from('OpenAPI Spec')
2207+
}
2208+
}
2209+
21222210
end (req, value) {
21232211
// do nothing, response completed
21242212
// this.log(req, value, 'result');

lib/well-knowns.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
const wellKnown = {
2+
'.well-known/ai-plugin.json': 'ai-plugin',
3+
'.well-known/api.json': 'api',
4+
'.well-known/openapi.yaml': 'openapi'
5+
};
6+
7+
module.exports = wellKnown;

0 commit comments

Comments
 (0)