veryfront 0.1.62 → 0.1.64

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.
Files changed (73) hide show
  1. package/esm/cli/templates/manifest.js +37 -37
  2. package/esm/deno.d.ts +3 -0
  3. package/esm/deno.js +6 -3
  4. package/esm/src/agent/composition/composition.d.ts.map +1 -1
  5. package/esm/src/agent/composition/composition.js +13 -3
  6. package/esm/src/agent/factory.d.ts.map +1 -1
  7. package/esm/src/agent/factory.js +3 -3
  8. package/esm/src/agent/middleware/security/validator.d.ts +92 -0
  9. package/esm/src/agent/middleware/security/validator.d.ts.map +1 -0
  10. package/esm/src/agent/middleware/security/validator.js +187 -0
  11. package/esm/src/agent/runtime/index.d.ts +3 -2
  12. package/esm/src/agent/runtime/index.d.ts.map +1 -1
  13. package/esm/src/agent/runtime/index.js +16 -8
  14. package/esm/src/agent/types.d.ts +4 -0
  15. package/esm/src/agent/types.d.ts.map +1 -1
  16. package/esm/src/channels/invoke.d.ts +491 -0
  17. package/esm/src/channels/invoke.d.ts.map +1 -0
  18. package/esm/src/channels/invoke.js +417 -0
  19. package/esm/src/embedding/embedding.js +2 -2
  20. package/esm/src/integrations/endpoint-executor.d.ts +1 -0
  21. package/esm/src/integrations/endpoint-executor.d.ts.map +1 -1
  22. package/esm/src/integrations/endpoint-executor.js +44 -0
  23. package/esm/src/integrations/schema.d.ts +2 -2
  24. package/esm/src/oauth/handlers/init-handler.d.ts +6 -2
  25. package/esm/src/oauth/handlers/init-handler.d.ts.map +1 -1
  26. package/esm/src/oauth/handlers/init-handler.js +8 -2
  27. package/esm/src/platform/compat/opaque-deps.d.ts.map +1 -1
  28. package/esm/src/platform/compat/opaque-deps.js +10 -1
  29. package/esm/src/prompt/factory.d.ts.map +1 -1
  30. package/esm/src/prompt/factory.js +9 -1
  31. package/esm/src/react/components/ai/markdown.d.ts.map +1 -1
  32. package/esm/src/react/components/ai/markdown.js +4 -4
  33. package/esm/src/server/handlers/dev/framework-candidates.generated.d.ts.map +1 -1
  34. package/esm/src/server/handlers/dev/framework-candidates.generated.js +5 -4
  35. package/esm/src/server/handlers/preview/markdown-html-generator.js +1 -1
  36. package/esm/src/server/handlers/request/api/api-handler-wrapper.d.ts.map +1 -1
  37. package/esm/src/server/handlers/request/api/api-handler-wrapper.js +1 -74
  38. package/esm/src/server/handlers/request/api/project-discovery.d.ts +9 -0
  39. package/esm/src/server/handlers/request/api/project-discovery.d.ts.map +1 -0
  40. package/esm/src/server/handlers/request/api/project-discovery.js +74 -0
  41. package/esm/src/server/handlers/request/channel-assistants.handler.d.ts +11 -0
  42. package/esm/src/server/handlers/request/channel-assistants.handler.d.ts.map +1 -0
  43. package/esm/src/server/handlers/request/channel-assistants.handler.js +71 -0
  44. package/esm/src/server/handlers/request/channel-invoke.handler.d.ts +11 -0
  45. package/esm/src/server/handlers/request/channel-invoke.handler.d.ts.map +1 -0
  46. package/esm/src/server/handlers/request/channel-invoke.handler.js +72 -0
  47. package/esm/src/server/runtime-handler/index.d.ts.map +1 -1
  48. package/esm/src/server/runtime-handler/index.js +4 -0
  49. package/esm/src/transforms/md/compiler/md-compiler.d.ts.map +1 -1
  50. package/esm/src/transforms/md/compiler/md-compiler.js +25 -1
  51. package/package.json +3 -1
  52. package/src/cli/templates/manifest.js +37 -37
  53. package/src/deno.js +6 -3
  54. package/src/src/agent/composition/composition.ts +15 -3
  55. package/src/src/agent/factory.ts +19 -6
  56. package/src/src/agent/middleware/security/validator.ts +288 -0
  57. package/src/src/agent/runtime/index.ts +26 -3
  58. package/src/src/agent/types.ts +4 -0
  59. package/src/src/channels/invoke.ts +546 -0
  60. package/src/src/embedding/embedding.ts +2 -2
  61. package/src/src/integrations/endpoint-executor.ts +51 -0
  62. package/src/src/oauth/handlers/init-handler.ts +20 -5
  63. package/src/src/platform/compat/opaque-deps.ts +19 -4
  64. package/src/src/prompt/factory.ts +10 -1
  65. package/src/src/react/components/ai/markdown.tsx +5 -4
  66. package/src/src/server/handlers/dev/framework-candidates.generated.ts +5 -4
  67. package/src/src/server/handlers/preview/markdown-html-generator.ts +1 -1
  68. package/src/src/server/handlers/request/api/api-handler-wrapper.ts +1 -85
  69. package/src/src/server/handlers/request/api/project-discovery.ts +86 -0
  70. package/src/src/server/handlers/request/channel-assistants.handler.ts +94 -0
  71. package/src/src/server/handlers/request/channel-invoke.handler.ts +95 -0
  72. package/src/src/server/runtime-handler/index.ts +4 -0
  73. package/src/src/transforms/md/compiler/md-compiler.ts +27 -1
