veryfront 0.1.13 → 0.1.15

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 (153) hide show
  1. package/esm/cli/app/data/slug-words.d.ts.map +1 -1
  2. package/esm/cli/app/data/slug-words.js +225 -90
  3. package/esm/cli/app/operations/project-creation.js +4 -3
  4. package/esm/cli/app/shell.js +1 -1
  5. package/esm/cli/app/utils.d.ts +5 -4
  6. package/esm/cli/app/utils.d.ts.map +1 -1
  7. package/esm/cli/app/utils.js +0 -23
  8. package/esm/cli/app/views/dashboard.d.ts +1 -1
  9. package/esm/cli/app/views/dashboard.d.ts.map +1 -1
  10. package/esm/cli/app/views/dashboard.js +22 -4
  11. package/esm/cli/auth/callback-server.d.ts.map +1 -1
  12. package/esm/cli/auth/callback-server.js +3 -2
  13. package/esm/cli/commands/dev/handler.d.ts.map +1 -1
  14. package/esm/cli/commands/dev/handler.js +2 -0
  15. package/esm/cli/commands/init/init-command.d.ts.map +1 -1
  16. package/esm/cli/commands/init/init-command.js +20 -3
  17. package/esm/cli/commands/init/interactive-wizard.d.ts +3 -2
  18. package/esm/cli/commands/init/interactive-wizard.d.ts.map +1 -1
  19. package/esm/cli/commands/init/interactive-wizard.js +55 -27
  20. package/esm/cli/mcp/remote-file-tools.d.ts +0 -6
  21. package/esm/cli/mcp/remote-file-tools.d.ts.map +1 -1
  22. package/esm/cli/mcp/remote-file-tools.js +37 -15
  23. package/esm/cli/shared/reserve-slug.d.ts.map +1 -1
  24. package/esm/cli/shared/reserve-slug.js +8 -3
  25. package/esm/cli/utils/env-prompt.d.ts.map +1 -1
  26. package/esm/cli/utils/env-prompt.js +3 -0
  27. package/esm/deno.d.ts +5 -1
  28. package/esm/deno.js +11 -4
  29. package/esm/src/agent/chat-handler.d.ts +4 -3
  30. package/esm/src/agent/chat-handler.d.ts.map +1 -1
  31. package/esm/src/agent/chat-handler.js +55 -4
  32. package/esm/src/agent/react/index.d.ts +1 -1
  33. package/esm/src/agent/react/index.d.ts.map +1 -1
  34. package/esm/src/agent/react/use-chat/browser-inference/browser-engine.d.ts +18 -0
  35. package/esm/src/agent/react/use-chat/browser-inference/browser-engine.d.ts.map +1 -0
  36. package/esm/src/agent/react/use-chat/browser-inference/browser-engine.js +54 -0
  37. package/esm/src/agent/react/use-chat/browser-inference/types.d.ts +43 -0
  38. package/esm/src/agent/react/use-chat/browser-inference/types.d.ts.map +1 -0
  39. package/esm/src/agent/react/use-chat/browser-inference/types.js +4 -0
  40. package/esm/src/agent/react/use-chat/browser-inference/worker-client.d.ts +23 -0
  41. package/esm/src/agent/react/use-chat/browser-inference/worker-client.d.ts.map +1 -0
  42. package/esm/src/agent/react/use-chat/browser-inference/worker-client.js +67 -0
  43. package/esm/src/agent/react/use-chat/browser-inference/worker-script.d.ts +8 -0
  44. package/esm/src/agent/react/use-chat/browser-inference/worker-script.d.ts.map +1 -0
  45. package/esm/src/agent/react/use-chat/browser-inference/worker-script.js +97 -0
  46. package/esm/src/agent/react/use-chat/index.d.ts +1 -1
  47. package/esm/src/agent/react/use-chat/index.d.ts.map +1 -1
  48. package/esm/src/agent/react/use-chat/types.d.ts +12 -0
  49. package/esm/src/agent/react/use-chat/types.d.ts.map +1 -1
  50. package/esm/src/agent/react/use-chat/use-chat.d.ts.map +1 -1
  51. package/esm/src/agent/react/use-chat/use-chat.js +120 -6
  52. package/esm/src/agent/runtime/index.d.ts.map +1 -1
  53. package/esm/src/agent/runtime/index.js +59 -7
  54. package/esm/src/build/production-build/templates.d.ts +2 -2
  55. package/esm/src/build/production-build/templates.d.ts.map +1 -1
  56. package/esm/src/build/production-build/templates.js +2 -68
  57. package/esm/src/chat/index.d.ts +1 -1
  58. package/esm/src/chat/index.d.ts.map +1 -1
  59. package/esm/src/errors/veryfront-error.d.ts +3 -0
  60. package/esm/src/errors/veryfront-error.d.ts.map +1 -1
  61. package/esm/src/platform/adapters/runtime/deno/adapter.d.ts.map +1 -1
  62. package/esm/src/platform/adapters/runtime/deno/adapter.js +24 -3
  63. package/esm/src/platform/compat/http/deno-server.d.ts.map +1 -1
  64. package/esm/src/platform/compat/http/deno-server.js +23 -2
  65. package/esm/src/provider/index.d.ts +1 -1
  66. package/esm/src/provider/index.d.ts.map +1 -1
  67. package/esm/src/provider/index.js +1 -1
  68. package/esm/src/provider/local/ai-sdk-adapter.d.ts +19 -0
  69. package/esm/src/provider/local/ai-sdk-adapter.d.ts.map +1 -0
  70. package/esm/src/provider/local/ai-sdk-adapter.js +164 -0
  71. package/esm/src/provider/local/env.d.ts +10 -0
  72. package/esm/src/provider/local/env.d.ts.map +1 -0
  73. package/esm/src/provider/local/env.js +23 -0
  74. package/esm/src/provider/local/local-engine.d.ts +61 -0
  75. package/esm/src/provider/local/local-engine.d.ts.map +1 -0
  76. package/esm/src/provider/local/local-engine.js +211 -0
  77. package/esm/src/provider/local/model-catalog.d.ts +30 -0
  78. package/esm/src/provider/local/model-catalog.d.ts.map +1 -0
  79. package/esm/src/provider/local/model-catalog.js +58 -0
  80. package/esm/src/provider/model-registry.d.ts +14 -0
  81. package/esm/src/provider/model-registry.d.ts.map +1 -1
  82. package/esm/src/provider/model-registry.js +58 -2
  83. package/esm/src/proxy/main.js +34 -6
  84. package/esm/src/proxy/server-resolver.d.ts +23 -0
  85. package/esm/src/proxy/server-resolver.d.ts.map +1 -0
  86. package/esm/src/proxy/server-resolver.js +124 -0
  87. package/esm/src/react/components/ai/chat/components/inference-badge.d.ts +8 -0
  88. package/esm/src/react/components/ai/chat/components/inference-badge.d.ts.map +1 -0
  89. package/esm/src/react/components/ai/chat/components/inference-badge.js +36 -0
  90. package/esm/src/react/components/ai/chat/components/upgrade-cta.d.ts +7 -0
  91. package/esm/src/react/components/ai/chat/components/upgrade-cta.d.ts.map +1 -0
  92. package/esm/src/react/components/ai/chat/components/upgrade-cta.js +33 -0
  93. package/esm/src/react/components/ai/chat/index.d.ts +7 -1
  94. package/esm/src/react/components/ai/chat/index.d.ts.map +1 -1
  95. package/esm/src/react/components/ai/chat/index.js +16 -4
  96. package/esm/src/sandbox/index.d.ts +31 -0
  97. package/esm/src/sandbox/index.d.ts.map +1 -0
  98. package/esm/src/sandbox/index.js +30 -0
  99. package/esm/src/sandbox/sandbox.d.ts +48 -0
  100. package/esm/src/sandbox/sandbox.d.ts.map +1 -0
  101. package/esm/src/sandbox/sandbox.js +178 -0
  102. package/esm/src/transforms/pipeline/stages/ssr-vf-modules/import-finder.d.ts.map +1 -1
  103. package/esm/src/transforms/pipeline/stages/ssr-vf-modules/import-finder.js +8 -2
  104. package/esm/src/transforms/pipeline/stages/ssr-vf-modules/index.d.ts +1 -0
  105. package/esm/src/transforms/pipeline/stages/ssr-vf-modules/index.d.ts.map +1 -1
  106. package/esm/src/transforms/pipeline/stages/ssr-vf-modules/index.js +1 -0
  107. package/esm/src/transforms/pipeline/stages/ssr-vf-modules/transform.d.ts.map +1 -1
  108. package/esm/src/transforms/pipeline/stages/ssr-vf-modules/transform.js +15 -1
  109. package/package.json +8 -1
  110. package/src/cli/app/data/slug-words.ts +225 -90
  111. package/src/cli/app/operations/project-creation.ts +3 -3
  112. package/src/cli/app/shell.ts +1 -1
  113. package/src/cli/app/utils.ts +0 -30
  114. package/src/cli/app/views/dashboard.ts +27 -4
  115. package/src/cli/auth/callback-server.ts +3 -2
  116. package/src/cli/commands/dev/handler.ts +2 -0
  117. package/src/cli/commands/init/init-command.ts +30 -3
  118. package/src/cli/commands/init/interactive-wizard.ts +62 -34
  119. package/src/cli/mcp/remote-file-tools.ts +50 -15
  120. package/src/cli/shared/reserve-slug.ts +9 -2
  121. package/src/cli/utils/env-prompt.ts +3 -0
  122. package/src/deno.js +11 -4
  123. package/src/src/agent/chat-handler.ts +57 -4
  124. package/src/src/agent/react/index.ts +2 -0
  125. package/src/src/agent/react/use-chat/browser-inference/browser-engine.ts +81 -0
  126. package/src/src/agent/react/use-chat/browser-inference/types.ts +52 -0
  127. package/src/src/agent/react/use-chat/browser-inference/worker-client.ts +89 -0
  128. package/src/src/agent/react/use-chat/browser-inference/worker-script.ts +98 -0
  129. package/src/src/agent/react/use-chat/index.ts +2 -0
  130. package/src/src/agent/react/use-chat/types.ts +20 -0
  131. package/src/src/agent/react/use-chat/use-chat.ts +148 -8
  132. package/src/src/agent/runtime/index.ts +72 -6
  133. package/src/src/build/production-build/templates.ts +2 -68
  134. package/src/src/chat/index.ts +2 -0
  135. package/src/src/errors/veryfront-error.ts +2 -1
  136. package/src/src/platform/adapters/runtime/deno/adapter.ts +25 -3
  137. package/src/src/platform/compat/http/deno-server.ts +28 -1
  138. package/src/src/provider/index.ts +1 -0
  139. package/src/src/provider/local/ai-sdk-adapter.ts +207 -0
  140. package/src/src/provider/local/env.ts +26 -0
  141. package/src/src/provider/local/local-engine.ts +288 -0
  142. package/src/src/provider/local/model-catalog.ts +73 -0
  143. package/src/src/provider/model-registry.ts +66 -2
  144. package/src/src/proxy/main.ts +41 -6
  145. package/src/src/proxy/server-resolver.ts +151 -0
  146. package/src/src/react/components/ai/chat/components/inference-badge.tsx +48 -0
  147. package/src/src/react/components/ai/chat/components/upgrade-cta.tsx +56 -0
  148. package/src/src/react/components/ai/chat/index.tsx +43 -6
  149. package/src/src/sandbox/index.ts +32 -0
  150. package/src/src/sandbox/sandbox.ts +236 -0
  151. package/src/src/transforms/pipeline/stages/ssr-vf-modules/import-finder.ts +9 -2
  152. package/src/src/transforms/pipeline/stages/ssr-vf-modules/index.ts +1 -0
  153. package/src/src/transforms/pipeline/stages/ssr-vf-modules/transform.ts +17 -0
