veryfront
Advanced tools
+1
-1
| export default { | ||
| "name": "veryfront", | ||
| "version": "0.1.59", | ||
| "version": "0.1.60", | ||
| "license": "Apache-2.0", | ||
@@ -5,0 +5,0 @@ "nodeModulesDir": "auto", |
@@ -29,2 +29,7 @@ import * as dntShim from "../../_dnt.shims.js"; | ||
| } | ||
| /** Options when passing an agent instance directly. */ | ||
| export interface ChatHandlerConfigWithAgent extends ChatHandlerOptions { | ||
| /** The agent instance to use (bypasses registry lookup). */ | ||
| agent: import("./types.js").Agent; | ||
| } | ||
| /** | ||
@@ -37,9 +42,18 @@ * Create a POST handler for a chat API route. | ||
| * | ||
| * Accepts either: | ||
| * - `createChatHandler("agentId", options?)` — looks up agent by ID from the registry | ||
| * - `createChatHandler({ agent, ...options })` — uses the provided agent instance directly | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * import { createChatHandler } from "veryfront/agent"; | ||
| * // By agent ID (requires auto-discovery registration) | ||
| * export const POST = createChatHandler("assistant"); | ||
| * | ||
| * // By agent instance (no registry needed) | ||
| * import { myAgent } from "../../agents/my-agent"; | ||
| * export const POST = createChatHandler({ agent: myAgent, beforeStream: ... }); | ||
| * ``` | ||
| */ | ||
| export declare function createChatHandler(agentId: string, options?: ChatHandlerOptions): (requestOrCtx: unknown) => Promise<dntShim.Response>; | ||
| export declare function createChatHandler(config: ChatHandlerConfigWithAgent, options?: ChatHandlerOptions): (requestOrCtx: unknown) => Promise<dntShim.Response>; | ||
| //# sourceMappingURL=chat-handler.d.ts.map |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"chat-handler.d.ts","sourceRoot":"","sources":["../../../src/src/agent/chat-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,qBAAqB,CAAC;AAG/C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AA8K1C,MAAM,MAAM,uBAAuB,GAAG,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG;IAAE,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAE5E,MAAM,WAAW,8BAA8B;IAC7C,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC;IACzB,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,6BAA6B;IAC5C,OAAO,CAAC,EAAE,uBAAuB,EAAE,CAAC;IACpC,MAAM,CAAC,EAAE,uBAAuB,EAAE,CAAC;IACnC,eAAe,CAAC,EAAE,uBAAuB,EAAE,CAAC;IAC5C,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED,MAAM,MAAM,uBAAuB,GAAG,CACpC,KAAK,EAAE,8BAA8B,KAEnC,IAAI,GACJ,OAAO,CAAC,QAAQ,GAChB,6BAA6B,GAC7B,OAAO,CAAC,IAAI,GAAG,OAAO,CAAC,QAAQ,GAAG,6BAA6B,CAAC,CAAC;AAiCrE,mFAAmF;AACnF,MAAM,WAAW,kBAAkB;IACjC,uFAAuF;IACvF,OAAO,CAAC,EACJ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACvB,CAAC,CACD,OAAO,EAAE,OAAO,CAAC,OAAO,KACrB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IACnE;;;OAGG;IACH,YAAY,CAAC,EAAE,uBAAuB,CAAC;CACxC;AAgDD;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,kBAAkB,IAED,cAAc,OAAO,KAAG,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CA+E7E"} | ||
| {"version":3,"file":"chat-handler.d.ts","sourceRoot":"","sources":["../../../src/src/agent/chat-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,qBAAqB,CAAC;AAG/C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AA8K1C,MAAM,MAAM,uBAAuB,GAAG,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG;IAAE,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAE5E,MAAM,WAAW,8BAA8B;IAC7C,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC;IACzB,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,6BAA6B;IAC5C,OAAO,CAAC,EAAE,uBAAuB,EAAE,CAAC;IACpC,MAAM,CAAC,EAAE,uBAAuB,EAAE,CAAC;IACnC,eAAe,CAAC,EAAE,uBAAuB,EAAE,CAAC;IAC5C,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED,MAAM,MAAM,uBAAuB,GAAG,CACpC,KAAK,EAAE,8BAA8B,KAEnC,IAAI,GACJ,OAAO,CAAC,QAAQ,GAChB,6BAA6B,GAC7B,OAAO,CAAC,IAAI,GAAG,OAAO,CAAC,QAAQ,GAAG,6BAA6B,CAAC,CAAC;AAiCrE,mFAAmF;AACnF,MAAM,WAAW,kBAAkB;IACjC,uFAAuF;IACvF,OAAO,CAAC,EACJ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACvB,CAAC,CACD,OAAO,EAAE,OAAO,CAAC,OAAO,KACrB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IACnE;;;OAGG;IACH,YAAY,CAAC,EAAE,uBAAuB,CAAC;CACxC;AAED,uDAAuD;AACvD,MAAM,WAAW,0BAA2B,SAAQ,kBAAkB;IACpE,4DAA4D;IAC5D,KAAK,EAAE,OAAO,YAAY,EAAE,KAAK,CAAC;CACnC;AAwDD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,kBAAkB,GAC3B,CAAC,YAAY,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;AACxD,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,0BAA0B,EAClC,OAAO,CAAC,EAAE,kBAAkB,GAC3B,CAAC,YAAY,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC"} |
@@ -158,2 +158,7 @@ import * as dntShim from "../../_dnt.shims.js"; | ||
| } | ||
| function mergeChatHandlerConfig(config, options) { | ||
| if (!options) | ||
| return config; | ||
| return { ...options, ...config }; | ||
| } | ||
| /** | ||
@@ -199,25 +204,22 @@ * Extract the raw Request from either a raw Request or a Pages Router APIContext. | ||
| } | ||
| /** | ||
| * Create a POST handler for a chat API route. | ||
| * | ||
| * Works with both App Router and Pages Router: | ||
| * - App Router: `app/api/chat/route.ts` — handler receives `(request, context)` | ||
| * - Pages Router: `pages/api/chat.ts` — handler receives `(ctx)` | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * import { createChatHandler } from "veryfront/agent"; | ||
| * export const POST = createChatHandler("assistant"); | ||
| * ``` | ||
| */ | ||
| export function createChatHandler(agentId, options) { | ||
| export function createChatHandler(agentIdOrConfig, options) { | ||
| return async function POST(requestOrCtx) { | ||
| const request = extractRequest(requestOrCtx); | ||
| let agent; | ||
| try { | ||
| agent = getAgent(agentId); | ||
| if (typeof agentIdOrConfig === "object" && agentIdOrConfig !== null && "agent" in agentIdOrConfig) { | ||
| // Object-based API: createChatHandler({ agent, beforeStream, ... }) | ||
| const config = mergeChatHandlerConfig(agentIdOrConfig, options); | ||
| agent = config.agent; | ||
| options = config; | ||
| } | ||
| catch (error) { | ||
| agentLogger.debug("getAgent lookup failed", { error }); | ||
| return dntShim.Response.json({ error: "Agent not found" }, { status: 404 }); | ||
| else { | ||
| // String-based API: createChatHandler("agentId", options?) | ||
| const agentId = agentIdOrConfig; | ||
| try { | ||
| agent = getAgent(agentId); | ||
| } | ||
| catch (error) { | ||
| agentLogger.debug("getAgent lookup failed", { error }); | ||
| return dntShim.Response.json({ error: "Agent not found" }, { status: 404 }); | ||
| } | ||
| } | ||
@@ -224,0 +226,0 @@ if (!agent) { |
@@ -87,4 +87,4 @@ /** | ||
| export { agent } from "./factory.js"; | ||
| export { type ChatHandlerBeforeStream, type ChatHandlerBeforeStreamContext, type ChatHandlerBeforeStreamResult, type ChatHandlerMessageInput, type ChatHandlerOptions, createChatHandler, } from "./chat-handler.js"; | ||
| export { type ChatHandlerBeforeStream, type ChatHandlerBeforeStreamContext, type ChatHandlerBeforeStreamResult, type ChatHandlerConfigWithAgent, type ChatHandlerMessageInput, type ChatHandlerOptions, createChatHandler, } from "./chat-handler.js"; | ||
| export { AgentRuntime } from "./runtime/index.js"; | ||
| //# sourceMappingURL=index.d.ts.map |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/src/agent/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+EG;AACH,OAAO,yBAAyB,CAAC;AAGjC,YAAY,EACV,KAAK,EACL,WAAW,EACX,YAAY,EACZ,eAAe,EACf,aAAa,EACb,WAAW,EACX,iBAAiB,EACjB,UAAU,EACV,YAAY,EACZ,OAAO,IAAI,YAAY,EACvB,WAAW,EACX,aAAa,EACb,WAAW,EACX,mBAAmB,EACnB,cAAc,EACd,QAAQ,EACR,YAAY,EACZ,oBAAoB,EACpB,qBAAqB,EACrB,cAAc,GACf,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEnF,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,YAAY,EACZ,iBAAiB,EACjB,KAAK,MAAM,EACX,KAAK,iBAAiB,EACtB,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,WAAW,EACX,KAAK,iBAAiB,EACtB,aAAa,GACd,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,WAAW,EACX,cAAc,EACd,QAAQ,EACR,gBAAgB,EAChB,cAAc,EACd,aAAa,EACb,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,YAAY,GAClB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AACrC,OAAO,EACL,KAAK,uBAAuB,EAC5B,KAAK,8BAA8B,EACnC,KAAK,6BAA6B,EAClC,KAAK,uBAAuB,EAC5B,KAAK,kBAAkB,EACvB,iBAAiB,GAClB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC"} | ||
| {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/src/agent/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+EG;AACH,OAAO,yBAAyB,CAAC;AAGjC,YAAY,EACV,KAAK,EACL,WAAW,EACX,YAAY,EACZ,eAAe,EACf,aAAa,EACb,WAAW,EACX,iBAAiB,EACjB,UAAU,EACV,YAAY,EACZ,OAAO,IAAI,YAAY,EACvB,WAAW,EACX,aAAa,EACb,WAAW,EACX,mBAAmB,EACnB,cAAc,EACd,QAAQ,EACR,YAAY,EACZ,oBAAoB,EACpB,qBAAqB,EACrB,cAAc,GACf,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEnF,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,YAAY,EACZ,iBAAiB,EACjB,KAAK,MAAM,EACX,KAAK,iBAAiB,EACtB,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,WAAW,EACX,KAAK,iBAAiB,EACtB,aAAa,GACd,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,WAAW,EACX,cAAc,EACd,QAAQ,EACR,gBAAgB,EAChB,cAAc,EACd,aAAa,EACb,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,YAAY,GAClB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AACrC,OAAO,EACL,KAAK,uBAAuB,EAC5B,KAAK,8BAA8B,EACnC,KAAK,6BAA6B,EAClC,KAAK,0BAA0B,EAC/B,KAAK,uBAAuB,EAC5B,KAAK,kBAAkB,EACvB,iBAAiB,GAClB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC"} |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"discovery-engine.d.ts","sourceRoot":"","sources":["../../../src/src/discovery/discovery-engine.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,KAAK,EACV,eAAe,EAEf,eAAe,EAEhB,MAAM,YAAY,CAAC;AA6DpB;;GAEG;AACH,wBAAsB,WAAW,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC,CA0EnF"} | ||
| {"version":3,"file":"discovery-engine.d.ts","sourceRoot":"","sources":["../../../src/src/discovery/discovery-engine.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,KAAK,EACV,eAAe,EAEf,eAAe,EAEhB,MAAM,YAAY,CAAC;AAqIpB;;GAEG;AACH,wBAAsB,WAAW,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC,CA0EnF"} |
@@ -14,4 +14,40 @@ /** | ||
| import { agentHandler, discoverSkills, promptHandler, resourceHandler, taskHandler, toolHandler, workflowHandler, } from "./handlers/index.js"; | ||
| import { filenameToId } from "./discovery-utils.js"; | ||
| import { join } from "../platform/compat/path/index.js"; | ||
| const logger = agentLogger.component("discovery"); | ||
| function isIndexModule(file) { | ||
| const normalized = file.replace("file://", ""); | ||
| return /(?:^|\/)index\.(?:ts|tsx|js|jsx)$/.test(normalized); | ||
| } | ||
| function compareDiscoveryFiles(a, b) { | ||
| const aIsIndex = isIndexModule(a); | ||
| const bIsIndex = isIndexModule(b); | ||
| if (aIsIndex !== bIsIndex) | ||
| return aIsIndex ? 1 : -1; | ||
| return a.localeCompare(b); | ||
| } | ||
| function collectDiscoveryCandidates(module, handler) { | ||
| const defaultItem = module.default; | ||
| if (handler.validate(defaultItem)) { | ||
| return [{ exportName: "default", item: defaultItem }]; | ||
| } | ||
| const candidates = []; | ||
| for (const [exportName, value] of Object.entries(module)) { | ||
| if (exportName === "default") | ||
| continue; | ||
| if (!handler.validate(value)) | ||
| continue; | ||
| candidates.push({ exportName, item: value }); | ||
| } | ||
| return candidates; | ||
| } | ||
| function getCandidateId(candidate, file, dir, handler, useExportNameFallback) { | ||
| const derivedId = handler.getId(candidate.item, file, dir); | ||
| if (!useExportNameFallback) | ||
| return derivedId; | ||
| const fileId = filenameToId(file); | ||
| if (derivedId !== fileId) | ||
| return derivedId; | ||
| return candidate.exportName; | ||
| } | ||
| /** | ||
@@ -21,3 +57,4 @@ * Discover items of a specific type in a directory | ||
| async function discoverItems(dir, result, context, handler, verbose) { | ||
| const files = await findTypeScriptFiles(dir, context); | ||
| const files = (await findTypeScriptFiles(dir, context)).sort(compareDiscoveryFiles); | ||
| const resultMap = handler.getResultMap(result); | ||
| if (verbose) { | ||
@@ -29,4 +66,4 @@ logger.info(`Found ${files.length} ${handler.typeName} files in ${dir}`); | ||
| const module = await importModule(file, context); | ||
| const item = module.default; | ||
| if (!handler.validate(item)) { | ||
| const candidates = collectDiscoveryCandidates(module, handler); | ||
| if (candidates.length === 0) { | ||
| if (verbose) { | ||
@@ -37,7 +74,19 @@ logger.warn(`${file} does not export a valid ${handler.typeName}`); | ||
| } | ||
| const id = handler.getId(item, file, dir); | ||
| const registered = handler.register(id, item, file, dir); | ||
| handler.getResultMap(result).set(id, registered); | ||
| if (verbose) { | ||
| logger.info(`Registered ${handler.typeName}: ${id}`); | ||
| const useExportNameFallback = candidates.length > 1 || isIndexModule(file); | ||
| for (const candidate of candidates) { | ||
| const id = getCandidateId(candidate, file, dir, handler, useExportNameFallback); | ||
| if (resultMap.has(id)) { | ||
| if (verbose) { | ||
| logger.warn(`Duplicate ${handler.typeName} "${id}" in ${file}; keeping first`); | ||
| } | ||
| continue; | ||
| } | ||
| const registered = handler.register(id, candidate.item, file, dir); | ||
| resultMap.set(id, registered); | ||
| if (verbose) { | ||
| const exportSuffix = candidate.exportName === "default" | ||
| ? "" | ||
| : ` (export: ${candidate.exportName})`; | ||
| logger.info(`Registered ${handler.typeName}: ${id}${exportSuffix}`); | ||
| } | ||
| } | ||
@@ -44,0 +93,0 @@ } |
+1
-1
| { | ||
| "name": "veryfront", | ||
| "version": "0.1.59", | ||
| "version": "0.1.60", | ||
| "description": "The simplest way to build AI-powered apps", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
+1
-1
| export default { | ||
| "name": "veryfront", | ||
| "version": "0.1.59", | ||
| "version": "0.1.60", | ||
| "license": "Apache-2.0", | ||
@@ -5,0 +5,0 @@ "nodeModulesDir": "auto", |
@@ -248,2 +248,16 @@ import * as dntShim from "../../_dnt.shims.js"; | ||
| /** Options when passing an agent instance directly. */ | ||
| export interface ChatHandlerConfigWithAgent extends ChatHandlerOptions { | ||
| /** The agent instance to use (bypasses registry lookup). */ | ||
| agent: import("./types.js").Agent; | ||
| } | ||
| function mergeChatHandlerConfig( | ||
| config: ChatHandlerConfigWithAgent, | ||
| options?: ChatHandlerOptions, | ||
| ): ChatHandlerConfigWithAgent { | ||
| if (!options) return config; | ||
| return { ...options, ...config }; | ||
| } | ||
| /** | ||
@@ -302,6 +316,14 @@ * Extract the raw Request from either a raw Request or a Pages Router APIContext. | ||
| * | ||
| * Accepts either: | ||
| * - `createChatHandler("agentId", options?)` — looks up agent by ID from the registry | ||
| * - `createChatHandler({ agent, ...options })` — uses the provided agent instance directly | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * import { createChatHandler } from "veryfront/agent"; | ||
| * // By agent ID (requires auto-discovery registration) | ||
| * export const POST = createChatHandler("assistant"); | ||
| * | ||
| * // By agent instance (no registry needed) | ||
| * import { myAgent } from "../../agents/my-agent"; | ||
| * export const POST = createChatHandler({ agent: myAgent, beforeStream: ... }); | ||
| * ``` | ||
@@ -312,12 +334,34 @@ */ | ||
| options?: ChatHandlerOptions, | ||
| ): (requestOrCtx: unknown) => Promise<dntShim.Response>; | ||
| export function createChatHandler( | ||
| config: ChatHandlerConfigWithAgent, | ||
| options?: ChatHandlerOptions, | ||
| ): (requestOrCtx: unknown) => Promise<dntShim.Response>; | ||
| export function createChatHandler( | ||
| agentIdOrConfig: string | ChatHandlerConfigWithAgent, | ||
| options?: ChatHandlerOptions, | ||
| ) { | ||
| return async function POST(requestOrCtx: unknown): Promise<dntShim.Response> { | ||
| const request = extractRequest(requestOrCtx); | ||
| let agent: ReturnType<typeof getAgent> | undefined; | ||
| try { | ||
| agent = getAgent(agentId); | ||
| } catch (error) { | ||
| agentLogger.debug("getAgent lookup failed", { error }); | ||
| return dntShim.Response.json({ error: "Agent not found" }, { status: 404 }); | ||
| if ( | ||
| typeof agentIdOrConfig === "object" && agentIdOrConfig !== null && "agent" in agentIdOrConfig | ||
| ) { | ||
| // Object-based API: createChatHandler({ agent, beforeStream, ... }) | ||
| const config = mergeChatHandlerConfig(agentIdOrConfig, options); | ||
| agent = config.agent; | ||
| options = config; | ||
| } else { | ||
| // String-based API: createChatHandler("agentId", options?) | ||
| const agentId = agentIdOrConfig as string; | ||
| try { | ||
| agent = getAgent(agentId); | ||
| } catch (error) { | ||
| agentLogger.debug("getAgent lookup failed", { error }); | ||
| return dntShim.Response.json({ error: "Agent not found" }, { status: 404 }); | ||
| } | ||
| } | ||
| if (!agent) { | ||
@@ -324,0 +368,0 @@ return dntShim.Response.json({ error: "Agent not found" }, { status: 404 }); |
@@ -140,2 +140,3 @@ /** | ||
| type ChatHandlerBeforeStreamResult, | ||
| type ChatHandlerConfigWithAgent, | ||
| type ChatHandlerMessageInput, | ||
@@ -142,0 +143,0 @@ type ChatHandlerOptions, |
@@ -29,2 +29,3 @@ /** | ||
| } from "./handlers/index.js"; | ||
| import { filenameToId } from "./discovery-utils.js"; | ||
| import { join } from "../platform/compat/path/index.js"; | ||
@@ -34,2 +35,53 @@ | ||
| type DiscoveryCandidate<T> = { | ||
| exportName: string; | ||
| item: T; | ||
| }; | ||
| function isIndexModule(file: string): boolean { | ||
| const normalized = file.replace("file://", ""); | ||
| return /(?:^|\/)index\.(?:ts|tsx|js|jsx)$/.test(normalized); | ||
| } | ||
| function compareDiscoveryFiles(a: string, b: string): number { | ||
| const aIsIndex = isIndexModule(a); | ||
| const bIsIndex = isIndexModule(b); | ||
| if (aIsIndex !== bIsIndex) return aIsIndex ? 1 : -1; | ||
| return a.localeCompare(b); | ||
| } | ||
| function collectDiscoveryCandidates<T>( | ||
| module: unknown, | ||
| handler: DiscoveryHandler<T>, | ||
| ): DiscoveryCandidate<T>[] { | ||
| const defaultItem = (module as { default?: T }).default; | ||
| if (handler.validate(defaultItem)) { | ||
| return [{ exportName: "default", item: defaultItem }]; | ||
| } | ||
| const candidates: DiscoveryCandidate<T>[] = []; | ||
| for (const [exportName, value] of Object.entries(module as Record<string, unknown>)) { | ||
| if (exportName === "default") continue; | ||
| if (!handler.validate(value)) continue; | ||
| candidates.push({ exportName, item: value }); | ||
| } | ||
| return candidates; | ||
| } | ||
| function getCandidateId<T>( | ||
| candidate: DiscoveryCandidate<T>, | ||
| file: string, | ||
| dir: string, | ||
| handler: DiscoveryHandler<T>, | ||
| useExportNameFallback: boolean, | ||
| ): string { | ||
| const derivedId = handler.getId(candidate.item, file, dir); | ||
| if (!useExportNameFallback) return derivedId; | ||
| const fileId = filenameToId(file); | ||
| if (derivedId !== fileId) return derivedId; | ||
| return candidate.exportName; | ||
| } | ||
| /** | ||
@@ -45,3 +97,4 @@ * Discover items of a specific type in a directory | ||
| ): Promise<void> { | ||
| const files = await findTypeScriptFiles(dir, context); | ||
| const files = (await findTypeScriptFiles(dir, context)).sort(compareDiscoveryFiles); | ||
| const resultMap = handler.getResultMap(result); | ||
@@ -55,5 +108,4 @@ if (verbose) { | ||
| const module = await importModule(file, context); | ||
| const item = (module as { default?: T }).default; | ||
| if (!handler.validate(item)) { | ||
| const candidates = collectDiscoveryCandidates(module, handler); | ||
| if (candidates.length === 0) { | ||
| if (verbose) { | ||
@@ -65,8 +117,28 @@ logger.warn(`${file} does not export a valid ${handler.typeName}`); | ||
| const id = handler.getId(item, file, dir); | ||
| const registered = handler.register(id, item, file, dir); | ||
| handler.getResultMap(result).set(id, registered); | ||
| const useExportNameFallback = candidates.length > 1 || isIndexModule(file); | ||
| for (const candidate of candidates) { | ||
| const id = getCandidateId( | ||
| candidate, | ||
| file, | ||
| dir, | ||
| handler, | ||
| useExportNameFallback, | ||
| ); | ||
| if (verbose) { | ||
| logger.info(`Registered ${handler.typeName}: ${id}`); | ||
| if (resultMap.has(id)) { | ||
| if (verbose) { | ||
| logger.warn(`Duplicate ${handler.typeName} "${id}" in ${file}; keeping first`); | ||
| } | ||
| continue; | ||
| } | ||
| const registered = handler.register(id, candidate.item, file, dir); | ||
| resultMap.set(id, registered); | ||
| if (verbose) { | ||
| const exportSuffix = candidate.exportName === "default" | ||
| ? "" | ||
| : ` (export: ${candidate.exportName})`; | ||
| logger.info(`Registered ${handler.typeName}: ${id}${exportSuffix}`); | ||
| } | ||
| } | ||
@@ -73,0 +145,0 @@ } catch (error) { |
Network access
Supply chain riskThis module accesses the network.
Found 2 instances in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 2 instances in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 5 instances in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 2 instances in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 2 instances in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 5 instances in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
16721646
0.04%349329
0.05%