Skip to content

Commit 90df66c

Browse files
committed
Support some basic .well-known endpoints by default for LLM integration
1 parent 11d0615 commit 90df66c

File tree

3 files changed

+478
-63
lines changed

3 files changed

+478
-63
lines changed

lib/gateway.js

Lines changed: 43 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,24 @@ class Gateway extends EventEmitter {
226226
);
227227
}
228228

229+
__wellKnownError__ (req, res, message, status, headers) {
230+
headers = headers || {};
231+
headers = this.__createHeaders__(req, headers);
232+
headers['content-type'] = 'application/json';
233+
return this.__endRequest__(
234+
status || 403,
235+
this.__formatHeaders__(headers),
236+
req,
237+
res,
238+
JSON.stringify({
239+
error: {
240+
type: 'WellKnownError',
241+
message: message
242+
}
243+
})
244+
);
245+
}
246+
229247
__clientError__ (req, res, message, status, headers) {
230248
headers = headers || {};
231249
headers = this.__createHeaders__(req, headers);
@@ -1315,17 +1333,25 @@ class Gateway extends EventEmitter {
13151333
if (definition.hasOwnProperty('wellKnown')) {
13161334
const wellKnown = definition.wellKnown;
13171335
const definitions = definition.definitions;
1336+
const pluginSupported = !!data.pluginSupported;
1337+
const pluginAuthorized = !!data.pluginAuthorized;
1338+
if (!pluginSupported) {
1339+
return this.__wellKnownError__(req, res, `Plugin not supported for this service`, 404);
1340+
} else if (!pluginAuthorized) {
1341+
return this.__wellKnownError__(req, res, `Plugin access not authorized`, 403);
1342+
}
1343+
let plugin;
1344+
try {
1345+
plugin = wellKnowns.validatePlugin(data.plugin);
1346+
} catch (e) {
1347+
return this.__wellKnownError__(req, res, `Failed to validate plugin: ${e.message}`, 502);
1348+
}
1349+
const server = data.server;
1350+
const origin = data.origin;
1351+
const identifier = data.identifier;
13181352
let httpResponse;
13191353
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-
}
1354+
httpResponse = wellKnowns.handlers[wellKnown](definitions, plugin, server, origin, identifier);
13291355
} catch (e) {
13301356
return this.__fatalError__(req, res, `Error running .well-known handler for "${wellKnown}"`, e.stack);
13311357
}
@@ -1668,9 +1694,9 @@ class Gateway extends EventEmitter {
16681694
name = name.replace(/^\/?(.*?)\/?$/gi, '$1');
16691695
let definition = definitions[name];
16701696
if (!definition) {
1671-
if (wellKnowns[name]) {
1697+
if (wellKnowns.handlers[name]) {
16721698
return {
1673-
wellKnown: wellKnowns[name],
1699+
wellKnown: name,
16741700
definitions: definitions
16751701
};
16761702
} else {
@@ -1701,6 +1727,12 @@ class Gateway extends EventEmitter {
17011727
}
17021728
let data = {};
17031729
data.canDebug = true;
1730+
data.pluginSupported = true;
1731+
data.pluginAuthorized = true;
1732+
data.plugin = {};
1733+
data.server = 'FunctionScript Gateway';
1734+
data.origin = urlinfo.origin;
1735+
data.identifier = 'service.localhost';
17041736
return callback(null, definition, data, buffer);
17051737
}
17061738

@@ -2160,53 +2192,6 @@ class Gateway extends EventEmitter {
21602192
}
21612193
}
21622194

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-
22102195
end (req, value) {
22112196
// do nothing, response completed
22122197
// this.log(req, value, 'result');

0 commit comments

Comments
 (0)