UNPKG

sensai

Version:

Because even AI needs a master

180 lines (179 loc) 6.74 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, /** * Create a resource based router where route are grouped by verbs/methods * and versions. * * @param rootDir directory used to create absolute path for route filepath */ "default", { enumerable: true, get: function() { return _default; } }); const _nodepath = require("node:path"); const _metadata = /*#__PURE__*/ _interop_require_default(require("./metadata")); const _trie = /*#__PURE__*/ _interop_require_default(require("./trie")); const _middlewares = /*#__PURE__*/ _interop_require_default(require("./middlewares")); const _orchestrator = /*#__PURE__*/ _interop_require_default(require("./orchestrator")); const _constants = require("../../constants"); function _interop_require_default(obj) { return obj && obj.__esModule ? obj : { default: obj }; } const _default = async (rootDir = "")=>{ const resources = new Map(); const middlewares = (0, _middlewares.default)(); const orchestrator = (0, _orchestrator.default)(); const routes = (0, _trie.default)(); /** * Add route with its optional middleware in the router/resource resolution. */ const addRoute = (routePath, type)=>{ const { pathname, method, version } = (0, _metadata.default)(routePath); //const relativePath = relative(rootDir, pathname) || '/' const relativePath = pathname; const endpoint = resources.get(relativePath) || {}; resources.set(relativePath, { ...endpoint, [method]: { ...endpoint[method], [version]: { // TODO the join rootDIr should be donei walker // middlewares: middlewarePaths.map((path) => join(rootDir, path)), route: (0, _nodepath.join)(rootDir, routePath), type } } }); routes.add(relativePath); }; const addTool = (toolPath)=>{ const filename = (0, _nodepath.basename)(toolPath); // TODO merge with get metadata const chunks = filename.split("."); if (chunks.length === 3) { const dirPath = (0, _nodepath.dirname)(toolPath); const resource = resources.get(dirPath) || {}; resources.set(dirPath, { ...resource, tool: [ { name: chunks[1], path: toolPath }, ...resource.tool || [] ] }); } }; return { add (filePath) { const prefix = getPrefix(filePath); switch(prefix){ case _constants.FILE_TYPE.MIDDLEWARE: case _constants.FILE_TYPE.AUTHORIZER: middlewares.add(filePath); break; case _constants.FILE_TYPE.ROUTE: case _constants.FILE_TYPE.MOCK: case _constants.FILE_TYPE.PROMPT: case _constants.FILE_TYPE.ORCHESTRATOR: addRoute(filePath, prefix); // a prompt can easily be switched into an orchestrator orchestrator.add(filePath); break; case _constants.FILE_TYPE.TOOL: addTool(filePath); break; } }, /** * An orchestrator can use agents as tools to create multi-agent * orchetration. */ getAgents (folderPath) { return orchestrator.get(folderPath); }, /** * Tools apply to a resource (i.e collection of routes under a URL segment). */ getTools (folderPath) { const resource = resources.get(folderPath.substring(rootDir.length)); return resource?.tool || []; }, /** * Lookup a path in the router Map. */ lookup (urlPath) { // TODO only use sanitizedUrl if we don't find anything int he static cache //const sanitizedUrl = sanitize(urlPath) //return resources.get(urlPath) const route = routes.lookup(urlPath); if (route) { const resource = resources.get(route.path); if (resource) { return { ...route, resource, // TODO we should move middlewares to build time (i.e NOT when fetching route) // TODO map/join is not efficient middlewares: middlewares.get(route.path + "/tmp.ts").map((path)=>(0, _nodepath.join)(rootDir, path)) }; } } }, /** * Remove a file from the router. */ remove (filePath) { const prefix = getPrefix(filePath); switch(prefix){ case _constants.FILE_TYPE.MIDDLEWARE: case _constants.FILE_TYPE.AUTHORIZER: { middlewares.remove(filePath); return true; } case _constants.FILE_TYPE.ORCHESTRATOR: { orchestrator.remove(filePath); // no return statement as we want to move on to the next case } case _constants.FILE_TYPE.ROUTE: case _constants.FILE_TYPE.MOCK: case _constants.FILE_TYPE.PROMPT: case _constants.FILE_TYPE.ORCHESTRATOR: { const { pathname, method } = (0, _metadata.default)(filePath); // TODO we should look at version const endpoint = resources.get(pathname); delete endpoint[method]; if (Object.keys(endpoint).length < 1) { routes.remove(pathname); resources.delete(pathname); } return true; } } return false; }, /** * // TODO remove if not needed * Remove all files in a folder */ prune (folderPath) { resources.delete(folderPath); return routes.remove(folderPath, true); } }; }; /** * Return file prefix. * * @examples * * getPrefix('route.get.ts') * // => 'route' * getPrefix('route.ts') * // => 'route' * getPrefix('prompt.name.world.md') * // => 'prompt' */ const getPrefix = (filePath)=>{ return (0, _nodepath.basename)(filePath).split(".")[0]; };