@@ -4,13 +4,21 @@ import { isCiEnv, isDenoTestingEnv } from "../../../src/config/index.js";
4
4
  import { isInteractive as checkIsInteractive } from "../../../src/platform/index.js";
5
5
  import { select, textInput } from "../../utils/terminal-select.js";
6
6
  import { getTemplateSelectOptions, TEMPLATES } from "./catalog.js";
7
+ /** Reject path separators and traversal so the name stays a single directory. */
8
+ export function validateProjectName(name) {
9
+ if (/[/\\]/.test(name))
10
+ return 'Project name cannot contain "/" or "\\"';
11
+ if (name === "." || name === "..")
12
+ return 'Project name cannot be "." or ".."';
13
+ return null;
14
+ }
7
15
  function canRunWizard() {
8
16
  return !(isCiEnv() || isDenoTestingEnv()) && checkIsInteractive();
9
17
  }
10
- export async function runInteractiveWizard() {
18
+ export async function runInteractiveWizard(existingName) {
11
19
  if (!canRunWizard()) {
12
20
  return {
13
- projectName: null,
21
+ projectName: existingName ?? null,
14
22
  template: "minimal",
15
23
  initGit: false,
16
24
  skipped: true,
@@ -24,25 +32,22 @@ export async function runInteractiveWizard() {
24
32
  console.log(`┌ ${brand("Veryfront")}`);
25
33
  console.log(`│ Let's set up your project.`);
26
34
  console.log("│");
27
- // Step 1: Location prompt
28
- const locationChoice = await select("Where should we create your project?", [
29
- { value: "current", label: "Current folder", description: "Use this directory" },
30
- { value: "new", label: "New folder", description: "Create a new directory" },
31
- ], 0);
32
- if (locationChoice === null) {
33
- console.log(muted("\n Cancelled.\n"));
34
- return {
35
- projectName: null,
36
- template: "minimal",
37
- initGit: false,
38
- skipped: false,
39
- cancelled: true,
40
- };
41
- }
42
- let projectName = null;
43
- if (locationChoice === "new") {
44
- const name = await textInput("Project name", "my-app");
45
- if (name === null) {
35
+ let projectName = existingName ?? null;
36
+ // Location prompt (skip when name was provided via CLI)
37
+ if (!existingName) {
38
+ const locationChoice = await select("Where should we create your project?", [
39
+ {
40
+ value: "current",
41
+ label: "Current folder",
42
+ description: "Use this directory",
43
+ },
44
+ {
45
+ value: "new",
46
+ label: "New folder",
47
+ description: "Create a new directory",
48
+ },
49
+ ], 0);
50
+ if (locationChoice === null) {
46
51
  console.log(muted("\n Cancelled.\n"));
47
52
  return {
48
53
  projectName: null,
@@ -52,11 +57,34 @@ export async function runInteractiveWizard() {
52
57
  cancelled: true,
53
58
  };
54
59
  }
55
- if (name) {
56
- projectName = name;
60
+ if (locationChoice === "new") {
61
+ const name = await textInput("Project name", "my-app");
62
+ if (name === null) {
63
+ console.log(muted("\n Cancelled.\n"));
64
+ return {
65
+ projectName: null,
66
+ template: "minimal",
67
+ initGit: false,
68
+ skipped: false,
69
+ cancelled: true,
70
+ };
71
+ }
72
+ const validName = name || "my-app";
73
+ const nameError = validateProjectName(validName);
74
+ if (nameError) {
75
+ console.log(muted(`\n ${nameError}\n`));
76
+ return {
77
+ projectName: null,
78
+ template: "minimal",
79
+ initGit: false,
80
+ skipped: false,
81
+ cancelled: true,
82
+ };
83
+ }
84
+ projectName = validName;
57
85
  }
58
86
  }
59
- // Step 2: Template selection
87
+ // Template selection
60
88
  const templateChoice = await select("What would you like to build?", getTemplateSelectOptions(), 0);
61
89
  if (templateChoice === null) {
62
90
  console.log(muted("\n Cancelled.\n"));
@@ -69,7 +97,7 @@ export async function runInteractiveWizard() {
69
97
  };
70
98
  }
71
99
  const template = templateChoice;
72
- // Step 3: Git init prompt
100
+ // Git init prompt
73
101
  const gitChoice = await select("Initialize a git repository?", [
74
102
  { value: "yes", label: "Yes", description: "Initialize git and create first commit" },
75
103
  { value: "no", label: "No", description: "Skip git initialization" },
@@ -102,6 +130,6 @@ export async function runInteractiveWizard() {
102
130
  return { projectName, template, initGit, skipped: false, cancelled: false };
103
131
  }
104
132
  export function shouldRunWizard(options) {
105
- // Run wizard if no template and no name specified via CLI
106
- return !options.template && !options.name;
133
+ // Always run wizard unless template is explicitly specified via --template
134
+ return !options.template;
107
135
  }
@@ -259,17 +259,14 @@ interface RemoteDeleteBranchOutput {
259
259
  }
260
260
  export declare const vfRemoteDeleteBranch: MCPTool<RemoteDeleteBranchInput, RemoteDeleteBranchOutput>;
261
261
  declare const remoteCreateProjectInput: z.ZodObject<{
262
- name: z.ZodString;
263
262
  slug: z.ZodString;
264
263
  template: z.ZodOptional<z.ZodString>;
265
264
  is_public: z.ZodOptional<z.ZodBoolean>;
266
265
  }, "strip", z.ZodTypeAny, {
267
- name: string;
268
266
  slug: string;
269
267
  template?: string | undefined;
270
268
  is_public?: boolean | undefined;
271
269
  }, {
272
- name: string;
273
270
  slug: string;
274
271
  template?: string | undefined;
275
272
  is_public?: boolean | undefined;
@@ -283,17 +280,14 @@ interface RemoteCreateProjectOutput {
283
280
  export declare const vfRemoteCreateProject: MCPTool<RemoteCreateProjectInput, RemoteCreateProjectOutput>;
284
281
  declare const remoteCloneProjectInput: z.ZodObject<{
285
282
  source_project: z.ZodString;
286
- target_name: z.ZodString;
287
283
  target_slug: z.ZodString;
288
284
  file_pattern: z.ZodOptional<z.ZodString>;
289
285
  }, "strip", z.ZodTypeAny, {
290
286
  source_project: string;
291
- target_name: string;
292
287
  target_slug: string;
293
288
  file_pattern?: string | undefined;
294
289
  }, {
295
290
  source_project: string;
296
- target_name: string;
297
291
  target_slug: string;
298
292
  file_pattern?: string | undefined;
299
293
  }>;
@@ -1 +1 @@
1
- {"version":3,"file":"remote-file-tools.d.ts","sourceRoot":"","sources":["../../../src/cli/mcp/remote-file-tools.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"remote-file-tools.d.ts","sourceRoot":"","sources":["../../../src/cli/mcp/remote-file-tools.ts"],"names":[],"mappings":"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"}
@@ -12,6 +12,7 @@ import * as dntShim from "../../_dnt.shims.js";
12
12
  import { z } from "zod";
13
13
  import { getEnvironmentConfig } from "../../src/config/index.js";
14
14
  import { withSpan } from "../../src/observability/tracing/otlp-setup.js";
15
+ import { randomSuffix } from "../shared/slug.js";
15
16
  import { DEFAULT_LOCAL_API_URL } from "../shared/constants.js";
16
17
  function getApiBaseUrl() {
17
18
  return getEnvironmentConfig().apiBaseUrl || DEFAULT_LOCAL_API_URL;
@@ -67,6 +68,35 @@ function getBranchPath(branch) {
67
68
  function getBranchParam(branch) {
68
69
  return branch ? `?branch_id=${branch}` : "";
69
70
  }
71
+ const MAX_SLUG_ATTEMPTS = 10;
72
+ function slugToName(slug) {
73
+ return slug
74
+ .split("-")
75
+ .map((w) => w.charAt(0).toUpperCase() + w.slice(1))
76
+ .join(" ");
77
+ }
78
+ /**
79
+ * Create a project with slug conflict retry.
80
+ * On 409, appends a random suffix and retries (matches reserveProjectSlug behavior).
81
+ * Name is derived from the base slug (without random suffix) for readability.
82
+ */
83
+ async function createProjectWithRetry(slug, body) {
84
+ const name = slugToName(slug);
85
+ let currentSlug = slug;
86
+ for (let attempt = 1; attempt <= MAX_SLUG_ATTEMPTS; attempt++) {
87
+ const result = await apiRequest("POST", "/projects", {
88
+ body: { ...body, slug: currentSlug, name },
89
+ });
90
+ if (result.ok && result.data) {
91
+ return { ok: true, data: result.data, slug: currentSlug };
92
+ }
93
+ if (result.status !== 409) {
94
+ return { ok: false, error: result.error ?? "Failed to create project" };
95
+ }
96
+ currentSlug = `${slug}-${randomSuffix()}`;
97
+ }
98
+ return { ok: false, error: `Could not find available slug after ${MAX_SLUG_ATTEMPTS} attempts` };
99
+ }
70
100
  // ============================================================================
71
101
  // Tool: vf_remote_list_files
72
102
  // ============================================================================
@@ -333,8 +363,7 @@ export const vfRemoteDeleteBranch = {
333
363
  // Tool: vf_remote_create_project
334
364
  // ============================================================================
335
365
  const remoteCreateProjectInput = z.object({
336
- name: z.string().describe("Project name"),
337
- slug: z.string().describe("Project slug (lowercase letters, numbers, hyphens only)"),
366
+ slug: z.string().describe("Project slug (lowercase letters, numbers, hyphens only). A random suffix is appended if the slug is already taken."),
338
367
  template: z.string().optional().describe("Template to use (e.g., 'chat', 'rag', 'minimal')"),
339
368
  is_public: z.boolean().optional().describe("Whether the project is public (default: false)"),
340
369
  });
@@ -343,13 +372,9 @@ export const vfRemoteCreateProject = {
343
372
  description: "Create a new Veryfront project. Returns the project details including ID and slug.",
344
373
  inputSchema: remoteCreateProjectInput,
345
374
  execute: async (input) => {
346
- const result = await apiRequest("POST", "/projects", {
347
- body: {
348
- name: input.name,
349
- slug: input.slug,
350
- template: input.template,
351
- isPublic: input.is_public,
352
- },
375
+ const result = await createProjectWithRetry(input.slug, {
376
+ template: input.template,
377
+ isPublic: input.is_public,
353
378
  });
354
379
  if (!result.ok)
355
380
  return { success: false, error: result.error };
@@ -361,8 +386,7 @@ export const vfRemoteCreateProject = {
361
386
  // ============================================================================
362
387
  const remoteCloneProjectInput = z.object({
363
388
  source_project: z.string().describe("Source project slug or ID to clone from"),
364
- target_name: z.string().describe("Name for the new project"),
365
- target_slug: z.string().describe("Slug for the new project (lowercase letters, numbers, hyphens only)"),
389
+ target_slug: z.string().describe("Slug for the new project (lowercase letters, numbers, hyphens only). A random suffix is appended if the slug is already taken."),
366
390
  file_pattern: z.string().optional().describe("Optional file pattern to filter which files to clone (e.g., '*.tsx')"),
367
391
  });
368
392
  export const vfRemoteCloneProject = {
@@ -370,9 +394,7 @@ export const vfRemoteCloneProject = {
370
394
  description: "Clone a Veryfront project by creating a new project and copying all files from the source.",
371
395
  inputSchema: remoteCloneProjectInput,
372
396
  execute: (input) => withSpan("cli.mcp.tool.vf_remote_clone_project", async () => {
373
- const createResult = await apiRequest("POST", "/projects", {
374
- body: { name: input.target_name, slug: input.target_slug },
375
- });
397
+ const createResult = await createProjectWithRetry(input.target_slug, {});
376
398
  if (!createResult.ok) {
377
399
  return { success: false, error: `Failed to create project: ${createResult.error}` };
378
400
  }
@@ -400,7 +422,7 @@ export const vfRemoteCloneProject = {
400
422
  errors.push(`Failed to read ${file.path}`);
401
423
  continue;
402
424
  }
403
- const createFileResult = await apiRequest("PUT", `/${input.target_slug}/files/${encodeFilePath(file.path)}`, { body: { content: getResult.data.content } });
425
+ const createFileResult = await apiRequest("PUT", `/${createResult.slug}/files/${encodeFilePath(file.path)}`, { body: { content: getResult.data.content } });
404
426
  if (createFileResult.ok) {
405
427
  filesCopied++;
406
428
  }
@@ -1 +1 @@
1
- {"version":3,"file":"reserve-slug.d.ts","sourceRoot":"","sources":["../../../src/cli/shared/reserve-slug.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,KAAK,iBAAiB,EAAwB,MAAM,2BAA2B,CAAC;AAGzF,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;CAClB;AAmBD,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,GAAG,GAAE,iBAA0C,GAC9C,OAAO,CAAC,aAAa,CAAC,CAsBxB;AAkCD,wBAAsB,eAAe,CACnC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,GAAG,GAAE,iBAA0C,GAC9C,OAAO,CAAC,OAAO,CAAC,CAWlB"}
1
+ {"version":3,"file":"reserve-slug.d.ts","sourceRoot":"","sources":["../../../src/cli/shared/reserve-slug.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,KAAK,iBAAiB,EAAwB,MAAM,2BAA2B,CAAC;AAQzF,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;CAClB;AAmBD,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,GAAG,GAAE,iBAA0C,GAC9C,OAAO,CAAC,aAAa,CAAC,CAuBxB;AAmCD,wBAAsB,eAAe,CACnC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,GAAG,GAAE,iBAA0C,GAC9C,OAAO,CAAC,OAAO,CAAC,CAWlB"}
@@ -7,15 +7,20 @@
7
7
  */
8
8
  import * as dntShim from "../../_dnt.shims.js";
9
9
  import { getEnvironmentConfig } from "../../src/config/index.js";
10
+ import { capitalizeSeparatedWords } from "../../src/utils/case-utils.js";
10
11
  import { randomSuffix } from "./slug.js";
12
+ function slugToName(slug) {
13
+ return capitalizeSeparatedWords(slug, "-", " ");
14
+ }
11
15
  const MAX_SLUG_ATTEMPTS = 10;
12
16
  function getApiUrl(env = getEnvironmentConfig()) {
13
17
  return env.apiUrl ?? "https://api.veryfront.com";
14
18
  }
15
19
  export async function reserveProjectSlug(slug, token, env = getEnvironmentConfig()) {
20
+ const name = slugToName(slug);
16
21
  let currentSlug = slug;
17
22
  for (let attempt = 1; attempt <= MAX_SLUG_ATTEMPTS; attempt++) {
18
- const result = await tryCreateProject(currentSlug, token, env);
23
+ const result = await tryCreateProject(currentSlug, name, token, env);
19
24
  if (result.success) {
20
25
  return {
21
26
  slug: currentSlug,
@@ -30,7 +35,7 @@ export async function reserveProjectSlug(slug, token, env = getEnvironmentConfig
30
35
  }
31
36
  throw new Error(`Could not find available slug after ${MAX_SLUG_ATTEMPTS} attempts`);
32
37
  }
33
- async function tryCreateProject(slug, token, env = getEnvironmentConfig()) {
38
+ async function tryCreateProject(slug, name, token, env = getEnvironmentConfig()) {
34
39
  try {
35
40
  const response = await dntShim.fetch(`${getApiUrl(env)}/projects`, {
36
41
  method: "POST",
@@ -39,7 +44,7 @@ async function tryCreateProject(slug, token, env = getEnvironmentConfig()) {
39
44
  "Content-Type": "application/json",
40
45
  Accept: "application/json",
41
46
  },
42
- body: JSON.stringify({ slug, name: slug }),
47
+ body: JSON.stringify({ slug, name }),
43
48
  });
44
49
  if (response.ok) {
45
50
  const data = (await response.json());
@@ -1 +1 @@
1
- {"version":3,"file":"env-prompt.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/env-prompt.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAG1D,MAAM,WAAW,gBAAgB;IAC/B,6DAA6D;IAC7D,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,yCAAyC;IACzC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,gEAAgE;IAChE,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC1C;AAED,MAAM,WAAW,eAAe;IAC9B,4BAA4B;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,oCAAoC;IACpC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,2CAA2C;IAC3C,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC;AAOD;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,YAAY,EAAE,EACvB,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,eAAe,CAAC,CAiF1B;AAkCD;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,eAAe,CAAC,EAAE,MAAM,GAAG,MAAM,CAuBzE"}
1
+ {"version":3,"file":"env-prompt.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/env-prompt.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAG1D,MAAM,WAAW,gBAAgB;IAC/B,6DAA6D;IAC7D,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,yCAAyC;IACzC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,gEAAgE;IAChE,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC1C;AAED,MAAM,WAAW,eAAe;IAC9B,4BAA4B;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,oCAAoC;IACpC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,2CAA2C;IAC3C,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC;AAOD;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,YAAY,EAAE,EACvB,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,eAAe,CAAC,CAiF1B;AAkCD;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,eAAe,CAAC,EAAE,MAAM,GAAG,MAAM,CA0BzE"}
@@ -126,6 +126,9 @@ export function generateGitignoreContent(existingContent) {
126
126
  "dist/",
127
127
  ".veryfront/",
128
128
  "",
129
+ "# Local AI model cache",
130
+ ".cache/",
131
+ "",
129
132
  "# IDE",
130
133
  ".vscode/",
131
134
  ".idea/",
package/esm/deno.d.ts CHANGED
@@ -27,6 +27,7 @@ declare namespace _default {
27
27
  "./provider": string;
28
28
  "./fs": string;
29
29
  "./integrations": string;
30
+ "./sandbox": string;
30
31
  "./cli": string;
31
32
  };
32
33
  let imports: {
@@ -45,6 +46,7 @@ declare namespace _default {
45
46
  "veryfront/react/fonts": string;
46
47
  "veryfront/react/components/ai": string;
47
48
  "veryfront/components/ai": string;
49
+ "veryfront/sandbox": string;
48
50
  "veryfront/agent/react": string;
49
51
  "veryfront/agent/testing": string;
50
52
  "veryfront/agent/middleware": string;
@@ -127,6 +129,7 @@ declare namespace _default {
127
129
  "#veryfront/testing/bdd.ts": string;
128
130
  "#veryfront/testing/deno-compat": string;
129
131
  "#veryfront/testing/utils": string;
132
+ "#veryfront/sandbox": string;
130
133
  "#veryfront/tool": string;
131
134
  "#veryfront/tool/schema": string;
132
135
  "#veryfront/transforms": string;
@@ -243,6 +246,7 @@ declare namespace _default {
243
246
  "@babel/traverse": string;
244
247
  "@babel/generator": string;
245
248
  "@babel/types": string;
249
+ "@huggingface/transformers": string;
246
250
  };
247
251
  namespace compilerOptions {
248
252
  let jsx: string;
@@ -345,7 +349,7 @@ declare namespace _default {
345
349
  export let proseWrap: string;
346
350
  }
347
351
  namespace allowScripts {
348
- let allow: never[];
352
+ let allow: string[];
349
353
  let deny: string[];
350
354
  }
351
355
  }
package/esm/deno.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export default {
2
2
  "name": "veryfront",
3
- "version": "0.1.13",
3
+ "version": "0.1.15",
4
4
  "nodeModulesDir": "auto",
5
5
  "exclude": [
6
6
  "npm/",
@@ -37,6 +37,7 @@ export default {
37
37
  "./provider": "./src/provider/index.ts",
38
38
  "./fs": "./src/fs/index.ts",
39
39
  "./integrations": "./src/integrations/index.ts",
40
+ "./sandbox": "./src/sandbox/index.ts",
40
41
  "./cli": "./cli/main.ts"
41
42
  },
42
43
  "imports": {
@@ -55,6 +56,7 @@ export default {
55
56
  "veryfront/react/fonts": "./src/react/fonts/index.ts",
56
57
  "veryfront/react/components/ai": "./src/react/components/ai/index.ts",
57
58
  "veryfront/components/ai": "./src/react/components/ai/index.ts",
59
+ "veryfront/sandbox": "./src/sandbox/index.ts",
58
60
  "veryfront/agent/react": "./src/agent/react/index.ts",
59
61
  "veryfront/agent/testing": "./src/agent/testing/index.ts",
60
62
  "veryfront/agent/middleware": "./src/agent/middleware/index.ts",
@@ -137,6 +139,7 @@ export default {
137
139
  "#veryfront/testing/bdd.ts": "./src/testing/bdd.ts",
138
140
  "#veryfront/testing/deno-compat": "./src/testing/deno-compat.ts",
139
141
  "#veryfront/testing/utils": "./src/testing/utils.ts",
142
+ "#veryfront/sandbox": "./src/sandbox/index.ts",
140
143
  "#veryfront/tool": "./src/tool/index.ts",
141
144
  "#veryfront/tool/schema": "./src/tool/schema/index.ts",
142
145
  "#veryfront/transforms": "./src/transforms/index.ts",
@@ -252,7 +255,8 @@ export default {
252
255
  "@babel/parser": "npm:@babel/parser@7.26.3",
253
256
  "@babel/traverse": "npm:@babel/traverse@7.26.3",
254
257
  "@babel/generator": "npm:@babel/generator@7.26.3",
255
- "@babel/types": "npm:@babel/types@7.26.3"
258
+ "@babel/types": "npm:@babel/types@7.26.3",
259
+ "@huggingface/transformers": "npm:@huggingface/transformers@3.4.2"
256
260
  },
257
261
  "compilerOptions": {
258
262
  "jsx": "react-jsx",
@@ -278,7 +282,7 @@ export default {
278
282
  "proxy": "deno run --allow-all cli/main.ts serve --mode=proxy",
279
283
  "dev": "deno run --allow-all cli/main.ts dev",
280
284
  "production": "deno run --allow-all cli/main.ts serve --mode=production",
281
- "build": "deno run -A scripts/build/generate-integrations-module.ts && deno run -A scripts/build/generate-templates-manifest.ts && deno run -A scripts/build/generate-dev-ui-manifest.ts && deno run -A scripts/build/prepare-framework-sources.ts && deno compile --allow-all --include src/platform/polyfills --include src/proxy/main.ts --include dist/framework-src --output ./bin/veryfront cli/main.ts",
285
+ "build": "deno run -A scripts/build/generate-integrations-module.ts && deno run -A scripts/build/generate-templates-manifest.ts && deno run -A scripts/build/generate-dev-ui-manifest.ts && deno run -A scripts/build/prepare-framework-sources.ts && deno run -A scripts/build/prebundle-client-scripts.ts && deno compile --allow-all --include src/platform/polyfills --include src/proxy/main.ts --include dist/framework-src --output ./bin/veryfront cli/main.ts",
282
286
  "build:npm": "deno run -A scripts/build/generate-integrations-module.ts && deno run -A scripts/build/build-npm-dnt.ts",
283
287
  "release": "deno run -A scripts/release.ts",
284
288
  "test": "VF_DISABLE_LRU_INTERVAL=1 SSR_TRANSFORM_PER_PROJECT_LIMIT=0 REVALIDATION_PER_PROJECT_LIMIT=0 NODE_ENV=production LOG_FORMAT=text deno test --no-check --parallel --allow-all '--ignore=tests/e2e,tests/integration/compiled-binary-e2e.test.ts' --unstable-worker-options --unstable-net",
@@ -383,7 +387,10 @@ export default {
383
387
  "proseWrap": "preserve"
384
388
  },
385
389
  "allowScripts": {
386
- "allow": [],
390
+ "allow": [
391
+ "npm:sharp@0.33.5",
392
+ "npm:onnxruntime-node@1.20.1"
393
+ ],
387
394
  "deny": [
388
395
  "npm:esbuild@0.20.2",
389
396
  "npm:protobufjs@7.5.4"
@@ -6,8 +6,9 @@ export interface ChatHandlerOptions {
6
6
  /**
7
7
  * Create a POST handler for a chat API route.
8
8
  *
9
- * Encapsulates request validation, message transformation, agent streaming,
10
- * and error handling so that template routes stay one-liners.
9
+ * Works with both App Router and Pages Router:
10
+ * - App Router: `app/api/chat/route.ts` handler receives `(request, context)`
11
+ * - Pages Router: `pages/api/chat.ts` — handler receives `(ctx)`
11
12
  *
12
13
  * @example
13
14
  * ```ts
@@ -15,5 +16,5 @@ export interface ChatHandlerOptions {
15
16
  * export const POST = createChatHandler("assistant");
16
17
  * ```
17
18
  */
18
- export declare function createChatHandler(agentId: string, options?: ChatHandlerOptions): (request: dntShim.Request) => Promise<dntShim.Response>;
19
+ export declare function createChatHandler(agentId: string, options?: ChatHandlerOptions): (requestOrCtx: any) => Promise<dntShim.Response>;
19
20
  //# sourceMappingURL=chat-handler.d.ts.map
@@ -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;AA0H/C,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;CACpE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,kBAAkB,IAED,SAAS,OAAO,CAAC,OAAO,KAAG,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAsChF"}
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;AA4H/C,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;CACpE;AAeD;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,kBAAkB,IAGD,cAAc,GAAG,KAAG,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CA0EzE"}
@@ -1,6 +1,8 @@
1
1
  import * as dntShim from "../../_dnt.shims.js";
2
2
  import { z } from "zod";
3
3
  import { getAgent } from "./composition/index.js";
4
+ import { fromError } from "../errors/veryfront-error.js";
5
+ import { DEFAULT_LOCAL_MODEL } from "../provider/local/model-catalog.js";
4
6
  // ---------------------------------------------------------------------------
5
7
  // Zod schemas for validating AI SDK v5 chat UI messages
6
8
  // ---------------------------------------------------------------------------
@@ -88,11 +90,26 @@ function transformUIMessages(messages) {
88
90
  // after normalization since Zod already validated the request boundary.
89
91
  return result;
90
92
  }
93
+ /**
94
+ * Extract the raw Request from either a raw Request or a Pages Router APIContext.
95
+ * Pages Router handlers receive `(ctx)` where `ctx.request` is the Request.
96
+ * App Router handlers receive `(request, context)` where `request` IS the Request.
97
+ */
98
+ function extractRequest(requestOrCtx) {
99
+ if (requestOrCtx instanceof dntShim.Request)
100
+ return requestOrCtx;
101
+ // Pages Router APIContext — has a .request property
102
+ const ctx = requestOrCtx;
103
+ if (ctx.request instanceof dntShim.Request)
104
+ return ctx.request;
105
+ throw new Error("Invalid handler argument: expected Request or APIContext");
106
+ }
91
107
  /**
92
108
  * Create a POST handler for a chat API route.
93
109
  *
94
- * Encapsulates request validation, message transformation, agent streaming,
95
- * and error handling so that template routes stay one-liners.
110
+ * Works with both App Router and Pages Router:
111
+ * - App Router: `app/api/chat/route.ts` handler receives `(request, context)`
112
+ * - Pages Router: `pages/api/chat.ts` — handler receives `(ctx)`
96
113
  *
97
114
  * @example
98
115
  * ```ts
@@ -101,11 +118,21 @@ function transformUIMessages(messages) {
101
118
  * ```
102
119
  */
103
120
  export function createChatHandler(agentId, options) {
104
- return async function POST(request) {
121
+ // deno-lint-ignore no-explicit-any
122
+ return async function POST(requestOrCtx) {
123
+ const request = extractRequest(requestOrCtx);
124
+ // Resolve agent outside try so it's available in the catch block for
125
+ // extracting the system prompt in the 503 fallback response.
126
+ let agent;
127
+ try {
128
+ agent = getAgent(agentId);
129
+ }
130
+ catch {
131
+ return dntShim.Response.json({ error: "Agent not found" }, { status: 404 });
132
+ }
105
133
  try {
106
134
  const body = await request.json();
107
135
  const { messages: rawMessages } = chatRequestSchema.parse(body);
108
- const agent = getAgent(agentId);
109
136
  if (!agent) {
110
137
  return dntShim.Response.json({ error: "Agent not found" }, { status: 404 });
111
138
  }
@@ -125,6 +152,30 @@ export function createChatHandler(agentId, options) {
125
152
  if (error instanceof z.ZodError) {
126
153
  return dntShim.Response.json({ error: "Invalid request", details: error.errors }, { status: 400 });
127
154
  }
155
+ // Detect structured "no_ai_available" errors from local engine
156
+ const vfError = fromError(error);
157
+ if (vfError?.type === "no_ai_available") {
158
+ // Resolve the agent's system prompt so the browser can use it for inference
159
+ const systemConfig = agent?.config?.system;
160
+ let systemPrompt = "You are a helpful AI assistant.";
161
+ if (typeof systemConfig === "string") {
162
+ systemPrompt = systemConfig;
163
+ }
164
+ else if (typeof systemConfig === "function") {
165
+ try {
166
+ systemPrompt = await systemConfig();
167
+ }
168
+ catch {
169
+ // Fall back to default
170
+ }
171
+ }
172
+ return dntShim.Response.json({
173
+ code: "NO_AI_AVAILABLE",
174
+ fallback: "browser",
175
+ model: DEFAULT_LOCAL_MODEL,
176
+ systemPrompt,
177
+ }, { status: 503 });
178
+ }
128
179
  return dntShim.Response.json({ error: "Internal server error" }, { status: 500 });
129
180
  }
130
181
  };
@@ -4,7 +4,7 @@
4
4
  * @module agent/react
5
5
  */
6
6
  export { useChat } from "./use-chat/index.js";
7
- export type { DynamicToolUIPart, OnToolCallArg, ReasoningUIPart, TextUIPart, ToolOutput, ToolResultUIPart, ToolState, ToolUIPart, UIMessage, UIMessagePart, UseChatOptions, UseChatResult, } from "./use-chat/index.js";
7
+ export type { BrowserInferenceStatus, DynamicToolUIPart, InferenceMode, OnToolCallArg, ReasoningUIPart, TextUIPart, ToolOutput, ToolResultUIPart, ToolState, ToolUIPart, UIMessage, UIMessagePart, UseChatOptions, UseChatResult, } from "./use-chat/index.js";
8
8
  export { useAgent } from "./use-agent.js";
9
9
  export type { UseAgentOptions, UseAgentResult } from "./use-agent.js";
10
10
  export { useCompletion } from "./use-completion.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/src/agent/react/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC9C,YAAY,EACV,iBAAiB,EACjB,aAAa,EACb,eAAe,EACf,UAAU,EACV,UAAU,EACV,gBAAgB,EAChB,SAAS,EACT,UAAU,EACV,SAAS,EACT,aAAa,EACb,cAAc,EACd,aAAa,GACd,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEtE,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,YAAY,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAErF,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,YAAY,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAElF,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,YAAY,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/src/agent/react/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC9C,YAAY,EACV,sBAAsB,EACtB,iBAAiB,EACjB,aAAa,EACb,aAAa,EACb,eAAe,EACf,UAAU,EACV,UAAU,EACV,gBAAgB,EAChB,SAAS,EACT,UAAU,EACV,SAAS,EACT,aAAa,EACb,cAAc,EACd,aAAa,GACd,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEtE,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,YAAY,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAErF,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,YAAY,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAElF,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,YAAY,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Bridge between BrowserInferenceClient (Worker) and useChat's streaming interface.
3
+ *
4
+ * Converts UIMessage[] to simple {role, content}[] for the Worker,
5
+ * and synthesizes the same streaming updates that handleStreamingResponse produces.
6
+ */
7
+ import type { BrowserInferenceStatus } from "../types.js";
8
+ import type { UIMessage, UIMessagePart } from "../types.js";
9
+ export interface BrowserInferenceCallbacks {
10
+ onUpdate: (parts: UIMessagePart[], messageId: string) => void;
11
+ onMessage: (message: UIMessage) => void;
12
+ onStatusChange: (status: BrowserInferenceStatus) => void;
13
+ onDownloadProgress?: (progress: number) => void;
14
+ onError: (error: Error) => void;
15
+ }
16
+ export declare function runBrowserInference(messages: UIMessage[], systemPrompt: string, callbacks: BrowserInferenceCallbacks): void;
17
+ export declare function stopBrowserInference(): void;
18
+ //# sourceMappingURL=browser-engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser-engine.d.ts","sourceRoot":"","sources":["../../../../../../src/src/agent/react/use-chat/browser-inference/browser-engine.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAI5D,MAAM,WAAW,yBAAyB;IACxC,QAAQ,EAAE,CAAC,KAAK,EAAE,aAAa,EAAE,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9D,SAAS,EAAE,CAAC,OAAO,EAAE,SAAS,KAAK,IAAI,CAAC;IACxC,cAAc,EAAE,CAAC,MAAM,EAAE,sBAAsB,KAAK,IAAI,CAAC;IACzD,kBAAkB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CACjC;AAeD,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,SAAS,EAAE,EACrB,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,yBAAyB,GACnC,IAAI,CAuCN;AAED,wBAAgB,oBAAoB,IAAI,IAAI,CAE3C"}