@faapi/faapi 6.26.0 → 6.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +82 -49
- package/dist/cli/index.js.map +1 -1
- package/dist/{contextTypes-gYf84EXF.d.ts → contextTypes-DhagvRH_.d.ts} +9 -25
- package/dist/index.d.ts +35 -28
- package/dist/index.js +124 -96
- package/dist/index.js.map +1 -1
- package/dist/{routeTypes-DlD6nnbT.d.ts → routeTypes-0rwuIws-.d.ts} +1 -1
- package/dist/testing.d.ts +3 -3
- package/dist/testing.js +59 -77
- package/dist/testing.js.map +1 -1
- package/dist/workerEntry.d.ts +1 -1
- package/dist/workerEntry.js +2 -1
- package/dist/workerEntry.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1835,6 +1835,19 @@ function createTaskRegistry() {
|
|
|
1835
1835
|
};
|
|
1836
1836
|
}
|
|
1837
1837
|
|
|
1838
|
+
// src/injection/subAgentToolName.ts
|
|
1839
|
+
var LLM_TOOL_NAME_PATTERN = /^[a-zA-Z0-9_-]+$/;
|
|
1840
|
+
var SUB_AGENT_TOOL_PREFIX = "agent-";
|
|
1841
|
+
function subAgentToolName(agentName) {
|
|
1842
|
+
const toolName = SUB_AGENT_TOOL_PREFIX + agentName;
|
|
1843
|
+
if (!LLM_TOOL_NAME_PATTERN.test(toolName)) {
|
|
1844
|
+
throw new Error(
|
|
1845
|
+
`Sub-agent tool name "${toolName}" (from agent name "${agentName}") violates the LLM tool name pattern ${LLM_TOOL_NAME_PATTERN} \u2014 rename the agent (allowed: a-z A-Z 0-9 '-' '_'; file-based agent directory segments allow a-z A-Z 0-9 '-' only, '_' is the nesting separator)`
|
|
1846
|
+
);
|
|
1847
|
+
}
|
|
1848
|
+
return toolName;
|
|
1849
|
+
}
|
|
1850
|
+
|
|
1838
1851
|
// src/injection/registries.ts
|
|
1839
1852
|
function createToolRegistry() {
|
|
1840
1853
|
let registry = /* @__PURE__ */ new Map();
|
|
@@ -1882,7 +1895,7 @@ function createAgentRegistry(tool) {
|
|
|
1882
1895
|
if (!agent) return void 0;
|
|
1883
1896
|
return {
|
|
1884
1897
|
kind: "agent",
|
|
1885
|
-
name:
|
|
1898
|
+
name: subAgentToolName(agent.name),
|
|
1886
1899
|
agentName: agent.name,
|
|
1887
1900
|
description: agent.description,
|
|
1888
1901
|
metadata: agent
|
|
@@ -2224,7 +2237,6 @@ async function runTaskInWorker(options) {
|
|
|
2224
2237
|
payload,
|
|
2225
2238
|
taskCtx: {
|
|
2226
2239
|
config: safeConfig(taskCtx.config),
|
|
2227
|
-
resourcesDir: taskCtx.resourcesDir,
|
|
2228
2240
|
job: taskCtx.job
|
|
2229
2241
|
},
|
|
2230
2242
|
registries: options.registries,
|
|
@@ -2607,7 +2619,6 @@ function createTaskQueue(deps) {
|
|
|
2607
2619
|
const taskCtx = {
|
|
2608
2620
|
signal: job.signal,
|
|
2609
2621
|
config: deps.config,
|
|
2610
|
-
resourcesDir: deps.resourcesDir,
|
|
2611
2622
|
job: { id: job.id, name: job.name, attempt: job.attempt },
|
|
2612
2623
|
registries: registriesView,
|
|
2613
2624
|
log: createLogger(`task:${job.name}`, {
|
|
@@ -3687,6 +3698,7 @@ function extractJSDocTagValue(jsDoc, tagName) {
|
|
|
3687
3698
|
}
|
|
3688
3699
|
|
|
3689
3700
|
// src/ast/extractToolMetadata.ts
|
|
3701
|
+
init_resolveTypeNode();
|
|
3690
3702
|
function extractToolMetadata(program, filePath, functionName, pathMeta) {
|
|
3691
3703
|
const sourceFile = program.getSourceFile(filePath);
|
|
3692
3704
|
if (!sourceFile) return null;
|
|
@@ -3696,6 +3708,14 @@ function extractToolMetadata(program, filePath, functionName, pathMeta) {
|
|
|
3696
3708
|
const jsDoc = getJSDocFromNode(jsDocOwner);
|
|
3697
3709
|
const description = extractDescription(jsDoc);
|
|
3698
3710
|
const toolNameOverride = extractJSDocTagValue(jsDoc, "tool");
|
|
3711
|
+
if (toolNameOverride !== void 0 && !LLM_TOOL_NAME_PATTERN.test(toolNameOverride)) {
|
|
3712
|
+
throw SchemaExtractionError.at(
|
|
3713
|
+
jsDocOwner,
|
|
3714
|
+
"@tool",
|
|
3715
|
+
`\u8986\u76D6\u540D "${toolNameOverride}" \u542B\u975E\u6CD5\u5B57\u7B26\u2014\u2014\u987B\u6EE1\u8DB3 ${LLM_TOOL_NAME_PATTERN}\uFF08tool \u540D\u76F4\u63A5\u4F5C\u4E3A LLM function.name\uFF0C\u5F3A\u6821\u9A8C\u4E0A\u6E38\u5BF9\u975E\u6CD5\u5B57\u7B26\u6574\u5355 400\uFF09`,
|
|
3716
|
+
sourceFile
|
|
3717
|
+
);
|
|
3718
|
+
}
|
|
3699
3719
|
const inputTypeName = getFirstParamTypeName(fn, sourceFile);
|
|
3700
3720
|
return {
|
|
3701
3721
|
name: toolNameOverride ?? pathMeta.name,
|
|
@@ -4296,7 +4316,7 @@ import {
|
|
|
4296
4316
|
import { createSecureServer as createHttp2SecureServer } from "http2";
|
|
4297
4317
|
import { readFileSync } from "fs";
|
|
4298
4318
|
import { Readable as Readable2 } from "stream";
|
|
4299
|
-
import
|
|
4319
|
+
import path20 from "path";
|
|
4300
4320
|
|
|
4301
4321
|
// src/router/matchRoute.ts
|
|
4302
4322
|
var httpIndexCache = /* @__PURE__ */ new WeakMap();
|
|
@@ -4917,18 +4937,10 @@ function formatSetCookie(name, value, options) {
|
|
|
4917
4937
|
if (options?.sameSite) cookie += `; SameSite=${options.sameSite}`;
|
|
4918
4938
|
return cookie;
|
|
4919
4939
|
}
|
|
4920
|
-
function createContext(request, params, config = {}, ip = "", registries
|
|
4921
|
-
return createContextFromUrl(
|
|
4922
|
-
request,
|
|
4923
|
-
new URL(request.url),
|
|
4924
|
-
params,
|
|
4925
|
-
config,
|
|
4926
|
-
ip,
|
|
4927
|
-
registries,
|
|
4928
|
-
resourcesDir
|
|
4929
|
-
);
|
|
4940
|
+
function createContext(request, params, config = {}, ip = "", registries) {
|
|
4941
|
+
return createContextFromUrl(request, new URL(request.url), params, config, ip, registries);
|
|
4930
4942
|
}
|
|
4931
|
-
function createContextFromUrl(request, url, params, config = {}, ip = "", registries
|
|
4943
|
+
function createContextFromUrl(request, url, params, config = {}, ip = "", registries) {
|
|
4932
4944
|
const meta = { headers: {}, setCookies: [] };
|
|
4933
4945
|
const parsedCookies = parseCookies(request.headers.get("cookie") ?? "");
|
|
4934
4946
|
const cookiesObj = {};
|
|
@@ -4956,9 +4968,6 @@ function createContextFromUrl(request, url, params, config = {}, ip = "", regist
|
|
|
4956
4968
|
ua: request.headers.get("user-agent") ?? "",
|
|
4957
4969
|
cookies: cookiesObj,
|
|
4958
4970
|
config,
|
|
4959
|
-
// 运行时资源根目录(HTTP/WS 链路由 createServer/handleWsUpgrade 传入;
|
|
4960
|
-
// testing 直调未传时为 undefined,见 contextTypes.resourcesDir 注释)
|
|
4961
|
-
resourcesDir,
|
|
4962
4971
|
meta,
|
|
4963
4972
|
setStatus(status) {
|
|
4964
4973
|
meta.status = status;
|
|
@@ -5776,17 +5785,9 @@ function etag(options = {}) {
|
|
|
5776
5785
|
}
|
|
5777
5786
|
|
|
5778
5787
|
// src/server/handleWsUpgrade.ts
|
|
5779
|
-
import
|
|
5788
|
+
import fs16 from "fs";
|
|
5780
5789
|
import { WebSocketServer, WebSocket } from "ws";
|
|
5781
|
-
import path20 from "path";
|
|
5782
|
-
|
|
5783
|
-
// src/cli/copyResources.ts
|
|
5784
5790
|
import path19 from "path";
|
|
5785
|
-
import fs16 from "fs";
|
|
5786
|
-
var RESOURCES_OUTPUT_DIR = "resources";
|
|
5787
|
-
function resolveResourcesDir(rootDir, dist) {
|
|
5788
|
-
return path19.resolve(rootDir, dist, RESOURCES_OUTPUT_DIR);
|
|
5789
|
-
}
|
|
5790
5791
|
|
|
5791
5792
|
// src/server/serverUtils.ts
|
|
5792
5793
|
function nodeHttpToWebHeaders(req) {
|
|
@@ -5926,7 +5927,7 @@ async function loadWsHandler(filePath, ctx, rootDir) {
|
|
|
5926
5927
|
const dist = getDevDist();
|
|
5927
5928
|
if (dist) {
|
|
5928
5929
|
const sourcePath = prodPathToSourcePath(filePath, rootDir, dist);
|
|
5929
|
-
if (sourcePath &&
|
|
5930
|
+
if (sourcePath && fs16.existsSync(sourcePath)) {
|
|
5930
5931
|
await ensureCompiled(sourcePath, rootDir, dist);
|
|
5931
5932
|
}
|
|
5932
5933
|
}
|
|
@@ -6024,7 +6025,6 @@ function attachWebSocket(options) {
|
|
|
6024
6025
|
trustedProxy = false,
|
|
6025
6026
|
registries
|
|
6026
6027
|
} = options;
|
|
6027
|
-
const resourcesDir = resolveResourcesDir(rootDir, dist);
|
|
6028
6028
|
const wss = new WebSocketServer({ noServer: true });
|
|
6029
6029
|
server.on("upgrade", async (req, socket, head) => {
|
|
6030
6030
|
try {
|
|
@@ -6056,19 +6056,12 @@ function attachWebSocket(options) {
|
|
|
6056
6056
|
const host = req.headers.host ?? "localhost";
|
|
6057
6057
|
const fullUrl = new URL(`http://${host}${req.url ?? "/"}`);
|
|
6058
6058
|
const request = new Request(fullUrl.toString(), { method: "GET", headers });
|
|
6059
|
-
const ctx = createContext(
|
|
6060
|
-
request,
|
|
6061
|
-
params,
|
|
6062
|
-
config,
|
|
6063
|
-
getClientIp(req, trustedProxy),
|
|
6064
|
-
registries,
|
|
6065
|
-
resourcesDir
|
|
6066
|
-
);
|
|
6059
|
+
const ctx = createContext(request, params, config, getClientIp(req, trustedProxy), registries);
|
|
6067
6060
|
const meta = ctx.meta;
|
|
6068
6061
|
let upgraded = false;
|
|
6069
6062
|
const finalHandler = async () => {
|
|
6070
6063
|
const schemaPath = getRuntimeSchemaPath(route.filePath, dist, rootDir);
|
|
6071
|
-
if (
|
|
6064
|
+
if (fs16.existsSync(schemaPath)) {
|
|
6072
6065
|
if (isDevOnDemandEnabled()) {
|
|
6073
6066
|
const devDist = getDevDist();
|
|
6074
6067
|
if (devDist) {
|
|
@@ -6107,7 +6100,7 @@ function attachWebSocket(options) {
|
|
|
6107
6100
|
}
|
|
6108
6101
|
let handlers;
|
|
6109
6102
|
try {
|
|
6110
|
-
const absoluteFilePath =
|
|
6103
|
+
const absoluteFilePath = path19.resolve(rootDir, route.filePath);
|
|
6111
6104
|
handlers = await loadWsHandler(absoluteFilePath, ctx, rootDir);
|
|
6112
6105
|
} catch (err) {
|
|
6113
6106
|
const reason = err instanceof Error ? err.message : String(err);
|
|
@@ -6267,7 +6260,6 @@ function createServer(options) {
|
|
|
6267
6260
|
trustedProxy = false
|
|
6268
6261
|
} = options;
|
|
6269
6262
|
const routesRef = { current: routes, wsCurrent: wsRoutes ?? [] };
|
|
6270
|
-
const resourcesDir = resolveResourcesDir(rootDir, dist);
|
|
6271
6263
|
const configMiddlewares = [];
|
|
6272
6264
|
if (compressionOption) {
|
|
6273
6265
|
const compOpts = typeof compressionOption === "object" ? compressionOption : {};
|
|
@@ -6314,8 +6306,7 @@ function createServer(options) {
|
|
|
6314
6306
|
bodyLimit,
|
|
6315
6307
|
trustedProxy,
|
|
6316
6308
|
registries,
|
|
6317
|
-
routesRef.wsCurrent
|
|
6318
|
-
resourcesDir
|
|
6309
|
+
routesRef.wsCurrent
|
|
6319
6310
|
).catch((err) => {
|
|
6320
6311
|
console.error("[faapi] Request pipeline failed after error response attempt:", err);
|
|
6321
6312
|
try {
|
|
@@ -6341,7 +6332,7 @@ function createServer(options) {
|
|
|
6341
6332
|
});
|
|
6342
6333
|
return { server, routesRef };
|
|
6343
6334
|
}
|
|
6344
|
-
function prepareRequest(req, request, url, config, trustedProxy, registries, preMatched
|
|
6335
|
+
function prepareRequest(req, request, url, config, trustedProxy, registries, preMatched) {
|
|
6345
6336
|
const method = request.method.toUpperCase();
|
|
6346
6337
|
const urlPath = url.pathname;
|
|
6347
6338
|
const ctx = createContextFromUrl(
|
|
@@ -6350,8 +6341,7 @@ function prepareRequest(req, request, url, config, trustedProxy, registries, pre
|
|
|
6350
6341
|
preMatched?.params ?? {},
|
|
6351
6342
|
config,
|
|
6352
6343
|
getClientIp(req, trustedProxy),
|
|
6353
|
-
registries
|
|
6354
|
-
resourcesDir
|
|
6344
|
+
registries
|
|
6355
6345
|
);
|
|
6356
6346
|
const meta = ctx.meta;
|
|
6357
6347
|
return { request, url, ctx, meta, method, urlPath };
|
|
@@ -6370,7 +6360,7 @@ function getRoutePaths(route, rootDir, dist) {
|
|
|
6370
6360
|
let cached = routePathCache.get(route);
|
|
6371
6361
|
if (!cached) {
|
|
6372
6362
|
cached = {
|
|
6373
|
-
absFilePath:
|
|
6363
|
+
absFilePath: path20.resolve(rootDir, route.filePath),
|
|
6374
6364
|
schemaPath: getRuntimeSchemaPath(route.filePath, dist, rootDir)
|
|
6375
6365
|
};
|
|
6376
6366
|
routePathCache.set(route, cached);
|
|
@@ -6493,7 +6483,7 @@ async function sendErrorResponse(err, meta, res, onError, ctx) {
|
|
|
6493
6483
|
}
|
|
6494
6484
|
}
|
|
6495
6485
|
}
|
|
6496
|
-
async function handleRequest(routes, rootDir, dist, req, res, outerMiddlewares, onError, config, globalInjectors, bodyLimit, trustedProxy, registries, wsRoutes
|
|
6486
|
+
async function handleRequest(routes, rootDir, dist, req, res, outerMiddlewares, onError, config, globalInjectors, bodyLimit, trustedProxy, registries, wsRoutes) {
|
|
6497
6487
|
let meta = { headers: {}, setCookies: [] };
|
|
6498
6488
|
let ctx;
|
|
6499
6489
|
let sseEarlySent = false;
|
|
@@ -6513,8 +6503,7 @@ async function handleRequest(routes, rootDir, dist, req, res, outerMiddlewares,
|
|
|
6513
6503
|
config,
|
|
6514
6504
|
trustedProxy,
|
|
6515
6505
|
registries,
|
|
6516
|
-
preMatched
|
|
6517
|
-
resourcesDir
|
|
6506
|
+
preMatched
|
|
6518
6507
|
);
|
|
6519
6508
|
ctx = prepared.ctx;
|
|
6520
6509
|
meta = prepared.meta;
|
|
@@ -6590,8 +6579,8 @@ function applyPluginWrappers(server, handlerWrappers, upgradeWrappers) {
|
|
|
6590
6579
|
}
|
|
6591
6580
|
|
|
6592
6581
|
// src/cli/generateRoutes.ts
|
|
6593
|
-
import
|
|
6594
|
-
import
|
|
6582
|
+
import fs17 from "fs";
|
|
6583
|
+
import path21 from "path";
|
|
6595
6584
|
async function hydrateRoutes(manifest) {
|
|
6596
6585
|
const hydrateRoute = (serialized) => ({
|
|
6597
6586
|
method: serialized.method,
|
|
@@ -6635,18 +6624,18 @@ function createIdleTaskDriver() {
|
|
|
6635
6624
|
}
|
|
6636
6625
|
|
|
6637
6626
|
// src/cli/loadPlugins.ts
|
|
6638
|
-
import
|
|
6639
|
-
import
|
|
6627
|
+
import path23 from "path";
|
|
6628
|
+
import fs19 from "fs";
|
|
6640
6629
|
import { pathToFileURL as pathToFileURL3 } from "url";
|
|
6641
6630
|
|
|
6642
6631
|
// src/cli/compileConfig.ts
|
|
6643
|
-
import
|
|
6644
|
-
import
|
|
6632
|
+
import path22 from "path";
|
|
6633
|
+
import fs18 from "fs";
|
|
6645
6634
|
async function compileProjectModules(entryPoints, rootDir, dist) {
|
|
6646
6635
|
const { insideFiles, outsideFiles } = await collectRelativeImports(entryPoints, rootDir);
|
|
6647
6636
|
const esbuild = await import("esbuild");
|
|
6648
6637
|
const aliasPlugins = buildAliasPlugins(rootDir);
|
|
6649
|
-
const absDist =
|
|
6638
|
+
const absDist = path22.resolve(rootDir, dist);
|
|
6650
6639
|
await esbuild.build({
|
|
6651
6640
|
entryPoints: [...entryPoints, ...outsideFiles],
|
|
6652
6641
|
outdir: absDist,
|
|
@@ -6660,7 +6649,7 @@ async function compileProjectModules(entryPoints, rootDir, dist) {
|
|
|
6660
6649
|
logLevel: "silent"
|
|
6661
6650
|
});
|
|
6662
6651
|
if (insideFiles.length > 0) {
|
|
6663
|
-
const appOutbase =
|
|
6652
|
+
const appOutbase = path22.resolve(rootDir, "src");
|
|
6664
6653
|
await esbuild.build({
|
|
6665
6654
|
entryPoints: insideFiles,
|
|
6666
6655
|
outdir: absDist,
|
|
@@ -6741,30 +6730,30 @@ async function loadPlugins(declarations, ctx, rootDir, dist) {
|
|
|
6741
6730
|
var TS_EXTS = /\.(ts|tsx|mts|cts)$/;
|
|
6742
6731
|
var JS_EXTS = /\.(js|mjs|cjs|jsx)$/;
|
|
6743
6732
|
function resolveLocalPluginSource(specifier, baseDir) {
|
|
6744
|
-
const base =
|
|
6745
|
-
if ((TS_EXTS.test(base) || JS_EXTS.test(base)) &&
|
|
6733
|
+
const base = path23.isAbsolute(specifier) ? specifier : path23.resolve(baseDir, specifier);
|
|
6734
|
+
if ((TS_EXTS.test(base) || JS_EXTS.test(base)) && fs19.existsSync(base)) return base;
|
|
6746
6735
|
for (const ext of [".ts", ".js"]) {
|
|
6747
|
-
if (
|
|
6736
|
+
if (fs19.existsSync(base + ext)) return base + ext;
|
|
6748
6737
|
}
|
|
6749
6738
|
for (const indexExt of ["/index.ts", "/index.js"]) {
|
|
6750
|
-
if (
|
|
6739
|
+
if (fs19.existsSync(base + indexExt)) return base + indexExt;
|
|
6751
6740
|
}
|
|
6752
6741
|
return null;
|
|
6753
6742
|
}
|
|
6754
6743
|
function mirrorProductPath(sourcePath, baseDir, distDir) {
|
|
6755
|
-
let rel =
|
|
6744
|
+
let rel = path23.relative(baseDir, sourcePath).replace(/\\/g, "/");
|
|
6756
6745
|
if (rel.startsWith("src/")) rel = rel.slice(4);
|
|
6757
|
-
return
|
|
6746
|
+
return path23.resolve(distDir, rel.replace(TS_EXTS, ".js"));
|
|
6758
6747
|
}
|
|
6759
6748
|
async function importPluginModule(specifier, baseDir, dist) {
|
|
6760
6749
|
const isRelative = specifier.startsWith("./") || specifier.startsWith("../");
|
|
6761
|
-
if (!isRelative && !
|
|
6750
|
+
if (!isRelative && !path23.isAbsolute(specifier)) {
|
|
6762
6751
|
return import(specifier);
|
|
6763
6752
|
}
|
|
6764
|
-
const distDir = dist ?
|
|
6753
|
+
const distDir = dist ? path23.resolve(baseDir, dist) : null;
|
|
6765
6754
|
const sourcePath = resolveLocalPluginSource(specifier, baseDir);
|
|
6766
6755
|
const productPath = sourcePath && distDir ? mirrorProductPath(sourcePath, baseDir, distDir) : null;
|
|
6767
|
-
if (productPath !== null &&
|
|
6756
|
+
if (productPath !== null && fs19.existsSync(productPath) && (sourcePath === null || isProductFresh(sourcePath, productPath))) {
|
|
6768
6757
|
return import(pathToFileURL3(productPath).href);
|
|
6769
6758
|
}
|
|
6770
6759
|
if (sourcePath && TS_EXTS.test(sourcePath)) {
|
|
@@ -6773,13 +6762,13 @@ async function importPluginModule(specifier, baseDir, dist) {
|
|
|
6773
6762
|
`Local plugin "${specifier}" has no up-to-date build artifact (dist is stale or missing). Run "faapi build" first, or use "faapi dev" for on-demand compilation.`
|
|
6774
6763
|
);
|
|
6775
6764
|
}
|
|
6776
|
-
const relFromRoot =
|
|
6765
|
+
const relFromRoot = path23.relative(baseDir, sourcePath).replace(/\\/g, "/");
|
|
6777
6766
|
if (relFromRoot.startsWith("src/")) {
|
|
6778
6767
|
await ensureCompiled(sourcePath, baseDir, dist);
|
|
6779
6768
|
} else {
|
|
6780
6769
|
await compileProjectModules([sourcePath], baseDir, dist);
|
|
6781
6770
|
}
|
|
6782
|
-
if (productPath &&
|
|
6771
|
+
if (productPath && fs19.existsSync(productPath)) {
|
|
6783
6772
|
return import(pathToFileURL3(productPath).href);
|
|
6784
6773
|
}
|
|
6785
6774
|
}
|
|
@@ -6791,7 +6780,7 @@ async function importPluginModule(specifier, baseDir, dist) {
|
|
|
6791
6780
|
`${specifier}/index.ts`,
|
|
6792
6781
|
`${specifier}.js`,
|
|
6793
6782
|
`${specifier}/index.js`
|
|
6794
|
-
].map((c) =>
|
|
6783
|
+
].map((c) => path23.isAbsolute(c) ? c : path23.join(baseDir, c));
|
|
6795
6784
|
throw new Error(
|
|
6796
6785
|
`Cannot find local plugin "${specifier}" (resolved from ${baseDir}). Expected one of:
|
|
6797
6786
|
${candidates.join("\n ")}
|
|
@@ -6816,11 +6805,11 @@ function resolveDeclaration(decl) {
|
|
|
6816
6805
|
}
|
|
6817
6806
|
|
|
6818
6807
|
// src/cli/manifestLoader.ts
|
|
6819
|
-
import
|
|
6820
|
-
import
|
|
6808
|
+
import fs20 from "fs";
|
|
6809
|
+
import path26 from "path";
|
|
6821
6810
|
|
|
6822
6811
|
// src/cli/generateAgentArtifacts.ts
|
|
6823
|
-
import
|
|
6812
|
+
import path24 from "path";
|
|
6824
6813
|
|
|
6825
6814
|
// src/ast/extractAgentMetadata.ts
|
|
6826
6815
|
import ts11 from "typescript";
|
|
@@ -6858,6 +6847,14 @@ function extractAgentMetadata(program, filePath, pathMeta) {
|
|
|
6858
6847
|
const jsDoc = getJSDocFromNode(configFound.jsDocOwner);
|
|
6859
6848
|
const description = extractDescription(jsDoc);
|
|
6860
6849
|
const agentNameOverride = extractJSDocTagValue(jsDoc, "agent");
|
|
6850
|
+
if (agentNameOverride !== void 0 && !LLM_TOOL_NAME_PATTERN.test(agentNameOverride)) {
|
|
6851
|
+
throw SchemaExtractionError.at(
|
|
6852
|
+
configFound.jsDocOwner,
|
|
6853
|
+
"@agent",
|
|
6854
|
+
`\u8986\u76D6\u540D "${agentNameOverride}" \u542B\u975E\u6CD5\u5B57\u7B26\u2014\u2014\u987B\u6EE1\u8DB3 ${LLM_TOOL_NAME_PATTERN}\uFF08\u8986\u76D6\u540D\u6210\u4E3A LLM \u5DE5\u5177\u540D "agent-<\u8986\u76D6\u540D>"\uFF0C\u5F3A\u6821\u9A8C\u4E0A\u6E38\u5BF9\u975E\u6CD5\u5B57\u7B26\u6574\u5355 400\uFF09`,
|
|
6855
|
+
sourceFile
|
|
6856
|
+
);
|
|
6857
|
+
}
|
|
6861
6858
|
const { systemPrompt, systemPromptFile, tools, agents, model, maxTurns, inputDescription } = extractConfigFields(objectLiteral, sourceFile);
|
|
6862
6859
|
return {
|
|
6863
6860
|
name: agentNameOverride ?? pathMeta.name,
|
|
@@ -7137,9 +7134,9 @@ function validateAgentList(metadata) {
|
|
|
7137
7134
|
}
|
|
7138
7135
|
async function generateAgentArtifacts(agents, rootDir, dist) {
|
|
7139
7136
|
const metadata = [];
|
|
7140
|
-
const programByFile = createPrograms(agents.map((m) =>
|
|
7137
|
+
const programByFile = createPrograms(agents.map((m) => path24.resolve(rootDir, m.filePath)));
|
|
7141
7138
|
for (const manifest of agents) {
|
|
7142
|
-
const absPath =
|
|
7139
|
+
const absPath = path24.resolve(rootDir, manifest.filePath);
|
|
7143
7140
|
const program = programByFile.get(absPath);
|
|
7144
7141
|
const result = extractAgentMetadata(program, absPath, {
|
|
7145
7142
|
name: manifest.name,
|
|
@@ -7154,14 +7151,14 @@ async function generateAgentArtifacts(agents, rootDir, dist) {
|
|
|
7154
7151
|
}
|
|
7155
7152
|
validateAgentList(metadata);
|
|
7156
7153
|
const serialized = serializeAgents(metadata, dist);
|
|
7157
|
-
const agentsPath =
|
|
7154
|
+
const agentsPath = path24.resolve(rootDir, dist, AGENTS_FILE);
|
|
7158
7155
|
await writeAgentsModule(serialized, agentsPath);
|
|
7159
7156
|
return metadata;
|
|
7160
7157
|
}
|
|
7161
7158
|
|
|
7162
7159
|
// src/cli/generateTaskArtifacts.ts
|
|
7163
7160
|
init_generateZodArtifacts();
|
|
7164
|
-
import
|
|
7161
|
+
import path25 from "path";
|
|
7165
7162
|
init_createProgram();
|
|
7166
7163
|
init_atomicWrite();
|
|
7167
7164
|
init_extractHandlerTypes();
|
|
@@ -7199,7 +7196,7 @@ function collectTaskSchemaSources(tasks, rootDir) {
|
|
|
7199
7196
|
const tasksByFile = /* @__PURE__ */ new Map();
|
|
7200
7197
|
for (const task of tasks) {
|
|
7201
7198
|
if (!task.inputTypeName) continue;
|
|
7202
|
-
const absPath =
|
|
7199
|
+
const absPath = path25.resolve(rootDir, task.filePath);
|
|
7203
7200
|
let list = tasksByFile.get(absPath);
|
|
7204
7201
|
if (!list) {
|
|
7205
7202
|
list = [];
|
|
@@ -7256,9 +7253,9 @@ function generateTaskSchemaFileSource(sources, resolveType, helpersImportPath) {
|
|
|
7256
7253
|
async function generateTaskArtifacts(manifests, rootDir, dist) {
|
|
7257
7254
|
const metadata = [];
|
|
7258
7255
|
if (manifests.length > 0) {
|
|
7259
|
-
const programByFile = createPrograms(manifests.map((m) =>
|
|
7256
|
+
const programByFile = createPrograms(manifests.map((m) => path25.resolve(rootDir, m.filePath)));
|
|
7260
7257
|
for (const manifest of manifests) {
|
|
7261
|
-
const absPath =
|
|
7258
|
+
const absPath = path25.resolve(rootDir, manifest.filePath);
|
|
7262
7259
|
const result = extractToolMetadata(programByFile.get(absPath), absPath, "run", {
|
|
7263
7260
|
name: manifest.name,
|
|
7264
7261
|
filePath: manifest.filePath
|
|
@@ -7269,7 +7266,7 @@ async function generateTaskArtifacts(manifests, rootDir, dist) {
|
|
|
7269
7266
|
}
|
|
7270
7267
|
}
|
|
7271
7268
|
const serialized = serializeTasks(manifests, dist);
|
|
7272
|
-
const tasksPath =
|
|
7269
|
+
const tasksPath = path25.resolve(rootDir, dist, TASKS_FILE);
|
|
7273
7270
|
await writeTasksModule(serialized, tasksPath);
|
|
7274
7271
|
if (metadata.length === 0) {
|
|
7275
7272
|
return hydrateTasks(serialized);
|
|
@@ -7291,8 +7288,8 @@ async function generateTaskArtifacts(manifests, rootDir, dist) {
|
|
|
7291
7288
|
var TOOLS_FILE2 = "faapi-tools.js";
|
|
7292
7289
|
var AGENTS_FILE2 = "faapi-agents.js";
|
|
7293
7290
|
async function loadAndHydrateTools(rootDir, dist, registries = defaultRegistries) {
|
|
7294
|
-
const toolsPath =
|
|
7295
|
-
if (!
|
|
7291
|
+
const toolsPath = path26.resolve(rootDir, dist, TOOLS_FILE2);
|
|
7292
|
+
if (!fs20.existsSync(toolsPath)) {
|
|
7296
7293
|
return [];
|
|
7297
7294
|
}
|
|
7298
7295
|
const serialized = await importWithCacheBust(toolsPath);
|
|
@@ -7301,8 +7298,8 @@ async function loadAndHydrateTools(rootDir, dist, registries = defaultRegistries
|
|
|
7301
7298
|
return hydrated;
|
|
7302
7299
|
}
|
|
7303
7300
|
async function loadAndHydrateAgents(rootDir, dist, registries = defaultRegistries) {
|
|
7304
|
-
const agentsPath =
|
|
7305
|
-
if (!
|
|
7301
|
+
const agentsPath = path26.resolve(rootDir, dist, AGENTS_FILE2);
|
|
7302
|
+
if (!fs20.existsSync(agentsPath)) {
|
|
7306
7303
|
return [];
|
|
7307
7304
|
}
|
|
7308
7305
|
const serialized = await importWithCacheBust(agentsPath);
|
|
@@ -7317,8 +7314,8 @@ function getTaskDriverOptions(config) {
|
|
|
7317
7314
|
return void 0;
|
|
7318
7315
|
}
|
|
7319
7316
|
async function loadAndHydrateTasks(rootDir, dist, registries = defaultRegistries) {
|
|
7320
|
-
const tasksPath =
|
|
7321
|
-
if (!
|
|
7317
|
+
const tasksPath = path26.resolve(rootDir, dist, TASKS_FILE);
|
|
7318
|
+
if (!fs20.existsSync(tasksPath)) {
|
|
7322
7319
|
return [];
|
|
7323
7320
|
}
|
|
7324
7321
|
const serialized = await importWithCacheBust(tasksPath);
|
|
@@ -7449,6 +7446,14 @@ function performInject(server, injectOpts) {
|
|
|
7449
7446
|
});
|
|
7450
7447
|
}
|
|
7451
7448
|
|
|
7449
|
+
// src/cli/copyResources.ts
|
|
7450
|
+
import path27 from "path";
|
|
7451
|
+
import fs21 from "fs";
|
|
7452
|
+
var RESOURCES_OUTPUT_DIR = "resources";
|
|
7453
|
+
function resolveResourcesDir(rootDir, dist) {
|
|
7454
|
+
return path27.resolve(rootDir, dist, RESOURCES_OUTPUT_DIR);
|
|
7455
|
+
}
|
|
7456
|
+
|
|
7452
7457
|
// src/cli/createAppCore.ts
|
|
7453
7458
|
var DEFAULT_DIST = "dist";
|
|
7454
7459
|
var DEFAULT_PORT = 3e3;
|
|
@@ -7580,7 +7585,6 @@ async function createAppBase(options) {
|
|
|
7580
7585
|
config?.plugins,
|
|
7581
7586
|
{
|
|
7582
7587
|
rootDir,
|
|
7583
|
-
resourcesDir,
|
|
7584
7588
|
registries,
|
|
7585
7589
|
routes: sorted,
|
|
7586
7590
|
getRoutes: () => sorted,
|
|
@@ -7611,8 +7615,7 @@ async function createAppBase(options) {
|
|
|
7611
7615
|
routes: sorted,
|
|
7612
7616
|
server,
|
|
7613
7617
|
registries,
|
|
7614
|
-
tasks: taskQueue
|
|
7615
|
-
resourcesDir
|
|
7618
|
+
tasks: taskQueue
|
|
7616
7619
|
});
|
|
7617
7620
|
console.log("- onBoot hook executed");
|
|
7618
7621
|
} catch (err) {
|
|
@@ -7647,8 +7650,7 @@ async function createAppBase(options) {
|
|
|
7647
7650
|
routes: sorted,
|
|
7648
7651
|
server,
|
|
7649
7652
|
registries,
|
|
7650
|
-
tasks: taskQueue
|
|
7651
|
-
resourcesDir
|
|
7653
|
+
tasks: taskQueue
|
|
7652
7654
|
});
|
|
7653
7655
|
console.log("- onReady hook executed");
|
|
7654
7656
|
}
|
|
@@ -7672,8 +7674,7 @@ async function createAppBase(options) {
|
|
|
7672
7674
|
routes: sorted,
|
|
7673
7675
|
server,
|
|
7674
7676
|
registries,
|
|
7675
|
-
tasks: taskQueue
|
|
7676
|
-
resourcesDir
|
|
7677
|
+
tasks: taskQueue
|
|
7677
7678
|
});
|
|
7678
7679
|
}
|
|
7679
7680
|
registries.tool.clear();
|
|
@@ -7926,11 +7927,20 @@ function extractToolExportsFromSource(source) {
|
|
|
7926
7927
|
}
|
|
7927
7928
|
return names;
|
|
7928
7929
|
}
|
|
7930
|
+
var TOOL_DIR_SEGMENT_PATTERN = /^[a-zA-Z0-9-]+$/;
|
|
7929
7931
|
function extractNamespaceFromRelPath(relPath) {
|
|
7930
7932
|
const lastSlash = relPath.lastIndexOf("/");
|
|
7931
7933
|
const dirPath = lastSlash === -1 ? "" : relPath.slice(0, lastSlash);
|
|
7932
7934
|
if (!dirPath) return "";
|
|
7933
|
-
|
|
7935
|
+
const segments = dirPath.split("/");
|
|
7936
|
+
for (const segment of segments) {
|
|
7937
|
+
if (!TOOL_DIR_SEGMENT_PATTERN.test(segment)) {
|
|
7938
|
+
throw new Error(
|
|
7939
|
+
`Invalid tool directory segment "${segment}" in "tools/${relPath}": tool directory names allow a-z A-Z 0-9 '-' only ('_' is reserved as the nesting separator, '.' is not allowed \u2014 tool names are sent to LLMs as function.name) \u2014 rename the directory`
|
|
7940
|
+
);
|
|
7941
|
+
}
|
|
7942
|
+
}
|
|
7943
|
+
return segments.join("_");
|
|
7934
7944
|
}
|
|
7935
7945
|
function filePathToToolNamespace(filePath) {
|
|
7936
7946
|
const normalized = filePath.replace(/\\/g, "/");
|
|
@@ -7941,7 +7951,13 @@ function filePathToToolNamespace(filePath) {
|
|
|
7941
7951
|
return "";
|
|
7942
7952
|
}
|
|
7943
7953
|
function buildToolName(namespace, functionName) {
|
|
7944
|
-
|
|
7954
|
+
const name = namespace ? `${namespace}_${functionName}` : functionName;
|
|
7955
|
+
if (!LLM_TOOL_NAME_PATTERN.test(name)) {
|
|
7956
|
+
throw new Error(
|
|
7957
|
+
`Tool name "${name}" (function "${functionName}"${namespace ? ` in namespace "${namespace}"` : ""}) violates the LLM tool name pattern ${LLM_TOOL_NAME_PATTERN} \u2014 rename the function or use a @tool JSDoc override (allowed: a-z A-Z 0-9 '-' '_')`
|
|
7958
|
+
);
|
|
7959
|
+
}
|
|
7960
|
+
return name;
|
|
7945
7961
|
}
|
|
7946
7962
|
async function scanTools(rootDir, patterns) {
|
|
7947
7963
|
const files = await fg4(patterns, {
|
|
@@ -7983,6 +7999,7 @@ async function scanTools(rootDir, patterns) {
|
|
|
7983
7999
|
// src/agents/scanAgents.ts
|
|
7984
8000
|
import fg5 from "fast-glob";
|
|
7985
8001
|
var DEFAULT_AGENT_PATTERNS = ["src/agents/**/handler.ts"];
|
|
8002
|
+
var AGENT_DIR_SEGMENT_PATTERN = /^[a-zA-Z0-9-]+$/;
|
|
7986
8003
|
function extractAgentNameFromPath(filePath) {
|
|
7987
8004
|
const normalized = filePath.replace(/\\/g, "/");
|
|
7988
8005
|
const match = normalized.match(/(?:^|\/)agents\/(.+)\/handler\.ts$/);
|
|
@@ -7991,7 +8008,15 @@ function extractAgentNameFromPath(filePath) {
|
|
|
7991
8008
|
`Not an agent path: "${filePath}". Expected pattern: src/agents/<name>/handler.ts`
|
|
7992
8009
|
);
|
|
7993
8010
|
}
|
|
7994
|
-
|
|
8011
|
+
const segments = match[1].split("/");
|
|
8012
|
+
for (const segment of segments) {
|
|
8013
|
+
if (!AGENT_DIR_SEGMENT_PATTERN.test(segment)) {
|
|
8014
|
+
throw new Error(
|
|
8015
|
+
`Invalid agent directory segment "${segment}" in "${filePath}": agent directory names allow a-z A-Z 0-9 '-' only ('_' is reserved as the nesting separator, '.' is not allowed \u2014 agent names become LLM tool names "agent-<name>") \u2014 rename the directory`
|
|
8016
|
+
);
|
|
8017
|
+
}
|
|
8018
|
+
}
|
|
8019
|
+
return segments.join("_");
|
|
7995
8020
|
}
|
|
7996
8021
|
async function scanAgents(rootDir, patterns) {
|
|
7997
8022
|
const files = await fg5(patterns, {
|
|
@@ -8107,9 +8132,11 @@ async function createProdApp(options) {
|
|
|
8107
8132
|
export {
|
|
8108
8133
|
FaapiError,
|
|
8109
8134
|
InternalError,
|
|
8135
|
+
LLM_TOOL_NAME_PATTERN,
|
|
8110
8136
|
MethodNotAllowedError,
|
|
8111
8137
|
ModuleLoadError,
|
|
8112
8138
|
RouteNotFoundError,
|
|
8139
|
+
SUB_AGENT_TOOL_PREFIX,
|
|
8113
8140
|
SchemaExtractionError,
|
|
8114
8141
|
TASK_PATTERNS,
|
|
8115
8142
|
ValidationError,
|
|
@@ -8154,6 +8181,7 @@ export {
|
|
|
8154
8181
|
resolveSubAgents,
|
|
8155
8182
|
resolveTypeNode,
|
|
8156
8183
|
scanTasks,
|
|
8184
|
+
subAgentToolName,
|
|
8157
8185
|
upsertSkill
|
|
8158
8186
|
};
|
|
8159
8187
|
//# sourceMappingURL=index.js.map
|