@@ -1 +1 @@
1
- {"version":3,"file":"framework-candidates.generated.d.ts","sourceRoot":"","sources":["../../../../../src/src/server/handlers/dev/framework-candidates.generated.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,eAAO,MAAM,oBAAoB,EAAE,SAAS,MAAM,EAkkKjD,CAAC"}
1
+ {"version":3,"file":"framework-candidates.generated.d.ts","sourceRoot":"","sources":["../../../../../src/src/server/handlers/dev/framework-candidates.generated.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,eAAO,MAAM,oBAAoB,EAAE,SAAS,MAAM,EAmkKjD,CAAC"}
@@ -3058,10 +3058,10 @@ export const FRAMEWORK_CANDIDATES = [
3058
3058
  "html:",
3059
3059
  "html>",
3060
3060
  "https://ai-sdk.dev/elements)",
3061
- "https://esm.sh/mermaid@11",
3062
- "https://esm.sh/react-markdown@9?external=react",
3063
- "https://esm.sh/rehype-highlight@7?target=es2022",
3064
- "https://esm.sh/remark-gfm@4?target=es2022",
3061
+ "https://esm.sh/mermaid@11.4.1?pin=v135",
3062
+ "https://esm.sh/react-markdown@9.0.3?external=react",
3063
+ "https://esm.sh/rehype-highlight@7.0.2?target=es2022",
3064
+ "https://esm.sh/remark-gfm@4.0.1?target=es2022",
3065
3065
  "hydration",
3066
3066
  "i)",
3067
3067
  "icon",
@@ -4006,6 +4006,7 @@ export const FRAMEWORK_CANDIDATES = [
4006
4006
  "persistThreads],",
4007
4007
  "pickers,",
4008
4008
  "pill",
4009
+ "pin=v135",
4009
4010
  "pl-2",
4010
4011
  "pl-2.5",
4011
4012
  "pl-3",
@@ -76,7 +76,7 @@ export function generateMarkdownHtml(options) {
76
76
  ${studioScript}
77
77
 
78
78
  <script type="module">
79
- import mermaid from 'https://esm.sh/mermaid@11';
79
+ import mermaid from 'https://esm.sh/mermaid@11.4.1?pin=v135';
80
80
 
81
81
  function getMermaidTheme() {
82
82
  return document.documentElement.dataset.theme === 'dark' ? 'dark' : 'default';
@@ -1 +1 @@
1
- {"version":3,"file":"api-handler-wrapper.d.ts","sourceRoot":"","sources":["../../../../../../src/src/server/handlers/request/api/api-handler-wrapper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,8BAA8B,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,KAAK,EACV,cAAc,EACd,eAAe,EAEf,aAAa,EACd,MAAM,gBAAgB,CAAC;AAqGxB,qBAAa,iBAAkB,SAAQ,WAAW;IAChD,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,OAAO,CAAiE;IAChF,OAAO,CAAC,WAAW,CAA8B;IAEjD,QAAQ,EAAE,eAAe,CAGvB;gBAGA,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,OAAO,uCAAuC,EAAE,cAAc;IAOnE,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAW3B,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;IA6C/E,OAAO,CAAC,iBAAiB;CA4D1B"}
1
+ {"version":3,"file":"api-handler-wrapper.d.ts","sourceRoot":"","sources":["../../../../../../src/src/server/handlers/request/api/api-handler-wrapper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,8BAA8B,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,KAAK,EACV,cAAc,EACd,eAAe,EAEf,aAAa,EACd,MAAM,gBAAgB,CAAC;AAiBxB,qBAAa,iBAAkB,SAAQ,WAAW;IAChD,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,OAAO,CAAiE;IAChF,OAAO,CAAC,WAAW,CAA8B;IAEjD,QAAQ,EAAE,eAAe,CAGvB;gBAGA,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,OAAO,uCAAuC,EAAE,cAAc;IAOnE,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAW3B,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;IA6C/E,OAAO,CAAC,iBAAiB;CA4D1B"}
@@ -2,80 +2,7 @@ import { BaseHandler } from "../../response/base.js";
2
2
  import { getApiHandler } from "./pages-api-handler.js";
3
3
  import { PRIORITY_MEDIUM_API } from "../../../../utils/constants/index.js";
4
4
  import { withSpan } from "../../../../observability/tracing/otlp-setup.js";
5
- import { serverLogger } from "../../../../utils/index.js";
6
- const logger = serverLogger.component("api-wrapper");
7
- /**
8
- * Tracks in-flight and completed AI discovery per project+release.
9
- *
10
- * Key: `{projectSlug}:{releaseId}` for production, `{projectSlug}:preview` for preview.
11
- * This ensures a new deployment triggers re-discovery of agents/tools.
12
- *
13
- * Using a Map<string, Promise> deduplicates concurrent requests and
14
- * allows retry on failure (the key is deleted if discovery rejects).
15
- */
16
- const discoveredProjects = new Map();
17
- /** Build a discovery cache key that incorporates the release/version. */
18
- function discoveryKey(ctx) {
19
- const slug = ctx.projectSlug ?? ctx.projectDir;
20
- const version = ctx.releaseId ?? "preview";
21
- return `${slug}:${version}`;
22
- }
23
- /**
24
- * Run AI discovery (agents, tools) for a project if not already done.
25
- * Must be called within a runWithContext scope so the VFS can resolve
26
- * the correct remote project files and the agent registry uses the
27
- * correct project scope.
28
- */
29
- async function ensureProjectDiscovery(ctx) {
30
- const key = discoveryKey(ctx);
31
- const existing = discoveredProjects.get(key);
32
- if (existing)
33
- return existing;
34
- const promise = (async () => {
35
- const { discoverAll } = await import("../../../../discovery/index.js");
36
- const { agentRegistry } = await import("../../../../agent/composition/composition.js");
37
- const { toolRegistry } = await import("../../../../tool/registry.js");
38
- // Clear stale entries for this project scope before re-discovery.
39
- // This prevents agents/tools removed in a new release from lingering.
40
- agentRegistry.clear();
41
- toolRegistry.clear();
42
- const result = await discoverAll({
43
- baseDir: ctx.projectDir,
44
- fsAdapter: ctx.adapter.fs,
45
- verbose: false,
46
- });
47
- const logData = {
48
- projectSlug: ctx.projectSlug,
49
- releaseId: ctx.releaseId,
50
- agents: result.agents.size,
51
- tools: result.tools.size,
52
- errors: result.errors.length,
53
- };
54
- if (result.agents.size === 0 && result.tools.size === 0) {
55
- logger.warn("AI discovery found 0 agents and 0 tools", {
56
- ...logData,
57
- errorMessages: result.errors.map((e) => e.error.message).slice(0, 5),
58
- baseDir: ctx.projectDir,
59
- });
60
- }
61
- else {
62
- logger.info("AI discovery completed", logData);
63
- }
64
- })();
65
- discoveredProjects.set(key, promise);
66
- try {
67
- await promise;
68
- }
69
- catch (error) {
70
- // Allow retry on next request
71
- discoveredProjects.delete(key);
72
- logger.warn("AI discovery failed (will retry)", {
73
- projectSlug: ctx.projectSlug,
74
- error: error instanceof Error ? error.message : String(error),
75
- stack: error instanceof Error ? error.stack : undefined,
76
- });
77
- }
78
- }
5
+ import { ensureProjectDiscovery } from "./project-discovery.js";
79
6
  export class ApiHandlerWrapper extends BaseHandler {
80
7
  projectDir;
81
8
  adapter;
@@ -0,0 +1,9 @@
1
+ import type { HandlerContext } from "../../types.js";
2
+ /**
3
+ * Run AI discovery (agents, tools) for a project if not already done.
4
+ * Must be called within a runWithContext scope so the VFS can resolve
5
+ * the correct remote project files and the agent registry uses the
6
+ * correct project scope.
7
+ */
8
+ export declare function ensureProjectDiscovery(ctx: HandlerContext): Promise<void>;
9
+ //# sourceMappingURL=project-discovery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-discovery.d.ts","sourceRoot":"","sources":["../../../../../../src/src/server/handlers/request/api/project-discovery.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAsBrD;;;;;GAKG;AACH,wBAAsB,sBAAsB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAwD/E"}
@@ -0,0 +1,74 @@
1
+ import { serverLogger } from "../../../../utils/index.js";
2
+ const logger = serverLogger.component("api-wrapper");
3
+ /**
4
+ * Tracks in-flight and completed AI discovery per project+release.
5
+ *
6
+ * Key: `{projectSlug}:{releaseId}` for production, `{projectSlug}:preview` for preview.
7
+ * This ensures a new deployment triggers re-discovery of agents/tools.
8
+ *
9
+ * Using a Map<string, Promise> deduplicates concurrent requests and
10
+ * allows retry on failure (the key is deleted if discovery rejects).
11
+ */
12
+ const discoveredProjects = new Map();
13
+ /** Build a discovery cache key that incorporates the release/version. */
14
+ function discoveryKey(ctx) {
15
+ const slug = ctx.projectSlug ?? ctx.projectDir;
16
+ const version = ctx.releaseId ?? "preview";
17
+ return `${slug}:${version}`;
18
+ }
19
+ /**
20
+ * Run AI discovery (agents, tools) for a project if not already done.
21
+ * Must be called within a runWithContext scope so the VFS can resolve
22
+ * the correct remote project files and the agent registry uses the
23
+ * correct project scope.
24
+ */
25
+ export async function ensureProjectDiscovery(ctx) {
26
+ const key = discoveryKey(ctx);
27
+ const existing = discoveredProjects.get(key);
28
+ if (existing)
29
+ return existing;
30
+ const promise = (async () => {
31
+ const { discoverAll } = await import("../../../../discovery/index.js");
32
+ const { agentRegistry } = await import("../../../../agent/composition/composition.js");
33
+ const { toolRegistry } = await import("../../../../tool/registry.js");
34
+ // Clear stale entries for this project scope before re-discovery.
35
+ // This prevents agents/tools removed in a new release from lingering.
36
+ agentRegistry.clear();
37
+ toolRegistry.clear();
38
+ const result = await discoverAll({
39
+ baseDir: ctx.projectDir,
40
+ fsAdapter: ctx.adapter.fs,
41
+ verbose: false,
42
+ });
43
+ const logData = {
44
+ projectSlug: ctx.projectSlug,
45
+ releaseId: ctx.releaseId,
46
+ agents: result.agents.size,
47
+ tools: result.tools.size,
48
+ errors: result.errors.length,
49
+ };
50
+ if (result.agents.size === 0 && result.tools.size === 0) {
51
+ logger.warn("AI discovery found 0 agents and 0 tools", {
52
+ ...logData,
53
+ errorMessages: result.errors.map((e) => e.error.message).slice(0, 5),
54
+ baseDir: ctx.projectDir,
55
+ });
56
+ }
57
+ else {
58
+ logger.info("AI discovery completed", logData);
59
+ }
60
+ })();
61
+ discoveredProjects.set(key, promise);
62
+ try {
63
+ await promise;
64
+ }
65
+ catch (error) {
66
+ // Allow retry on next request
67
+ discoveredProjects.delete(key);
68
+ logger.warn("AI discovery failed (will retry)", {
69
+ projectSlug: ctx.projectSlug,
70
+ error: error instanceof Error ? error.message : String(error),
71
+ stack: error instanceof Error ? error.stack : undefined,
72
+ });
73
+ }
74
+ }
@@ -0,0 +1,11 @@
1
+ import * as dntShim from "../../../../_dnt.shims.js";
2
+ import { BaseHandler } from "../response/base.js";
3
+ import type { HandlerContext, HandlerMetadata, HandlerResult } from "../types.js";
4
+ import { type ChannelInvokeDeps } from "../../../channels/invoke.js";
5
+ export declare class ChannelAssistantsHandler extends BaseHandler {
6
+ private readonly deps;
7
+ metadata: HandlerMetadata;
8
+ constructor(deps?: ChannelInvokeDeps);
9
+ handle(req: dntShim.Request, ctx: HandlerContext): Promise<HandlerResult>;
10
+ }
11
+ //# sourceMappingURL=channel-assistants.handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"channel-assistants.handler.d.ts","sourceRoot":"","sources":["../../../../../src/src/server/handlers/request/channel-assistants.handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,2BAA2B,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAmB,aAAa,EAAE,MAAM,aAAa,CAAC;AACnG,OAAO,EAEL,KAAK,iBAAiB,EAIvB,MAAM,6BAA6B,CAAC;AASrC,qBAAa,wBAAyB,SAAQ,WAAW;IAO3C,OAAO,CAAC,QAAQ,CAAC,IAAI;IANjC,QAAQ,EAAE,eAAe,CAIvB;gBAE2B,IAAI,GAAE,iBAA4C;IAIzE,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;CAgEhF"}
@@ -0,0 +1,71 @@
1
+ import { BaseHandler } from "../response/base.js";
2
+ import { ChannelAssistantsRequestSchema, defaultChannelInvokeDeps, listChannelAssistants, verifyDispatchJws, } from "../../../channels/invoke.js";
3
+ import { HTTP_INTERNAL_SERVER_ERROR, PRIORITY_MEDIUM_API, } from "../../../utils/constants/index.js";
4
+ const DISPATCH_JWS_HEADER = "x-veryfront-dispatch-jws";
5
+ const MAX_DISPATCH_SIGNATURE_AGE_SECONDS = 60;
6
+ export class ChannelAssistantsHandler extends BaseHandler {
7
+ deps;
8
+ metadata = {
9
+ name: "ChannelAssistantsHandler",
10
+ priority: PRIORITY_MEDIUM_API,
11
+ patterns: [{ pattern: "/channels/assistants", exact: true, method: "POST" }],
12
+ };
13
+ constructor(deps = defaultChannelInvokeDeps) {
14
+ super();
15
+ this.deps = deps;
16
+ }
17
+ async handle(req, ctx) {
18
+ if (!this.shouldHandle(req, ctx)) {
19
+ return this.continue();
20
+ }
21
+ return this.withProxyContext(ctx, async () => {
22
+ const builder = this.createResponseBuilder(ctx)
23
+ .withCORS(req, ctx.securityConfig?.cors)
24
+ .withSecurity(ctx.securityConfig ?? undefined, req);
25
+ const publicKeyPem = ctx.adapter.env.get("CHANNEL_DISPATCH_SIGNING_PUBLIC_KEY");
26
+ if (!publicKeyPem) {
27
+ this.logWarn("Missing CHANNEL_DISPATCH_SIGNING_PUBLIC_KEY for channel assistants endpoint");
28
+ return this.respond(builder.json({ error: "Channel dispatch verification is not configured" }, HTTP_INTERNAL_SERVER_ERROR));
29
+ }
30
+ const projectSlug = ctx.projectSlug;
31
+ if (!projectSlug) {
32
+ this.logWarn("Channel assistants request arrived without resolved project slug");
33
+ return this.respond(builder.json({ error: "Project context is unavailable" }, 400));
34
+ }
35
+ const dispatchJws = req.headers.get(DISPATCH_JWS_HEADER);
36
+ if (!dispatchJws) {
37
+ return this.respond(builder.json({ error: "Missing dispatch signature" }, 401));
38
+ }
39
+ const rawBody = await req.text();
40
+ try {
41
+ await verifyDispatchJws(dispatchJws, rawBody, {
42
+ audience: projectSlug,
43
+ expectedProjectId: ctx.projectId,
44
+ publicKeyPem,
45
+ maxAgeSeconds: MAX_DISPATCH_SIGNATURE_AGE_SECONDS,
46
+ });
47
+ }
48
+ catch (error) {
49
+ this.logWarn("Channel assistants signature verification failed", {
50
+ error: error instanceof Error ? error.message : String(error),
51
+ projectSlug,
52
+ projectId: ctx.projectId,
53
+ });
54
+ return this.respond(builder.json({ error: "Invalid dispatch signature" }, 401));
55
+ }
56
+ try {
57
+ ChannelAssistantsRequestSchema.parse(JSON.parse(rawBody));
58
+ }
59
+ catch (error) {
60
+ this.logWarn("Channel assistants request validation failed", {
61
+ error: error instanceof Error ? error.message : String(error),
62
+ projectSlug,
63
+ projectId: ctx.projectId,
64
+ });
65
+ return this.respond(builder.json({ error: "Invalid channel assistants request" }, 400));
66
+ }
67
+ const response = await listChannelAssistants(ctx, this.deps);
68
+ return this.respond(builder.json(response, 200));
69
+ });
70
+ }
71
+ }
@@ -0,0 +1,11 @@
1
+ import * as dntShim from "../../../../_dnt.shims.js";
2
+ import { BaseHandler } from "../response/base.js";
3
+ import type { HandlerContext, HandlerMetadata, HandlerResult } from "../types.js";
4
+ import { type ChannelInvokeDeps } from "../../../channels/invoke.js";
5
+ export declare class ChannelInvokeHandler extends BaseHandler {
6
+ private readonly deps;
7
+ metadata: HandlerMetadata;
8
+ constructor(deps?: ChannelInvokeDeps);
9
+ handle(req: dntShim.Request, ctx: HandlerContext): Promise<HandlerResult>;
10
+ }
11
+ //# sourceMappingURL=channel-invoke.handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"channel-invoke.handler.d.ts","sourceRoot":"","sources":["../../../../../src/src/server/handlers/request/channel-invoke.handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,2BAA2B,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAmB,aAAa,EAAE,MAAM,aAAa,CAAC;AACnG,OAAO,EACL,KAAK,iBAAiB,EAKvB,MAAM,6BAA6B,CAAC;AASrC,qBAAa,oBAAqB,SAAQ,WAAW;IAOvC,OAAO,CAAC,QAAQ,CAAC,IAAI;IANjC,QAAQ,EAAE,eAAe,CAIvB;gBAE2B,IAAI,GAAE,iBAA4C;IAIzE,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;CAiEhF"}
@@ -0,0 +1,72 @@
1
+ import { BaseHandler } from "../response/base.js";
2
+ import { ChannelInvokeRequestSchema, defaultChannelInvokeDeps, executeChannelInvoke, verifyDispatchJws, } from "../../../channels/invoke.js";
3
+ import { HTTP_INTERNAL_SERVER_ERROR, PRIORITY_MEDIUM_API, } from "../../../utils/constants/index.js";
4
+ const DISPATCH_JWS_HEADER = "x-veryfront-dispatch-jws";
5
+ const MAX_DISPATCH_SIGNATURE_AGE_SECONDS = 60;
6
+ export class ChannelInvokeHandler extends BaseHandler {
7
+ deps;
8
+ metadata = {
9
+ name: "ChannelInvokeHandler",
10
+ priority: PRIORITY_MEDIUM_API,
11
+ patterns: [{ pattern: "/channels/invoke", exact: true, method: "POST" }],
12
+ };
13
+ constructor(deps = defaultChannelInvokeDeps) {
14
+ super();
15
+ this.deps = deps;
16
+ }
17
+ async handle(req, ctx) {
18
+ if (!this.shouldHandle(req, ctx)) {
19
+ return this.continue();
20
+ }
21
+ return this.withProxyContext(ctx, async () => {
22
+ const builder = this.createResponseBuilder(ctx)
23
+ .withCORS(req, ctx.securityConfig?.cors)
24
+ .withSecurity(ctx.securityConfig ?? undefined, req);
25
+ const publicKeyPem = ctx.adapter.env.get("CHANNEL_DISPATCH_SIGNING_PUBLIC_KEY");
26
+ if (!publicKeyPem) {
27
+ this.logWarn("Missing CHANNEL_DISPATCH_SIGNING_PUBLIC_KEY for channel invoke endpoint");
28
+ return this.respond(builder.json({ error: "Channel dispatch verification is not configured" }, HTTP_INTERNAL_SERVER_ERROR));
29
+ }
30
+ const projectSlug = ctx.projectSlug;
31
+ if (!projectSlug) {
32
+ this.logWarn("Channel invoke request arrived without resolved project slug");
33
+ return this.respond(builder.json({ error: "Project context is unavailable" }, 400));
34
+ }
35
+ const dispatchJws = req.headers.get(DISPATCH_JWS_HEADER);
36
+ if (!dispatchJws) {
37
+ return this.respond(builder.json({ error: "Missing dispatch signature" }, 401));
38
+ }
39
+ const rawBody = await req.text();
40
+ try {
41
+ await verifyDispatchJws(dispatchJws, rawBody, {
42
+ audience: projectSlug,
43
+ expectedProjectId: ctx.projectId,
44
+ publicKeyPem,
45
+ maxAgeSeconds: MAX_DISPATCH_SIGNATURE_AGE_SECONDS,
46
+ });
47
+ }
48
+ catch (error) {
49
+ this.logWarn("Channel invoke signature verification failed", {
50
+ error: error instanceof Error ? error.message : String(error),
51
+ projectSlug,
52
+ projectId: ctx.projectId,
53
+ });
54
+ return this.respond(builder.json({ error: "Invalid dispatch signature" }, 401));
55
+ }
56
+ let payload;
57
+ try {
58
+ payload = ChannelInvokeRequestSchema.parse(JSON.parse(rawBody));
59
+ }
60
+ catch (error) {
61
+ this.logWarn("Channel invoke request validation failed", {
62
+ error: error instanceof Error ? error.message : String(error),
63
+ projectSlug,
64
+ projectId: ctx.projectId,
65
+ });
66
+ return this.respond(builder.json({ error: "Invalid channel invoke request" }, 400));
67
+ }
68
+ const response = await executeChannelInvoke(payload, ctx, this.deps);
69
+ return this.respond(builder.json(response, 200));
70
+ });
71
+ }
72
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/src/server/runtime-handler/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,OAAO,MAAM,wBAAwB,CAAC;AAQlD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAwF7D,OAAO,EAAE,qBAAqB,EAAE,KAAK,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAMtF,MAAM,WAAW,qBAAqB;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,kDAAkD;IAClD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,wEAAwE;IACxE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,0DAA0D;IAC1D,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB,oFAAoF;IACpF,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,sFAAsF;IACtF,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,oFAAoF;IACpF,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,uGAAuG;IACvG,kBAAkB,CAAC,EAAE,SAAS,GAAG,YAAY,CAAC;CAC/C;AAED,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,cAAc,EACvB,IAAI,GAAE,qBAAsC,GAC3C,CAAC,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,GAAG;IAAE,KAAK,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,CAAA;CAAE,CAuanF;AAGD,YAAY,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAChE,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/src/server/runtime-handler/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,OAAO,MAAM,wBAAwB,CAAC;AAQlD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AA0F7D,OAAO,EAAE,qBAAqB,EAAE,KAAK,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAMtF,MAAM,WAAW,qBAAqB;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,kDAAkD;IAClD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,wEAAwE;IACxE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,0DAA0D;IAC1D,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB,oFAAoF;IACpF,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,sFAAsF;IACtF,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,oFAAoF;IACpF,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,uGAAuG;IACvG,kBAAkB,CAAC,EAAE,SAAS,GAAG,YAAY,CAAC;CAC/C;AAED,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,cAAc,EACvB,IAAI,GAAE,qBAAsC,GAC3C,CAAC,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,GAAG;IAAE,KAAK,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,CAAA;CAAE,CAyanF;AAGD,YAAY,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAChE,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC"}
@@ -42,6 +42,8 @@ import { HMRHandler } from "../handlers/preview/hmr.handler.js";
42
42
  import { MarkdownPreviewHandler } from "../handlers/preview/markdown-preview.handler.js";
43
43
  import { OpenAPIHandler } from "../handlers/request/openapi.handler.js";
44
44
  import { OpenAPIDocsHandler } from "../handlers/request/openapi-docs.handler.js";
45
+ import { ChannelAssistantsHandler } from "../handlers/request/channel-assistants.handler.js";
46
+ import { ChannelInvokeHandler } from "../handlers/request/channel-invoke.handler.js";
45
47
  import { DevDashboardHandler } from "../handlers/dev/dashboard/index.js";
46
48
  import { ProjectsHandler } from "../handlers/dev/projects/index.js";
47
49
  // Extracted modules
@@ -123,6 +125,8 @@ export function createVeryfrontHandler(projectDir, adapter, opts = { projectDir
123
125
  new DebugContextHandler(),
124
126
  new OpenAPIHandler(),
125
127
  new OpenAPIDocsHandler(),
128
+ new ChannelAssistantsHandler(),
129
+ new ChannelInvokeHandler(),
126
130
  new DevDashboardHandler(),
127
131
  new ProjectsHandler(),
128
132
  new StudioBridgeModulesHandler(),
@@ -1 +1 @@
1
- {"version":3,"file":"md-compiler.d.ts","sourceRoot":"","sources":["../../../../../src/src/transforms/md/compiler/md-compiler.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EACV,eAAe,EACf,iBAAiB,EACjB,gBAAgB,EACjB,MAAM,6BAA6B,CAAC;AAoDrC,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,eAAe,EACtB,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EACf,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACrC,QAAQ,CAAC,EAAE,MAAM,EACjB,OAAO,GAAE,iBAA4B,EACrC,QAAQ,CAAC,EAAE,MAAM,EACjB,WAAW,CAAC,EAAE,OAAO,GACpB,OAAO,CAAC,gBAAgB,CAAC,CA2E3B"}
1
+ {"version":3,"file":"md-compiler.d.ts","sourceRoot":"","sources":["../../../../../src/src/transforms/md/compiler/md-compiler.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EACV,eAAe,EACf,iBAAiB,EACjB,gBAAgB,EACjB,MAAM,6BAA6B,CAAC;AAoDrC,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,eAAe,EACtB,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EACf,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACrC,QAAQ,CAAC,EAAE,MAAM,EACjB,OAAO,GAAE,iBAA4B,EACrC,QAAQ,CAAC,EAAE,MAAM,EACjB,WAAW,CAAC,EAAE,OAAO,GACpB,OAAO,CAAC,gBAAgB,CAAC,CAmG3B"}
@@ -5,6 +5,8 @@ import remarkFrontmatter from "remark-frontmatter";
5
5
  import remarkRehype from "remark-rehype";
6
6
  import rehypeStarryNight from "rehype-starry-night";
7
7
  import rehypeSlug from "rehype-slug";
8
+ import rehypeRaw from "rehype-raw";
9
+ import rehypeSanitize, { defaultSchema } from "rehype-sanitize";
8
10
  import rehypeStringify from "rehype-stringify";
9
11
  import { visit } from "unist-util-visit";
10
12
  import { toString } from "mdast-util-to-string";
@@ -62,11 +64,33 @@ export function compileMarkdownRuntime(_mode, _projectDir, content, frontmatter,
62
64
  .use(remarkRehype, { allowDangerousHtml: true })
63
65
  .use(rehypeStarryNight)
64
66
  .use(rehypeSlug);
67
+ // Parse raw HTML nodes into proper elements before sanitizing.
68
+ pipeline.use(rehypeRaw);
69
+ // Add node positions after rehype-raw so attributes survive re-parsing.
65
70
  if (studioEmbed && filePath) {
66
71
  pipeline.use(rehypeNodePositions, { filePath });
67
72
  }
73
+ // Extend the sanitize schema in studio embed mode to preserve
74
+ // data-node-* attributes used for element-to-source mapping.
75
+ const sanitizeSchema = studioEmbed
76
+ ? {
77
+ ...defaultSchema,
78
+ attributes: {
79
+ ...defaultSchema.attributes,
80
+ "*": [
81
+ ...(defaultSchema.attributes?.["*"] ?? []),
82
+ "data-node-file",
83
+ "data-node-name",
84
+ "data-node-line",
85
+ "data-node-column",
86
+ "data-node-source",
87
+ ],
88
+ },
89
+ }
90
+ : defaultSchema;
68
91
  const result = await pipeline
69
- .use(rehypeStringify, { allowDangerousHtml: true })
92
+ .use(rehypeSanitize, sanitizeSchema)
93
+ .use(rehypeStringify)
70
94
  .process(body);
71
95
  const html = String(result);
72
96
  logger.debug("Compiled markdown:", {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "veryfront",
3
- "version": "0.1.62",
3
+ "version": "0.1.64",
4
4
  "description": "The simplest way to build AI-powered apps",
5
5
  "keywords": [
6
6
  "react",
@@ -151,6 +151,8 @@
151
151
  "react-dom": "19.1.1",
152
152
  "redis": "4.6.13",
153
153
  "rehype-highlight": "7.0.2",
154
+ "rehype-raw": "7.0.0",
155
+ "rehype-sanitize": "6.0.0",
154
156
  "rehype-slug": "6.0.0",
155
157
  "rehype-starry-night": "2.2.0",
156
158
  "rehype-stringify": "10.0.1",