veryfront 0.1.56 → 0.1.57
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/esm/deno.js +1 -1
- package/esm/src/agent/chat-handler.d.ts.map +1 -1
- package/esm/src/agent/chat-handler.js +9 -1
- package/esm/src/agent/memory/redis.d.ts +3 -0
- package/esm/src/agent/memory/redis.d.ts.map +1 -1
- package/esm/src/agent/memory/redis.js +3 -1
- package/esm/src/agent/runtime/index.d.ts.map +1 -1
- package/esm/src/agent/runtime/index.js +2 -1
- package/esm/src/middleware/builtin/security/rate-limit.d.ts +2 -0
- package/esm/src/middleware/builtin/security/rate-limit.d.ts.map +1 -1
- package/esm/src/middleware/builtin/security/rate-limit.js +18 -2
- package/esm/src/oauth/token-store/memory.d.ts +3 -0
- package/esm/src/oauth/token-store/memory.d.ts.map +1 -1
- package/esm/src/oauth/token-store/memory.js +11 -4
- package/esm/src/proxy/main.js +3 -0
- package/esm/src/routing/api/module-loader/security-config.d.ts.map +1 -1
- package/esm/src/routing/api/module-loader/security-config.js +4 -0
- package/esm/src/security/http/config.d.ts.map +1 -1
- package/esm/src/security/http/config.js +6 -1
- package/esm/src/server/handlers/dev/dashboard/api.d.ts.map +1 -1
- package/esm/src/server/handlers/dev/dashboard/api.js +2 -0
- package/esm/src/server/handlers/request/openapi.handler.js +1 -1
- package/esm/src/server/services/static/static-file.service.d.ts +1 -0
- package/esm/src/server/services/static/static-file.service.d.ts.map +1 -1
- package/esm/src/server/services/static/static-file.service.js +11 -0
- package/esm/src/tool/factory.d.ts.map +1 -1
- package/esm/src/tool/factory.js +10 -0
- package/esm/src/transforms/pipeline/stages/ssr-vf-modules/transform.d.ts.map +1 -1
- package/esm/src/transforms/pipeline/stages/ssr-vf-modules/transform.js +15 -0
- package/esm/src/workflow/claude-code/tool.d.ts +0 -8
- package/esm/src/workflow/claude-code/tool.d.ts.map +1 -1
- package/esm/src/workflow/claude-code/tool.js +8 -10
- package/package.json +1 -1
- package/src/deno.js +1 -1
- package/src/src/agent/chat-handler.ts +11 -1
- package/src/src/agent/memory/redis.ts +5 -1
- package/src/src/agent/runtime/index.ts +2 -1
- package/src/src/middleware/builtin/security/rate-limit.ts +18 -2
- package/src/src/oauth/token-store/memory.ts +13 -4
- package/src/src/proxy/main.ts +3 -0
- package/src/src/routing/api/module-loader/security-config.ts +6 -0
- package/src/src/security/http/config.ts +9 -1
- package/src/src/server/handlers/dev/dashboard/api.ts +2 -0
- package/src/src/server/handlers/request/openapi.handler.ts +1 -1
- package/src/src/server/services/static/static-file.service.ts +11 -0
- package/src/src/tool/factory.ts +10 -0
- package/src/src/transforms/pipeline/stages/ssr-vf-modules/transform.ts +22 -0
- package/src/src/workflow/claude-code/tool.ts +8 -11
package/esm/deno.js
CHANGED
|
@@ -1 +1 @@
|
|
|
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;
|
|
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"}
|
|
@@ -172,6 +172,14 @@ function isRequest(obj) {
|
|
|
172
172
|
"method" in obj &&
|
|
173
173
|
typeof obj.method === "string");
|
|
174
174
|
}
|
|
175
|
+
function extractUserId(request) {
|
|
176
|
+
const userId = request.headers.get("x-user-id");
|
|
177
|
+
if (userId)
|
|
178
|
+
return userId;
|
|
179
|
+
agentLogger.warn("No user identity found in request. Using anonymous fallback. " +
|
|
180
|
+
"Set x-user-id header or provide a context function for proper user isolation.");
|
|
181
|
+
return "anonymous";
|
|
182
|
+
}
|
|
175
183
|
function extractRequest(requestOrCtx) {
|
|
176
184
|
if (isRequest(requestOrCtx))
|
|
177
185
|
return requestOrCtx;
|
|
@@ -219,7 +227,7 @@ export function createChatHandler(agentId, options) {
|
|
|
219
227
|
const { messages: rawMessages, model: requestModel } = chatRequestSchema.parse(body);
|
|
220
228
|
const context = typeof options?.context === "function"
|
|
221
229
|
? await options.context(request)
|
|
222
|
-
: options?.context ?? { userId:
|
|
230
|
+
: options?.context ?? { userId: extractUserId(request) };
|
|
223
231
|
const baseMessages = transformUIMessages(rawMessages);
|
|
224
232
|
const beforeStreamResult = await options?.beforeStream?.({
|
|
225
233
|
request,
|
|
@@ -25,12 +25,15 @@ export interface RedisMemoryConfig extends MemoryConfigBase {
|
|
|
25
25
|
client: RedisClient;
|
|
26
26
|
/** Key prefix for namespacing */
|
|
27
27
|
keyPrefix?: string;
|
|
28
|
+
/** User ID for per-user memory isolation */
|
|
29
|
+
userId?: string;
|
|
28
30
|
/** TTL in seconds (default: 24 hours) */
|
|
29
31
|
ttl?: number;
|
|
30
32
|
}
|
|
31
33
|
export declare class RedisMemory<M extends MinimalMessage = MinimalMessage> implements Memory<M> {
|
|
32
34
|
private client;
|
|
33
35
|
private agentId;
|
|
36
|
+
private userId;
|
|
34
37
|
private keyPrefix;
|
|
35
38
|
private ttl;
|
|
36
39
|
private config;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"redis.d.ts","sourceRoot":"","sources":["../../../../src/src/agent/memory/redis.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAEL,KAAK,MAAM,EACX,KAAK,gBAAgB,EACrB,KAAK,WAAW,EAChB,KAAK,cAAc,EACpB,MAAM,uBAAuB,CAAC;AAG/B;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACzC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,EAAE,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7E,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAClC,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACvD;AAED;;GAEG;AACH,MAAM,WAAW,iBAAkB,SAAQ,gBAAgB;IACzD,IAAI,EAAE,OAAO,CAAC;IACd,4BAA4B;IAC5B,MAAM,EAAE,WAAW,CAAC;IACpB,iCAAiC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yCAAyC;IACzC,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAKD,qBAAa,WAAW,CAAC,CAAC,SAAS,cAAc,GAAG,cAAc,CAAE,YAAW,MAAM,CAAC,CAAC,CAAC;IACtF,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,MAAM,CAAoB;gBAEtB,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,iBAAiB;
|
|
1
|
+
{"version":3,"file":"redis.d.ts","sourceRoot":"","sources":["../../../../src/src/agent/memory/redis.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAEL,KAAK,MAAM,EACX,KAAK,gBAAgB,EACrB,KAAK,WAAW,EAChB,KAAK,cAAc,EACpB,MAAM,uBAAuB,CAAC;AAG/B;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACzC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,EAAE,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7E,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAClC,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACvD;AAED;;GAEG;AACH,MAAM,WAAW,iBAAkB,SAAQ,gBAAgB;IACzD,IAAI,EAAE,OAAO,CAAC;IACd,4BAA4B;IAC5B,MAAM,EAAE,WAAW,CAAC;IACpB,iCAAiC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4CAA4C;IAC5C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,yCAAyC;IACzC,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAKD,qBAAa,WAAW,CAAC,CAAC,SAAS,cAAc,GAAG,cAAc,CAAE,YAAW,MAAM,CAAC,CAAC,CAAC;IACtF,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,MAAM,CAAoB;gBAEtB,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,iBAAiB;IAStD,OAAO,CAAC,MAAM;IAId,OAAO,CAAC,aAAa;IAUrB,GAAG,CAAC,OAAO,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IA2B9B,WAAW,IAAI,OAAO,CAAC,CAAC,EAAE,CAAC;IAQ3B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAUtB,QAAQ,IAAI,OAAO,CAAC,WAAW,CAAC;IAehC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAYtB,OAAO,CAAC,gBAAgB;CAazB;AAED,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,cAAc,GAAG,cAAc,EACzE,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,iBAAiB,GACxB,WAAW,CAAC,CAAC,CAAC,CAEhB"}
|
|
@@ -11,18 +11,20 @@ const DEFAULT_KEY_PREFIX = "veryfront:agent:memory:";
|
|
|
11
11
|
export class RedisMemory {
|
|
12
12
|
client;
|
|
13
13
|
agentId;
|
|
14
|
+
userId;
|
|
14
15
|
keyPrefix;
|
|
15
16
|
ttl;
|
|
16
17
|
config;
|
|
17
18
|
constructor(agentId, config) {
|
|
18
19
|
this.client = config.client;
|
|
19
20
|
this.agentId = agentId;
|
|
21
|
+
this.userId = config.userId ?? "anonymous";
|
|
20
22
|
this.keyPrefix = config.keyPrefix ?? DEFAULT_KEY_PREFIX;
|
|
21
23
|
this.ttl = config.ttl ?? DEFAULT_TTL;
|
|
22
24
|
this.config = config;
|
|
23
25
|
}
|
|
24
26
|
getKey() {
|
|
25
|
-
return `${this.keyPrefix}${this.agentId}`;
|
|
27
|
+
return `${this.keyPrefix}${this.agentId}:${this.userId}`;
|
|
26
28
|
}
|
|
27
29
|
parseMessages(data) {
|
|
28
30
|
if (!data)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/src/agent/runtime/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EACL,KAAK,WAAW,EAEhB,KAAK,aAAa,EAGlB,KAAK,OAAO,EAEZ,KAAK,QAAQ,EACd,MAAM,aAAa,CAAC;AAKrB,OAAO,EAAgB,KAAK,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAe/D,OAAO,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACpF,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzE,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAChF,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC1E,YAAY,EAAE,iBAAiB,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAClG,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,mBAAmB,EACnB,sBAAsB,GACvB,MAAM,gBAAgB,CAAC;AAqBxB;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,EAAE,GAAG,SAAS,CA6BxE;AAED,gEAAgE;AAChE,KAAK,iBAAiB,GAClB;IAAE,OAAO,EAAE,IAAI,CAAA;CAAE,GACjB;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtC;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,iBAAiB,EAAE,MAAM,EAAE,GAAG,SAAS,EACvC,kBAAkB,EAAE,OAAO,GAC1B,iBAAiB,CAiBnB;AAkCD,qBAAa,YAAY;IACvB,OAAO,CAAC,EAAE,CAAS;IACnB,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,MAAM,CAAuB;gBAEzB,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW;IAS3C;;OAEG;IACG,QAAQ,CACZ,KAAK,EAAE,MAAM,GAAG,OAAO,EAAE,EACzB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,aAAa,CAAC,EAAE,MAAM,GACrB,OAAO,CAAC,aAAa,CAAC;IAgCzB;;;OAGG;IACG,MAAM,CACV,QAAQ,EAAE,OAAO,EAAE,EACnB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,SAAS,CAAC,EAAE;QACV,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,IAAI,CAAC;QAC1C,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;KACnC,EACD,aAAa,CAAC,EAAE,MAAM,GACrB,OAAO,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/src/agent/runtime/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EACL,KAAK,WAAW,EAEhB,KAAK,aAAa,EAGlB,KAAK,OAAO,EAEZ,KAAK,QAAQ,EACd,MAAM,aAAa,CAAC;AAKrB,OAAO,EAAgB,KAAK,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAe/D,OAAO,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACpF,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzE,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAChF,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC1E,YAAY,EAAE,iBAAiB,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAClG,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,mBAAmB,EACnB,sBAAsB,GACvB,MAAM,gBAAgB,CAAC;AAqBxB;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,EAAE,GAAG,SAAS,CA6BxE;AAED,gEAAgE;AAChE,KAAK,iBAAiB,GAClB;IAAE,OAAO,EAAE,IAAI,CAAA;CAAE,GACjB;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtC;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,iBAAiB,EAAE,MAAM,EAAE,GAAG,SAAS,EACvC,kBAAkB,EAAE,OAAO,GAC1B,iBAAiB,CAiBnB;AAkCD,qBAAa,YAAY;IACvB,OAAO,CAAC,EAAE,CAAS;IACnB,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,MAAM,CAAuB;gBAEzB,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW;IAS3C;;OAEG;IACG,QAAQ,CACZ,KAAK,EAAE,MAAM,GAAG,OAAO,EAAE,EACzB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,aAAa,CAAC,EAAE,MAAM,GACrB,OAAO,CAAC,aAAa,CAAC;IAgCzB;;;OAGG;IACG,MAAM,CACV,QAAQ,EAAE,OAAO,EAAE,EACnB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,SAAS,CAAC,EAAE;QACV,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,IAAI,CAAC;QAC1C,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;KACnC,EACD,aAAa,CAAC,EAAE,MAAM,GACrB,OAAO,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;IAgFtC;;OAEG;YACW,gBAAgB;IAyN9B;;;;OAIG;YACW,yBAAyB;IAyNvC;;OAEG;YACW,eAAe;IAqC7B;;OAEG;YACW,mBAAmB;IAOjC;;OAEG;IACH,OAAO,CAAC,eAAe;IAKvB;;OAEG;IACH,SAAS,IAAI,MAAM,CAAC,OAAO,CAAC;IAI5B;;OAEG;IACG,cAAc,IAAI,OAAO,CAAC;QAC9B,aAAa,EAAE,MAAM,CAAC;QACtB,eAAe,EAAE,MAAM,CAAC;QACxB,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;IAIF;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;CAGnC"}
|
|
@@ -211,9 +211,10 @@ export class AgentRuntime {
|
|
|
211
211
|
}
|
|
212
212
|
catch (error) {
|
|
213
213
|
this.status = "error";
|
|
214
|
+
logger.error("Agent stream error", { error });
|
|
214
215
|
sendSSE(controller, encoder, {
|
|
215
216
|
type: "error",
|
|
216
|
-
error:
|
|
217
|
+
error: "An internal error occurred",
|
|
217
218
|
});
|
|
218
219
|
controller.close();
|
|
219
220
|
}
|
|
@@ -16,4 +16,6 @@ export interface RateLimitOptions {
|
|
|
16
16
|
keyGenerator?: (req: dntShim.Request) => string;
|
|
17
17
|
}
|
|
18
18
|
export declare function rateLimit(optionsOrMaxRequests?: number | RateLimitOptions, windowMsArg?: number): Middleware;
|
|
19
|
+
/** Pre-configured rate limiter for authentication endpoints (5 req/15min). */
|
|
20
|
+
export declare function authRateLimit(store?: RateLimitStore): Middleware;
|
|
19
21
|
//# sourceMappingURL=rate-limit.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rate-limit.d.ts","sourceRoot":"","sources":["../../../../../src/src/middleware/builtin/security/rate-limit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,2BAA2B,CAAC;AACrD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAYjE,qBAAa,oBAAqB,YAAW,cAAc;IACzD,OAAO,CAAC,MAAM,CAAqC;IACnD,OAAO,CAAC,eAAe,CAAC,CAAyC;gBAErD,QAAQ,EAAE,MAAM;IAgB5B,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAcjE,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKjC,OAAO,IAAI,IAAI;CAIhB;AAED,MAAM,WAAW,gBAAgB;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,KAAK,MAAM,CAAC;CACjD;AAED,wBAAgB,SAAS,CACvB,oBAAoB,CAAC,EAAE,MAAM,GAAG,gBAAgB,EAChD,WAAW,CAAC,EAAE,MAAM,GACnB,UAAU,
|
|
1
|
+
{"version":3,"file":"rate-limit.d.ts","sourceRoot":"","sources":["../../../../../src/src/middleware/builtin/security/rate-limit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,2BAA2B,CAAC;AACrD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAYjE,qBAAa,oBAAqB,YAAW,cAAc;IACzD,OAAO,CAAC,MAAM,CAAqC;IACnD,OAAO,CAAC,eAAe,CAAC,CAAyC;gBAErD,QAAQ,EAAE,MAAM;IAgB5B,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAcjE,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKjC,OAAO,IAAI,IAAI;CAIhB;AAED,MAAM,WAAW,gBAAgB;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,KAAK,MAAM,CAAC;CACjD;AAED,wBAAgB,SAAS,CACvB,oBAAoB,CAAC,EAAE,MAAM,GAAG,gBAAgB,EAChD,WAAW,CAAC,EAAE,MAAM,GACnB,UAAU,CAkCZ;AAED,8EAA8E;AAC9E,wBAAgB,aAAa,CAAC,KAAK,CAAC,EAAE,cAAc,GAAG,UAAU,CAMhE"}
|
|
@@ -49,8 +49,16 @@ export function rateLimit(optionsOrMaxRequests, windowMsArg) {
|
|
|
49
49
|
const maxRequests = options.maxRequests ?? DEFAULT_RATE_LIMIT_REQUESTS;
|
|
50
50
|
const windowMs = options.windowMs ?? DEFAULT_RATE_LIMIT_WINDOW_MS;
|
|
51
51
|
const store = options.store ?? new MemoryRateLimitStore(windowMs);
|
|
52
|
-
const keyGenerator = options.keyGenerator ??
|
|
53
|
-
|
|
52
|
+
const keyGenerator = options.keyGenerator ?? ((req) => {
|
|
53
|
+
const forwarded = req.headers.get("x-forwarded-for");
|
|
54
|
+
if (forwarded) {
|
|
55
|
+
const parts = forwarded.split(",").map((s) => s.trim()).filter(Boolean);
|
|
56
|
+
// Use rightmost IP — added by nearest trusted proxy, not spoofable by clients
|
|
57
|
+
if (parts.length > 0)
|
|
58
|
+
return parts[parts.length - 1];
|
|
59
|
+
}
|
|
60
|
+
return "anonymous";
|
|
61
|
+
});
|
|
54
62
|
return async (ctx, next) => {
|
|
55
63
|
const req = getRequest(ctx);
|
|
56
64
|
const key = keyGenerator(req);
|
|
@@ -64,3 +72,11 @@ export function rateLimit(optionsOrMaxRequests, windowMsArg) {
|
|
|
64
72
|
});
|
|
65
73
|
};
|
|
66
74
|
}
|
|
75
|
+
/** Pre-configured rate limiter for authentication endpoints (5 req/15min). */
|
|
76
|
+
export function authRateLimit(store) {
|
|
77
|
+
return rateLimit({
|
|
78
|
+
maxRequests: 5,
|
|
79
|
+
windowMs: 15 * MS_PER_MINUTE,
|
|
80
|
+
store,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
@@ -2,6 +2,9 @@ import type { OAuthState, OAuthTokens, TokenStore } from "../types.js";
|
|
|
2
2
|
export declare class MemoryTokenStore implements TokenStore {
|
|
3
3
|
private tokens;
|
|
4
4
|
private states;
|
|
5
|
+
private projectId;
|
|
6
|
+
constructor(projectId?: string);
|
|
7
|
+
private scopedKey;
|
|
5
8
|
getTokens(serviceId: string): Promise<OAuthTokens | null>;
|
|
6
9
|
setTokens(serviceId: string, tokens: OAuthTokens): Promise<void>;
|
|
7
10
|
clearTokens(serviceId: string): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../../../../src/src/oauth/token-store/memory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAKvE,qBAAa,gBAAiB,YAAW,UAAU;IACjD,OAAO,CAAC,MAAM,CAAkC;IAChD,OAAO,CAAC,MAAM,CAAiC;
|
|
1
|
+
{"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../../../../src/src/oauth/token-store/memory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAKvE,qBAAa,gBAAiB,YAAW,UAAU;IACjD,OAAO,CAAC,MAAM,CAAkC;IAChD,OAAO,CAAC,MAAM,CAAiC;IAC/C,OAAO,CAAC,SAAS,CAAS;gBAEd,SAAS,SAAY;IAIjC,OAAO,CAAC,SAAS;IAIX,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAIzD,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAIhE,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI7C,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAYnD,QAAQ,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAK/C,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI9C,OAAO,CAAC,oBAAoB;IAS5B,oBAAoB,IAAI,MAAM,EAAE;IAIhC,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAQvC,QAAQ,IAAI,IAAI;CAIjB;AAED,eAAO,MAAM,gBAAgB,kBAAyB,CAAC"}
|
|
@@ -3,14 +3,21 @@ const STATE_EXPIRATION_MS = 10 * 60 * 1_000;
|
|
|
3
3
|
export class MemoryTokenStore {
|
|
4
4
|
tokens = new Map();
|
|
5
5
|
states = new Map();
|
|
6
|
+
projectId;
|
|
7
|
+
constructor(projectId = "default") {
|
|
8
|
+
this.projectId = projectId;
|
|
9
|
+
}
|
|
10
|
+
scopedKey(serviceId) {
|
|
11
|
+
return `${this.projectId}:${serviceId}`;
|
|
12
|
+
}
|
|
6
13
|
async getTokens(serviceId) {
|
|
7
|
-
return this.tokens.get(serviceId) ?? null;
|
|
14
|
+
return this.tokens.get(this.scopedKey(serviceId)) ?? null;
|
|
8
15
|
}
|
|
9
16
|
async setTokens(serviceId, tokens) {
|
|
10
|
-
this.tokens.set(serviceId, tokens);
|
|
17
|
+
this.tokens.set(this.scopedKey(serviceId), tokens);
|
|
11
18
|
}
|
|
12
19
|
async clearTokens(serviceId) {
|
|
13
|
-
this.tokens.delete(serviceId);
|
|
20
|
+
this.tokens.delete(this.scopedKey(serviceId));
|
|
14
21
|
}
|
|
15
22
|
async getState(state) {
|
|
16
23
|
const oauthState = this.states.get(state);
|
|
@@ -41,7 +48,7 @@ export class MemoryTokenStore {
|
|
|
41
48
|
return [...this.tokens.keys()];
|
|
42
49
|
}
|
|
43
50
|
isConnected(serviceId) {
|
|
44
|
-
const tokens = this.tokens.get(serviceId);
|
|
51
|
+
const tokens = this.tokens.get(this.scopedKey(serviceId));
|
|
45
52
|
if (!tokens)
|
|
46
53
|
return false;
|
|
47
54
|
const isExpired = tokens.expiresAt != null && Date.now() > tokens.expiresAt;
|
package/esm/src/proxy/main.js
CHANGED
|
@@ -480,6 +480,9 @@ function router(req) {
|
|
|
480
480
|
}
|
|
481
481
|
switch (url.pathname) {
|
|
482
482
|
case "/_proxy/stats":
|
|
483
|
+
if (Object.keys(proxyHandler.localProjects).length === 0) {
|
|
484
|
+
return Promise.resolve(new dntShim.Response("Forbidden", { status: 403 }));
|
|
485
|
+
}
|
|
483
486
|
return handleStats();
|
|
484
487
|
case "/_proxy/health":
|
|
485
488
|
return Promise.resolve(dntShim.Response.json({ service: "veryfront-proxy", status: "ok" }));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"security-config.d.ts","sourceRoot":"","sources":["../../../../../src/src/routing/api/module-loader/security-config.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAGzE,wBAAsB,kBAAkB,CACtC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,MAAM,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"security-config.d.ts","sourceRoot":"","sources":["../../../../../src/src/routing/api/module-loader/security-config.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAGzE,wBAAsB,kBAAkB,CACtC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,MAAM,EAAE,CAAC,CAoBnB"}
|
|
@@ -5,6 +5,10 @@ export async function loadSecurityConfig(projectDir, adapter) {
|
|
|
5
5
|
const cfg = await getConfig(projectDir, adapter);
|
|
6
6
|
const remote = cfg.security?.remoteHosts;
|
|
7
7
|
if (Array.isArray(remote)) {
|
|
8
|
+
if (remote.length === 0) {
|
|
9
|
+
logger.warn("security.remoteHosts is set to an empty array — all remote requests will be blocked. " +
|
|
10
|
+
"If this is intentional, you can ignore this warning.");
|
|
11
|
+
}
|
|
8
12
|
return remote;
|
|
9
13
|
}
|
|
10
14
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../../src/src/security/http/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAO7D,qBAAa,oBAAoB;IAO7B,OAAO,CAAC,UAAU;IAClB,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,cAAc,CAAC;IARzB,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,aAAa,CAAuB;IAC5C,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,WAAW,CAA8B;gBAGvC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,cAAc,EACvB,cAAc,CAAC,EAAE,eAAe,YAAA;IAGpC,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;YAQrB,IAAI;IAWlB,OAAO,CAAC,WAAW;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../../src/src/security/http/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAO7D,qBAAa,oBAAoB;IAO7B,OAAO,CAAC,UAAU;IAClB,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,cAAc,CAAC;IARzB,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,aAAa,CAAuB;IAC5C,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,WAAW,CAA8B;gBAGvC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,cAAc,EACvB,cAAc,CAAC,EAAE,eAAe,YAAA;IAGpC,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;YAQrB,IAAI;IAWlB,OAAO,CAAC,WAAW;IAoBnB,OAAO,CAAC,kBAAkB;IAgB1B,iBAAiB,IAAI,cAAc,GAAG,IAAI;IAI1C,gBAAgB,IAAI,MAAM,GAAG,IAAI;IAIjC,aAAa,IAAI,cAAc,CAAC,MAAM,CAAC;IAIvC,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,GAAE,MAAwB,GAAG,MAAM;IAIjE,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM;IASnE,KAAK,IAAI,IAAI;CAMd"}
|
|
@@ -38,7 +38,12 @@ export class SecurityConfigLoader {
|
|
|
38
38
|
const security = cfg?.security ? { ...cfg.security } : {};
|
|
39
39
|
if (security.headers)
|
|
40
40
|
security.headers = { ...security.headers };
|
|
41
|
-
security.cors ??=
|
|
41
|
+
security.cors ??= false;
|
|
42
|
+
if (!cfg?.security?.cors && !cfg?.security?.csrf) {
|
|
43
|
+
logger.warn("Neither CORS nor CSRF protection is configured. " +
|
|
44
|
+
"CORS is disabled by default (same-origin only). " +
|
|
45
|
+
"Consider explicitly configuring security.cors and security.csrf.");
|
|
46
|
+
}
|
|
42
47
|
this.securityConfig = security;
|
|
43
48
|
this.cspUserHeader = this.parseCspUserHeader(security.csp);
|
|
44
49
|
this.isLoaded = true;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../../../../src/src/server/handlers/dev/dashboard/api.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,8BAA8B,CAAC;AA2BxD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AA2CrD,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,OAAO,CAAC,OAAO,EACpB,GAAG,EAAE,cAAc,GAClB,OAAO,CAAC,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../../../../src/src/server/handlers/dev/dashboard/api.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,8BAA8B,CAAC;AA2BxD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AA2CrD,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,OAAO,CAAC,OAAO,EACpB,GAAG,EAAE,cAAc,GAClB,OAAO,CAAC,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAgE5D"}
|
|
@@ -56,6 +56,8 @@ function errorResponse(message, status = 500) {
|
|
|
56
56
|
return jsonResponse({ error: message }, status);
|
|
57
57
|
}
|
|
58
58
|
export function handleDashboardAPI(req, ctx) {
|
|
59
|
+
if (!ctx.isLocalProject)
|
|
60
|
+
return errorResponse("Unauthorized", 401);
|
|
59
61
|
const { pathname } = new URL(req.url);
|
|
60
62
|
if (req.method === "GET") {
|
|
61
63
|
switch (pathname) {
|
|
@@ -40,7 +40,7 @@ export class OpenAPIHandler extends BaseHandler {
|
|
|
40
40
|
const isDev = !!ctx.isLocalProject;
|
|
41
41
|
const response = this.createResponseBuilder(ctx)
|
|
42
42
|
.withCache(isDev ? "no-cache" : { maxAge: SPEC_CACHE_MAX_AGE_SECONDS, public: true })
|
|
43
|
-
.withCORS(req,
|
|
43
|
+
.withCORS(req, ctx.securityConfig?.cors)
|
|
44
44
|
.withContentType(isYaml ? "text/yaml; charset=utf-8" : "application/json; charset=utf-8", content, HTTP_OK);
|
|
45
45
|
return this.respond(response);
|
|
46
46
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"static-file.service.d.ts","sourceRoot":"","sources":["../../../../../src/src/server/services/static/static-file.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAEzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAEhE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;AAY3E;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,gCAAgC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,4BAA4B;IAC5B,IAAI,EAAE,UAAU,CAAC;IACjB,uBAAuB;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,sCAAsC;IACtC,WAAW,EAAE,MAAM,CAAC;IACpB,4BAA4B;IAC5B,aAAa,EAAE,aAAa,CAAC;IAC7B,gDAAgD;IAChD,MAAM,EAAE,UAAU,GAAG,MAAM,GAAG,QAAQ,CAAC;CACxC;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,6BAA6B;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,6CAA6C;IAC7C,OAAO,EAAE,cAAc,CAAC;IACxB,gDAAgD;IAChD,aAAa,EAAE,OAAO,CAAC;IACvB,iDAAiD;IACjD,cAAc,EAAE,OAAO,CAAC;CACzB;AAED;;GAEG;AACH,UAAU,aAAa;IACrB,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAYD;;GAEG;AACH,UAAU,qBAAqB;IAC7B,aAAa,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IAC3C,eAAe,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAAC,CAAC;CAC9D;AAID;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,qBAAqB,GAAG,IAAI,GAAG,IAAI,CAE7E;AAED,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,MAAM,CAAC,aAAa,CAAoC;IAChE,OAAO,CAAC,MAAM,CAAC,eAAe,CAAoD;IAElF,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAuB;gBAEnC,MAAM,CAAC,EAAE,oBAAoB;IAIzC,OAAO,CAAC,gBAAgB;IAIxB,OAAO,CAAC,kBAAkB;IAI1B,OAAO,CAAC,aAAa;IAWf,WAAW,CACf,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;YAarB,eAAe;YA2Bf,mBAAmB;IA2BjC,OAAO,CAAC,sBAAsB;YAkBhB,oBAAoB;YAYpB,iBAAiB;IA+C/B,OAAO,CAAC,qBAAqB;IAyC7B,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;
|
|
1
|
+
{"version":3,"file":"static-file.service.d.ts","sourceRoot":"","sources":["../../../../../src/src/server/services/static/static-file.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAEzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAEhE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;AAY3E;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,gCAAgC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,4BAA4B;IAC5B,IAAI,EAAE,UAAU,CAAC;IACjB,uBAAuB;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,sCAAsC;IACtC,WAAW,EAAE,MAAM,CAAC;IACpB,4BAA4B;IAC5B,aAAa,EAAE,aAAa,CAAC;IAC7B,gDAAgD;IAChD,MAAM,EAAE,UAAU,GAAG,MAAM,GAAG,QAAQ,CAAC;CACxC;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,6BAA6B;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,6CAA6C;IAC7C,OAAO,EAAE,cAAc,CAAC;IACxB,gDAAgD;IAChD,aAAa,EAAE,OAAO,CAAC;IACvB,iDAAiD;IACjD,cAAc,EAAE,OAAO,CAAC;CACzB;AAED;;GAEG;AACH,UAAU,aAAa;IACrB,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAYD;;GAEG;AACH,UAAU,qBAAqB;IAC7B,aAAa,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IAC3C,eAAe,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAAC,CAAC;CAC9D;AAID;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,qBAAqB,GAAG,IAAI,GAAG,IAAI,CAE7E;AAED,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,MAAM,CAAC,aAAa,CAAoC;IAChE,OAAO,CAAC,MAAM,CAAC,eAAe,CAAoD;IAElF,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAuB;gBAEnC,MAAM,CAAC,EAAE,oBAAoB;IAIzC,OAAO,CAAC,gBAAgB;IAIxB,OAAO,CAAC,kBAAkB;IAI1B,OAAO,CAAC,aAAa;IAWf,WAAW,CACf,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;YAarB,eAAe;YA2Bf,mBAAmB;IA2BjC,OAAO,CAAC,sBAAsB;YAkBhB,oBAAoB;YAYpB,iBAAiB;IA+C/B,OAAO,CAAC,qBAAqB;IAyC7B,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAOzC,OAAO,CAAC,eAAe;IAUvB,MAAM,CAAC,UAAU,IAAI,IAAI;CAI1B"}
|
|
@@ -196,8 +196,19 @@ export class StaticFileService {
|
|
|
196
196
|
return false;
|
|
197
197
|
if (pathname.endsWith(".md"))
|
|
198
198
|
return false;
|
|
199
|
+
if (this.isDeniedDotfile(pathname))
|
|
200
|
+
return false;
|
|
199
201
|
return pathname.includes(".") || pathname.startsWith("/_veryfront/");
|
|
200
202
|
}
|
|
203
|
+
isDeniedDotfile(pathname) {
|
|
204
|
+
const segments = pathname.split("/");
|
|
205
|
+
for (const segment of segments) {
|
|
206
|
+
if (segment.startsWith(".") && segment !== ".well-known") {
|
|
207
|
+
return true;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
return false;
|
|
211
|
+
}
|
|
201
212
|
static clearCache() {
|
|
202
213
|
StaticFileService.manifestCache.clear();
|
|
203
214
|
StaticFileService.manifestLoading.clear();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../../src/src/tool/factory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AA2HzE,wBAAgB,IAAI,CAAC,MAAM,GAAG,OAAO,EAAE,OAAO,GAAG,OAAO,EACtD,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,GAClC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAoCvB;AAED,MAAM,WAAW,iBAAiB;IAChC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,OAAO,CAAC;IACrB,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,oBAAoB,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;IACxF,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC;IAC7C,GAAG,CAAC,EAAE;QACJ,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,YAAY,CAAC,EAAE,OAAO,CAAC;QACvB,WAAW,CAAC,EAAE,UAAU,GAAG,OAAO,GAAG,aAAa,CAAC;KACpD,CAAC;CACH;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../../src/src/tool/factory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AA2HzE,wBAAgB,IAAI,CAAC,MAAM,GAAG,OAAO,EAAE,OAAO,GAAG,OAAO,EACtD,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,GAClC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAoCvB;AAED,MAAM,WAAW,iBAAiB;IAChC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,OAAO,CAAC;IACrB,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,oBAAoB,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;IACxF,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC;IAC7C,GAAG,CAAC,EAAE;QACJ,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,YAAY,CAAC,EAAE,OAAO,CAAC;QACvB,WAAW,CAAC,EAAE,UAAU,GAAG,OAAO,GAAG,aAAa,CAAC;KACpD,CAAC;CACH;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CA2B7E"}
|
package/esm/src/tool/factory.js
CHANGED
|
@@ -105,6 +105,16 @@ export function dynamicTool(config) {
|
|
|
105
105
|
inputSchema: config.inputSchema,
|
|
106
106
|
inputSchemaJson,
|
|
107
107
|
execute: async (input, context) => {
|
|
108
|
+
if (config.inputSchema &&
|
|
109
|
+
typeof config.inputSchema.parse === "function") {
|
|
110
|
+
config.inputSchema.parse(input);
|
|
111
|
+
}
|
|
112
|
+
else if (input === undefined) {
|
|
113
|
+
input = {};
|
|
114
|
+
}
|
|
115
|
+
else if (input === null || typeof input !== "object") {
|
|
116
|
+
throw new Error("dynamicTool: input must be a non-null object");
|
|
117
|
+
}
|
|
108
118
|
const result = await config.execute(input, context);
|
|
109
119
|
return config.toModelOutput ? config.toModelOutput(result) : result;
|
|
110
120
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../../../../../../src/src/transforms/pipeline/stages/ssr-vf-modules/transform.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;
|
|
1
|
+
{"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../../../../../../src/src/transforms/pipeline/stages/ssr-vf-modules/transform.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAcrE,OAAO,EAOL,KAAK,gBAAgB,EAGtB,MAAM,gBAAgB,CAAC;AAIxB;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAExD;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,oBAAoB,CACxC,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,EACpB,EAAE,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,GACtC,OAAO,CAAC,MAAM,CAAC,CA2BjB;AAED;;;;;GAKG;AACH,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,GAAG,EAAE,gBAAgB,EACrB,oBAAoB,UAAQ,EAC5B,KAAK,SAAI,GACR,OAAO,CAAC,MAAM,CAAC,CAyQjB;AAED;;;GAGG;AACH,wBAAsB,kCAAkC,CACtD,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,gBAAgB,GACpB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA4CxB;AAED;;;GAGG;AACH,wBAAsB,wBAAwB,CAC5C,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,EAClB,EAAE,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,GACtC,OAAO,CAAC,MAAM,CAAC,CAEjB"}
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* resolves all imports (#veryfront/, relative, React).
|
|
6
6
|
*/
|
|
7
7
|
import { join } from "../../../../platform/compat/path/index.js";
|
|
8
|
+
import denoConfig from "../../../../../deno.js";
|
|
8
9
|
import { rendererLogger as logger } from "../../../../utils/index.js";
|
|
9
10
|
import { IMPORT_RESOLUTION_ERROR } from "../../../../errors/index.js";
|
|
10
11
|
import { replaceSpecifiers } from "../../../esm/lexer.js";
|
|
@@ -17,6 +18,7 @@ import { buildReactUrl, getReactImportMap } from "../../../import-rewriter/url-b
|
|
|
17
18
|
import { findRelativeImports } from "./import-finder.js";
|
|
18
19
|
import { resolveRelativeFrameworkImport, resolveVeryfrontSourcePath } from "./path-resolver.js";
|
|
19
20
|
import { EMBEDDED_SRC_DIR, FRAMEWORK_ROOT, frameworkFileCache, frameworkWriteFlight, LOG_PREFIX, MAX_RELATIVE_IMPORT_DEPTH, transformingFiles, veryfrontTransformCache, } from "./constants.js";
|
|
21
|
+
const DENO_CONFIG_STUB_CODE = `export default ${JSON.stringify(denoConfig)};`;
|
|
20
22
|
/**
|
|
21
23
|
* Check if a transformed code string is a cycle placeholder.
|
|
22
24
|
* Cycle placeholders are returned when transformFrameworkCode detects a cycle
|
|
@@ -236,7 +238,20 @@ export async function transformFrameworkCode(content, sourcePath, ctx, throwOnMi
|
|
|
236
238
|
}
|
|
237
239
|
// Rewrite imports to resolved paths
|
|
238
240
|
const reactImportMap = getReactImportMap(ctx.reactVersion);
|
|
241
|
+
// Handle Deno import-map aliases (e.g. #deno-config) that only exist in
|
|
242
|
+
// the Deno runtime and cannot be resolved by esm.sh or the HTTP cache.
|
|
243
|
+
// We create a cached JS stub module so the transformed code can import it
|
|
244
|
+
// without losing access to imports/exports metadata from deno.json.
|
|
245
|
+
let denoConfigStubUrl = null;
|
|
246
|
+
if (transformed.includes('"#deno-config"') || transformed.includes("'#deno-config'")) {
|
|
247
|
+
const stubPath = await cacheTransformedCode(DENO_CONFIG_STUB_CODE, "#deno-config-stub", ctx.fs);
|
|
248
|
+
denoConfigStubUrl = `file://${stubPath}`;
|
|
249
|
+
}
|
|
239
250
|
transformed = await replaceSpecifiers(transformed, (specifier) => {
|
|
251
|
+
// Handle Deno import-map aliases
|
|
252
|
+
if (specifier === "#deno-config") {
|
|
253
|
+
return denoConfigStubUrl;
|
|
254
|
+
}
|
|
240
255
|
// Handle #veryfront/ imports
|
|
241
256
|
if (specifier.startsWith("#veryfront/")) {
|
|
242
257
|
return veryfrontReplacements.get(specifier) ?? null;
|
|
@@ -20,21 +20,17 @@ declare const claudeCodeInputSchema: z.ZodObject<{
|
|
|
20
20
|
files: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
21
21
|
/** Additional context */
|
|
22
22
|
context: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
23
|
-
/** Custom system prompt */
|
|
24
|
-
system: z.ZodOptional<z.ZodString>;
|
|
25
23
|
}, "strip", z.ZodTypeAny, {
|
|
26
24
|
mode: "code" | "custom" | "analysis";
|
|
27
25
|
task: string;
|
|
28
26
|
maxTurns: number;
|
|
29
27
|
context?: Record<string, unknown> | undefined;
|
|
30
28
|
files?: string[] | undefined;
|
|
31
|
-
system?: string | undefined;
|
|
32
29
|
}, {
|
|
33
30
|
task: string;
|
|
34
31
|
context?: Record<string, unknown> | undefined;
|
|
35
32
|
files?: string[] | undefined;
|
|
36
33
|
mode?: "code" | "custom" | "analysis" | undefined;
|
|
37
|
-
system?: string | undefined;
|
|
38
34
|
maxTurns?: number | undefined;
|
|
39
35
|
}>;
|
|
40
36
|
type ClaudeCodeInput = z.infer<typeof claudeCodeInputSchema>;
|
|
@@ -81,7 +77,6 @@ export declare const codeReviewTool: Tool<{
|
|
|
81
77
|
maxTurns: number;
|
|
82
78
|
context?: Record<string, unknown> | undefined;
|
|
83
79
|
files?: string[] | undefined;
|
|
84
|
-
system?: string | undefined;
|
|
85
80
|
}, ClaudeCodeResult>;
|
|
86
81
|
/** Bug fix tool (code mode) */
|
|
87
82
|
export declare const bugFixTool: Tool<{
|
|
@@ -90,7 +85,6 @@ export declare const bugFixTool: Tool<{
|
|
|
90
85
|
maxTurns: number;
|
|
91
86
|
context?: Record<string, unknown> | undefined;
|
|
92
87
|
files?: string[] | undefined;
|
|
93
|
-
system?: string | undefined;
|
|
94
88
|
}, ClaudeCodeResult>;
|
|
95
89
|
/** Refactoring tool (code mode) */
|
|
96
90
|
export declare const refactorTool: Tool<{
|
|
@@ -99,7 +93,6 @@ export declare const refactorTool: Tool<{
|
|
|
99
93
|
maxTurns: number;
|
|
100
94
|
context?: Record<string, unknown> | undefined;
|
|
101
95
|
files?: string[] | undefined;
|
|
102
|
-
system?: string | undefined;
|
|
103
96
|
}, ClaudeCodeResult>;
|
|
104
97
|
/** Documentation tool (code mode) */
|
|
105
98
|
export declare const docsTool: Tool<{
|
|
@@ -108,7 +101,6 @@ export declare const docsTool: Tool<{
|
|
|
108
101
|
maxTurns: number;
|
|
109
102
|
context?: Record<string, unknown> | undefined;
|
|
110
103
|
files?: string[] | undefined;
|
|
111
|
-
system?: string | undefined;
|
|
112
104
|
}, ClaudeCodeResult>;
|
|
113
105
|
export {};
|
|
114
106
|
//# sourceMappingURL=tool.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool.d.ts","sourceRoot":"","sources":["../../../../src/src/workflow/claude-code/tool.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAEhD,OAAO,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnE;;GAEG;AACH,QAAA,MAAM,qBAAqB;IACzB,qCAAqC;;IAGrC,gBAAgB;;IAOhB,oBAAoB;;
|
|
1
|
+
{"version":3,"file":"tool.d.ts","sourceRoot":"","sources":["../../../../src/src/workflow/claude-code/tool.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAEhD,OAAO,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnE;;GAEG;AACH,QAAA,MAAM,qBAAqB;IACzB,qCAAqC;;IAGrC,gBAAgB;;IAOhB,oBAAoB;;IAQpB,wBAAwB;;IAMxB,yBAAyB;;;;;;;;;;;;;;EAKzB,CAAC;AAEH,KAAK,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAmB7D;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,cAAc,EAAE,IAAI,CAAC,eAAe,EAAE,gBAAgB,CA6BlE,CAAC;AAEF;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,GAAE;IACP,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,cAAc,CAAC;IAC7B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;CACZ,GACL,IAAI,CAAC,eAAe,EAAE,gBAAgB,CAAC,CAqBzC;AAED;;GAEG;AAEH,kDAAkD;AAClD,eAAO,MAAM,cAAc;;;;;;oBAazB,CAAC;AAEH,+BAA+B;AAC/B,eAAO,MAAM,UAAU;;;;;;oBAarB,CAAC;AAEH,mCAAmC;AACnC,eAAO,MAAM,YAAY;;;;;;oBAavB,CAAC;AAEH,qCAAqC;AACrC,eAAO,MAAM,QAAQ;;;;;;oBAYnB,CAAC"}
|
|
@@ -20,6 +20,7 @@ const claudeCodeInputSchema = z.object({
|
|
|
20
20
|
/** Maximum turns */
|
|
21
21
|
maxTurns: z
|
|
22
22
|
.number()
|
|
23
|
+
.max(100)
|
|
23
24
|
.optional()
|
|
24
25
|
.default(20)
|
|
25
26
|
.describe("Maximum agentic loop turns"),
|
|
@@ -33,11 +34,6 @@ const claudeCodeInputSchema = z.object({
|
|
|
33
34
|
.record(z.unknown())
|
|
34
35
|
.optional()
|
|
35
36
|
.describe("Additional context to include in the prompt"),
|
|
36
|
-
/** Custom system prompt */
|
|
37
|
-
system: z
|
|
38
|
-
.string()
|
|
39
|
-
.optional()
|
|
40
|
-
.describe("Custom system prompt override"),
|
|
41
37
|
});
|
|
42
38
|
/**
|
|
43
39
|
* Build the full prompt from input
|
|
@@ -92,7 +88,6 @@ export const claudeCodeTool = {
|
|
|
92
88
|
maxTurns: { type: "number", default: 20 },
|
|
93
89
|
files: { type: "array", items: { type: "string" } },
|
|
94
90
|
context: { type: "object" },
|
|
95
|
-
system: { type: "string" },
|
|
96
91
|
},
|
|
97
92
|
required: ["task"],
|
|
98
93
|
},
|
|
@@ -100,7 +95,6 @@ export const claudeCodeTool = {
|
|
|
100
95
|
return executeAgent(buildPrompt(input), {
|
|
101
96
|
mode: input.mode,
|
|
102
97
|
maxTurns: input.maxTurns,
|
|
103
|
-
systemPrompt: input.system,
|
|
104
98
|
debug: true,
|
|
105
99
|
});
|
|
106
100
|
},
|
|
@@ -113,14 +107,18 @@ export function createClaudeCodeTool(options = {}) {
|
|
|
113
107
|
...claudeCodeTool,
|
|
114
108
|
id: options.id || claudeCodeTool.id,
|
|
115
109
|
description: options.description || claudeCodeTool.description,
|
|
116
|
-
execute: (input,
|
|
110
|
+
execute: (input, _context) => {
|
|
117
111
|
const mergedInput = {
|
|
118
112
|
...input,
|
|
119
113
|
mode: input.mode || options.defaultMode || "code",
|
|
120
114
|
maxTurns: input.maxTurns || options.defaultMaxTurns || 20,
|
|
121
|
-
system: input.system || options.system,
|
|
122
115
|
};
|
|
123
|
-
return
|
|
116
|
+
return executeAgent(buildPrompt(mergedInput), {
|
|
117
|
+
mode: mergedInput.mode,
|
|
118
|
+
maxTurns: mergedInput.maxTurns,
|
|
119
|
+
systemPrompt: options.system,
|
|
120
|
+
debug: true,
|
|
121
|
+
});
|
|
124
122
|
},
|
|
125
123
|
};
|
|
126
124
|
}
|
package/package.json
CHANGED
package/src/deno.js
CHANGED
|
@@ -265,6 +265,16 @@ function isRequest(obj: unknown): obj is dntShim.Request {
|
|
|
265
265
|
);
|
|
266
266
|
}
|
|
267
267
|
|
|
268
|
+
function extractUserId(request: dntShim.Request): string {
|
|
269
|
+
const userId = request.headers.get("x-user-id");
|
|
270
|
+
if (userId) return userId;
|
|
271
|
+
agentLogger.warn(
|
|
272
|
+
"No user identity found in request. Using anonymous fallback. " +
|
|
273
|
+
"Set x-user-id header or provide a context function for proper user isolation.",
|
|
274
|
+
);
|
|
275
|
+
return "anonymous";
|
|
276
|
+
}
|
|
277
|
+
|
|
268
278
|
function extractRequest(requestOrCtx: unknown): dntShim.Request {
|
|
269
279
|
if (isRequest(requestOrCtx)) return requestOrCtx;
|
|
270
280
|
// Pages Router APIContext — has a .request property
|
|
@@ -317,7 +327,7 @@ export function createChatHandler(
|
|
|
317
327
|
|
|
318
328
|
const context = typeof options?.context === "function"
|
|
319
329
|
? await options.context(request)
|
|
320
|
-
: options?.context ?? { userId:
|
|
330
|
+
: options?.context ?? { userId: extractUserId(request) };
|
|
321
331
|
|
|
322
332
|
const baseMessages = transformUIMessages(rawMessages);
|
|
323
333
|
const beforeStreamResult = await options?.beforeStream?.({
|
|
@@ -33,6 +33,8 @@ export interface RedisMemoryConfig extends MemoryConfigBase {
|
|
|
33
33
|
client: RedisClient;
|
|
34
34
|
/** Key prefix for namespacing */
|
|
35
35
|
keyPrefix?: string;
|
|
36
|
+
/** User ID for per-user memory isolation */
|
|
37
|
+
userId?: string;
|
|
36
38
|
/** TTL in seconds (default: 24 hours) */
|
|
37
39
|
ttl?: number;
|
|
38
40
|
}
|
|
@@ -43,6 +45,7 @@ const DEFAULT_KEY_PREFIX = "veryfront:agent:memory:";
|
|
|
43
45
|
export class RedisMemory<M extends MinimalMessage = MinimalMessage> implements Memory<M> {
|
|
44
46
|
private client: RedisClient;
|
|
45
47
|
private agentId: string;
|
|
48
|
+
private userId: string;
|
|
46
49
|
private keyPrefix: string;
|
|
47
50
|
private ttl: number;
|
|
48
51
|
private config: RedisMemoryConfig;
|
|
@@ -50,13 +53,14 @@ export class RedisMemory<M extends MinimalMessage = MinimalMessage> implements M
|
|
|
50
53
|
constructor(agentId: string, config: RedisMemoryConfig) {
|
|
51
54
|
this.client = config.client;
|
|
52
55
|
this.agentId = agentId;
|
|
56
|
+
this.userId = config.userId ?? "anonymous";
|
|
53
57
|
this.keyPrefix = config.keyPrefix ?? DEFAULT_KEY_PREFIX;
|
|
54
58
|
this.ttl = config.ttl ?? DEFAULT_TTL;
|
|
55
59
|
this.config = config;
|
|
56
60
|
}
|
|
57
61
|
|
|
58
62
|
private getKey(): string {
|
|
59
|
-
return `${this.keyPrefix}${this.agentId}`;
|
|
63
|
+
return `${this.keyPrefix}${this.agentId}:${this.userId}`;
|
|
60
64
|
}
|
|
61
65
|
|
|
62
66
|
private parseMessages(data: string | null): M[] {
|
|
@@ -307,9 +307,10 @@ export class AgentRuntime {
|
|
|
307
307
|
controller.close();
|
|
308
308
|
} catch (error) {
|
|
309
309
|
this.status = "error";
|
|
310
|
+
logger.error("Agent stream error", { error });
|
|
310
311
|
sendSSE(controller, encoder, {
|
|
311
312
|
type: "error",
|
|
312
|
-
error:
|
|
313
|
+
error: "An internal error occurred",
|
|
313
314
|
});
|
|
314
315
|
controller.close();
|
|
315
316
|
}
|
|
@@ -76,8 +76,15 @@ export function rateLimit(
|
|
|
76
76
|
const maxRequests = options.maxRequests ?? DEFAULT_RATE_LIMIT_REQUESTS;
|
|
77
77
|
const windowMs = options.windowMs ?? DEFAULT_RATE_LIMIT_WINDOW_MS;
|
|
78
78
|
const store = options.store ?? new MemoryRateLimitStore(windowMs);
|
|
79
|
-
const keyGenerator = options.keyGenerator ??
|
|
80
|
-
|
|
79
|
+
const keyGenerator = options.keyGenerator ?? ((req: dntShim.Request) => {
|
|
80
|
+
const forwarded = req.headers.get("x-forwarded-for");
|
|
81
|
+
if (forwarded) {
|
|
82
|
+
const parts = forwarded.split(",").map((s) => s.trim()).filter(Boolean);
|
|
83
|
+
// Use rightmost IP — added by nearest trusted proxy, not spoofable by clients
|
|
84
|
+
if (parts.length > 0) return parts[parts.length - 1]!;
|
|
85
|
+
}
|
|
86
|
+
return "anonymous";
|
|
87
|
+
});
|
|
81
88
|
|
|
82
89
|
return async (ctx, next) => {
|
|
83
90
|
const req = getRequest(ctx);
|
|
@@ -96,3 +103,12 @@ export function rateLimit(
|
|
|
96
103
|
});
|
|
97
104
|
};
|
|
98
105
|
}
|
|
106
|
+
|
|
107
|
+
/** Pre-configured rate limiter for authentication endpoints (5 req/15min). */
|
|
108
|
+
export function authRateLimit(store?: RateLimitStore): Middleware {
|
|
109
|
+
return rateLimit({
|
|
110
|
+
maxRequests: 5,
|
|
111
|
+
windowMs: 15 * MS_PER_MINUTE,
|
|
112
|
+
store,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
@@ -6,17 +6,26 @@ const STATE_EXPIRATION_MS = 10 * 60 * 1_000;
|
|
|
6
6
|
export class MemoryTokenStore implements TokenStore {
|
|
7
7
|
private tokens = new Map<string, OAuthTokens>();
|
|
8
8
|
private states = new Map<string, OAuthState>();
|
|
9
|
+
private projectId: string;
|
|
10
|
+
|
|
11
|
+
constructor(projectId = "default") {
|
|
12
|
+
this.projectId = projectId;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
private scopedKey(serviceId: string): string {
|
|
16
|
+
return `${this.projectId}:${serviceId}`;
|
|
17
|
+
}
|
|
9
18
|
|
|
10
19
|
async getTokens(serviceId: string): Promise<OAuthTokens | null> {
|
|
11
|
-
return this.tokens.get(serviceId) ?? null;
|
|
20
|
+
return this.tokens.get(this.scopedKey(serviceId)) ?? null;
|
|
12
21
|
}
|
|
13
22
|
|
|
14
23
|
async setTokens(serviceId: string, tokens: OAuthTokens): Promise<void> {
|
|
15
|
-
this.tokens.set(serviceId, tokens);
|
|
24
|
+
this.tokens.set(this.scopedKey(serviceId), tokens);
|
|
16
25
|
}
|
|
17
26
|
|
|
18
27
|
async clearTokens(serviceId: string): Promise<void> {
|
|
19
|
-
this.tokens.delete(serviceId);
|
|
28
|
+
this.tokens.delete(this.scopedKey(serviceId));
|
|
20
29
|
}
|
|
21
30
|
|
|
22
31
|
async getState(state: string): Promise<OAuthState | null> {
|
|
@@ -54,7 +63,7 @@ export class MemoryTokenStore implements TokenStore {
|
|
|
54
63
|
}
|
|
55
64
|
|
|
56
65
|
isConnected(serviceId: string): boolean {
|
|
57
|
-
const tokens = this.tokens.get(serviceId);
|
|
66
|
+
const tokens = this.tokens.get(this.scopedKey(serviceId));
|
|
58
67
|
if (!tokens) return false;
|
|
59
68
|
|
|
60
69
|
const isExpired = tokens.expiresAt != null && Date.now() > tokens.expiresAt;
|
package/src/src/proxy/main.ts
CHANGED
|
@@ -577,6 +577,9 @@ function router(req: dntShim.Request): Promise<dntShim.Response> {
|
|
|
577
577
|
|
|
578
578
|
switch (url.pathname) {
|
|
579
579
|
case "/_proxy/stats":
|
|
580
|
+
if (Object.keys(proxyHandler.localProjects).length === 0) {
|
|
581
|
+
return Promise.resolve(new dntShim.Response("Forbidden", { status: 403 }));
|
|
582
|
+
}
|
|
580
583
|
return handleStats();
|
|
581
584
|
case "/_proxy/health":
|
|
582
585
|
return Promise.resolve(
|
|
@@ -12,6 +12,12 @@ export async function loadSecurityConfig(
|
|
|
12
12
|
const remote = cfg.security?.remoteHosts;
|
|
13
13
|
|
|
14
14
|
if (Array.isArray(remote)) {
|
|
15
|
+
if (remote.length === 0) {
|
|
16
|
+
logger.warn(
|
|
17
|
+
"security.remoteHosts is set to an empty array — all remote requests will be blocked. " +
|
|
18
|
+
"If this is intentional, you can ignore this warning.",
|
|
19
|
+
);
|
|
20
|
+
}
|
|
15
21
|
return remote;
|
|
16
22
|
}
|
|
17
23
|
} catch (e) {
|
|
@@ -43,7 +43,15 @@ export class SecurityConfigLoader {
|
|
|
43
43
|
|
|
44
44
|
if (security.headers) security.headers = { ...security.headers };
|
|
45
45
|
|
|
46
|
-
security.cors ??=
|
|
46
|
+
security.cors ??= false;
|
|
47
|
+
|
|
48
|
+
if (!cfg?.security?.cors && !cfg?.security?.csrf) {
|
|
49
|
+
logger.warn(
|
|
50
|
+
"Neither CORS nor CSRF protection is configured. " +
|
|
51
|
+
"CORS is disabled by default (same-origin only). " +
|
|
52
|
+
"Consider explicitly configuring security.cors and security.csrf.",
|
|
53
|
+
);
|
|
54
|
+
}
|
|
47
55
|
|
|
48
56
|
this.securityConfig = security;
|
|
49
57
|
this.cspUserHeader = this.parseCspUserHeader(security.csp);
|
|
@@ -72,6 +72,8 @@ export function handleDashboardAPI(
|
|
|
72
72
|
req: dntShim.Request,
|
|
73
73
|
ctx: HandlerContext,
|
|
74
74
|
): Promise<dntShim.Response | null> | dntShim.Response | null {
|
|
75
|
+
if (!ctx.isLocalProject) return errorResponse("Unauthorized", 401);
|
|
76
|
+
|
|
75
77
|
const { pathname } = new URL(req.url);
|
|
76
78
|
|
|
77
79
|
if (req.method === "GET") {
|
|
@@ -56,7 +56,7 @@ export class OpenAPIHandler extends BaseHandler {
|
|
|
56
56
|
|
|
57
57
|
const response = this.createResponseBuilder(ctx)
|
|
58
58
|
.withCache(isDev ? "no-cache" : { maxAge: SPEC_CACHE_MAX_AGE_SECONDS, public: true })
|
|
59
|
-
.withCORS(req,
|
|
59
|
+
.withCORS(req, ctx.securityConfig?.cors)
|
|
60
60
|
.withContentType(
|
|
61
61
|
isYaml ? "text/yaml; charset=utf-8" : "application/json; charset=utf-8",
|
|
62
62
|
content,
|
|
@@ -312,9 +312,20 @@ export class StaticFileService {
|
|
|
312
312
|
isAssetRequest(pathname: string): boolean {
|
|
313
313
|
if (pathname.includes("/.veryfront/") || pathname.startsWith("/.veryfront")) return false;
|
|
314
314
|
if (pathname.endsWith(".md")) return false;
|
|
315
|
+
if (this.isDeniedDotfile(pathname)) return false;
|
|
315
316
|
return pathname.includes(".") || pathname.startsWith("/_veryfront/");
|
|
316
317
|
}
|
|
317
318
|
|
|
319
|
+
private isDeniedDotfile(pathname: string): boolean {
|
|
320
|
+
const segments = pathname.split("/");
|
|
321
|
+
for (const segment of segments) {
|
|
322
|
+
if (segment.startsWith(".") && segment !== ".well-known") {
|
|
323
|
+
return true;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
return false;
|
|
327
|
+
}
|
|
328
|
+
|
|
318
329
|
static clearCache(): void {
|
|
319
330
|
StaticFileService.manifestCache.clear();
|
|
320
331
|
StaticFileService.manifestLoading.clear();
|
package/src/src/tool/factory.ts
CHANGED
|
@@ -186,6 +186,16 @@ export function dynamicTool(config: DynamicToolConfig): Tool<unknown, unknown> {
|
|
|
186
186
|
inputSchema: config.inputSchema as z.ZodSchema<unknown>,
|
|
187
187
|
inputSchemaJson,
|
|
188
188
|
execute: async (input: unknown, context?: ToolExecutionContext) => {
|
|
189
|
+
if (
|
|
190
|
+
config.inputSchema &&
|
|
191
|
+
typeof (config.inputSchema as { parse?: unknown }).parse === "function"
|
|
192
|
+
) {
|
|
193
|
+
(config.inputSchema as { parse: (v: unknown) => unknown }).parse(input);
|
|
194
|
+
} else if (input === undefined) {
|
|
195
|
+
input = {};
|
|
196
|
+
} else if (input === null || typeof input !== "object") {
|
|
197
|
+
throw new Error("dynamicTool: input must be a non-null object");
|
|
198
|
+
}
|
|
189
199
|
const result = await config.execute(input, context);
|
|
190
200
|
return config.toModelOutput ? config.toModelOutput(result) : result;
|
|
191
201
|
},
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
import { createFileSystem } from "../../../../platform/compat/fs.js";
|
|
9
9
|
import { join } from "../../../../platform/compat/path/index.js";
|
|
10
|
+
import denoConfig from "../../../../../deno.js";
|
|
10
11
|
import { rendererLogger as logger } from "../../../../utils/index.js";
|
|
11
12
|
import { IMPORT_RESOLUTION_ERROR } from "../../../../errors/index.js";
|
|
12
13
|
import { replaceSpecifiers } from "../../../esm/lexer.js";
|
|
@@ -30,6 +31,8 @@ import {
|
|
|
30
31
|
veryfrontTransformCache,
|
|
31
32
|
} from "./constants.js";
|
|
32
33
|
|
|
34
|
+
const DENO_CONFIG_STUB_CODE = `export default ${JSON.stringify(denoConfig)};`;
|
|
35
|
+
|
|
33
36
|
/**
|
|
34
37
|
* Check if a transformed code string is a cycle placeholder.
|
|
35
38
|
* Cycle placeholders are returned when transformFrameworkCode detects a cycle
|
|
@@ -291,7 +294,26 @@ export async function transformFrameworkCode(
|
|
|
291
294
|
// Rewrite imports to resolved paths
|
|
292
295
|
const reactImportMap = getReactImportMap(ctx.reactVersion);
|
|
293
296
|
|
|
297
|
+
// Handle Deno import-map aliases (e.g. #deno-config) that only exist in
|
|
298
|
+
// the Deno runtime and cannot be resolved by esm.sh or the HTTP cache.
|
|
299
|
+
// We create a cached JS stub module so the transformed code can import it
|
|
300
|
+
// without losing access to imports/exports metadata from deno.json.
|
|
301
|
+
let denoConfigStubUrl: string | null = null;
|
|
302
|
+
if (transformed.includes('"#deno-config"') || transformed.includes("'#deno-config'")) {
|
|
303
|
+
const stubPath = await cacheTransformedCode(
|
|
304
|
+
DENO_CONFIG_STUB_CODE,
|
|
305
|
+
"#deno-config-stub",
|
|
306
|
+
ctx.fs,
|
|
307
|
+
);
|
|
308
|
+
denoConfigStubUrl = `file://${stubPath}`;
|
|
309
|
+
}
|
|
310
|
+
|
|
294
311
|
transformed = await replaceSpecifiers(transformed, (specifier) => {
|
|
312
|
+
// Handle Deno import-map aliases
|
|
313
|
+
if (specifier === "#deno-config") {
|
|
314
|
+
return denoConfigStubUrl;
|
|
315
|
+
}
|
|
316
|
+
|
|
295
317
|
// Handle #veryfront/ imports
|
|
296
318
|
if (specifier.startsWith("#veryfront/")) {
|
|
297
319
|
return veryfrontReplacements.get(specifier) ?? null;
|
|
@@ -26,6 +26,7 @@ const claudeCodeInputSchema = z.object({
|
|
|
26
26
|
/** Maximum turns */
|
|
27
27
|
maxTurns: z
|
|
28
28
|
.number()
|
|
29
|
+
.max(100)
|
|
29
30
|
.optional()
|
|
30
31
|
.default(20)
|
|
31
32
|
.describe("Maximum agentic loop turns"),
|
|
@@ -41,12 +42,6 @@ const claudeCodeInputSchema = z.object({
|
|
|
41
42
|
.record(z.unknown())
|
|
42
43
|
.optional()
|
|
43
44
|
.describe("Additional context to include in the prompt"),
|
|
44
|
-
|
|
45
|
-
/** Custom system prompt */
|
|
46
|
-
system: z
|
|
47
|
-
.string()
|
|
48
|
-
.optional()
|
|
49
|
-
.describe("Custom system prompt override"),
|
|
50
45
|
});
|
|
51
46
|
|
|
52
47
|
type ClaudeCodeInput = z.infer<typeof claudeCodeInputSchema>;
|
|
@@ -108,7 +103,6 @@ export const claudeCodeTool: Tool<ClaudeCodeInput, ClaudeCodeResult> = {
|
|
|
108
103
|
maxTurns: { type: "number", default: 20 },
|
|
109
104
|
files: { type: "array", items: { type: "string" } },
|
|
110
105
|
context: { type: "object" },
|
|
111
|
-
system: { type: "string" },
|
|
112
106
|
},
|
|
113
107
|
required: ["task"],
|
|
114
108
|
},
|
|
@@ -117,7 +111,6 @@ export const claudeCodeTool: Tool<ClaudeCodeInput, ClaudeCodeResult> = {
|
|
|
117
111
|
return executeAgent(buildPrompt(input), {
|
|
118
112
|
mode: input.mode as ClaudeCodeMode,
|
|
119
113
|
maxTurns: input.maxTurns,
|
|
120
|
-
systemPrompt: input.system,
|
|
121
114
|
debug: true,
|
|
122
115
|
});
|
|
123
116
|
},
|
|
@@ -140,15 +133,19 @@ export function createClaudeCodeTool(
|
|
|
140
133
|
id: options.id || claudeCodeTool.id,
|
|
141
134
|
description: options.description || claudeCodeTool.description,
|
|
142
135
|
|
|
143
|
-
execute: (input,
|
|
136
|
+
execute: (input, _context) => {
|
|
144
137
|
const mergedInput: ClaudeCodeInput = {
|
|
145
138
|
...input,
|
|
146
139
|
mode: input.mode || options.defaultMode || "code",
|
|
147
140
|
maxTurns: input.maxTurns || options.defaultMaxTurns || 20,
|
|
148
|
-
system: input.system || options.system,
|
|
149
141
|
};
|
|
150
142
|
|
|
151
|
-
return
|
|
143
|
+
return executeAgent(buildPrompt(mergedInput), {
|
|
144
|
+
mode: mergedInput.mode as ClaudeCodeMode,
|
|
145
|
+
maxTurns: mergedInput.maxTurns,
|
|
146
|
+
systemPrompt: options.system,
|
|
147
|
+
debug: true,
|
|
148
|
+
});
|
|
152
149
|
},
|
|
153
150
|
};
|
|
154
151
|
}
|