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
@@ -0,0 +1,124 @@
1
+ /**
2
+ * Dedicated Server Resolver
3
+ *
4
+ * Resolves an environment ID to a dedicated server hostname.
5
+ * Used by the proxy to route traffic to dedicated servers instead of the shared pool.
6
+ *
7
+ * Caches results in memory with a short TTL to avoid hitting the API on every request.
8
+ * A null result (no dedicated server) is also cached to prevent repeated lookups.
9
+ */
10
+ import * as dntShim from "../../_dnt.shims.js";
11
+ import { proxyLogger } from "./logger.js";
12
+ import { unrefTimer } from "../platform/compat/process.js";
13
+ const logger = proxyLogger.child({ module: "server-resolver" });
14
+ /** Thrown when the API call fails (network error, non-OK status, parse error). */
15
+ class ServerResolverError extends Error {
16
+ constructor(message, options) {
17
+ super(message, options);
18
+ }
19
+ }
20
+ export class ServerResolver {
21
+ apiInternalUrl;
22
+ apiUser;
23
+ apiPass;
24
+ cacheTtlMs;
25
+ cache = new Map();
26
+ pending = new Map();
27
+ cleanupTimer = null;
28
+ constructor(apiInternalUrl, apiUser, apiPass, cacheTtlMs = 30_000) {
29
+ this.apiInternalUrl = apiInternalUrl;
30
+ this.apiUser = apiUser;
31
+ this.apiPass = apiPass;
32
+ this.cacheTtlMs = cacheTtlMs;
33
+ // Cleanup expired entries every 60s
34
+ this.cleanupTimer = dntShim.setInterval(() => this.cleanup(), 60_000);
35
+ // Don't keep the process alive for cleanup
36
+ unrefTimer(this.cleanupTimer);
37
+ }
38
+ /**
39
+ * Resolve an environment ID to a dedicated server URL, or null for shared pool.
40
+ */
41
+ async resolve(environmentId) {
42
+ if (!environmentId)
43
+ return null;
44
+ const cached = this.cache.get(environmentId);
45
+ if (cached && Date.now() < cached.expiresAt) {
46
+ return cached.server ? `http://${cached.server.hostname}` : null;
47
+ }
48
+ // Deduplicate concurrent requests for the same environment
49
+ const inflight = this.pending.get(environmentId);
50
+ if (inflight) {
51
+ const server = await inflight;
52
+ return server ? `http://${server.hostname}` : null;
53
+ }
54
+ const promise = this.fetchServer(environmentId);
55
+ this.pending.set(environmentId, promise);
56
+ try {
57
+ const server = await promise;
58
+ // Only cache successful API responses (server found OR explicit "no server").
59
+ // Transient errors (network failures, non-OK status) are NOT cached so the
60
+ // next request retries the API instead of suppressing dedicated routing.
61
+ this.cache.set(environmentId, {
62
+ server,
63
+ expiresAt: Date.now() + this.cacheTtlMs,
64
+ });
65
+ return server ? `http://${server.hostname}` : null;
66
+ }
67
+ catch (error) {
68
+ // API error — don't cache, fall back to shared pool for this request
69
+ logger.warn("[ServerResolver] Transient error, skipping cache", {
70
+ environmentId,
71
+ error: error instanceof Error ? error.message : String(error),
72
+ });
73
+ return null;
74
+ }
75
+ finally {
76
+ this.pending.delete(environmentId);
77
+ }
78
+ }
79
+ close() {
80
+ if (this.cleanupTimer) {
81
+ clearInterval(this.cleanupTimer);
82
+ this.cleanupTimer = null;
83
+ }
84
+ this.cache.clear();
85
+ }
86
+ /**
87
+ * Fetch dedicated server from API.
88
+ * Returns DedicatedServer | null on success (null = no dedicated server assigned).
89
+ * Throws ServerResolverError on transient failures (network, non-OK status).
90
+ */
91
+ async fetchServer(environmentId) {
92
+ const url = `${this.apiInternalUrl}/internal/environment-server?environmentId=${encodeURIComponent(environmentId)}`;
93
+ const headers = { Accept: "application/json" };
94
+ if (this.apiUser && this.apiPass) {
95
+ headers.Authorization = `Basic ${btoa(`${this.apiUser}:${this.apiPass}`)}`;
96
+ }
97
+ let response;
98
+ try {
99
+ response = await dntShim.fetch(url, { headers, signal: AbortSignal.timeout(5_000) });
100
+ }
101
+ catch (error) {
102
+ throw new ServerResolverError(`Failed to reach API: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
103
+ }
104
+ if (!response.ok) {
105
+ await response.body?.cancel();
106
+ throw new ServerResolverError(`API returned ${response.status} for ${environmentId}`);
107
+ }
108
+ const data = (await response.json());
109
+ if (data.server) {
110
+ logger.debug("[ServerResolver] Resolved dedicated server", {
111
+ environmentId,
112
+ hostname: data.server.hostname,
113
+ });
114
+ }
115
+ return data.server;
116
+ }
117
+ cleanup() {
118
+ const now = Date.now();
119
+ for (const [key, entry] of this.cache) {
120
+ if (now >= entry.expiresAt)
121
+ this.cache.delete(key);
122
+ }
123
+ }
124
+ }
@@ -0,0 +1,8 @@
1
+ import * as React from "react";
2
+ import type { BrowserInferenceStatus, InferenceMode } from "../../../../../agent/react/index.js";
3
+ export interface InferenceBadgeProps {
4
+ inferenceMode: InferenceMode;
5
+ browserStatus?: BrowserInferenceStatus | null;
6
+ }
7
+ export declare function InferenceBadge({ inferenceMode, browserStatus, }: InferenceBadgeProps): React.ReactElement | null;
8
+ //# sourceMappingURL=inference-badge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inference-badge.d.ts","sourceRoot":"","sources":["../../../../../../../src/src/react/components/ai/chat/components/inference-badge.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,sBAAsB,EAAE,aAAa,EAAE,MAAM,qCAAqC,CAAC;AAEjG,MAAM,WAAW,mBAAmB;IAClC,aAAa,EAAE,aAAa,CAAC;IAC7B,aAAa,CAAC,EAAE,sBAAsB,GAAG,IAAI,CAAC;CAC/C;AAED,wBAAgB,cAAc,CAAC,EAC7B,aAAa,EACb,aAAa,GACd,EAAE,mBAAmB,GAAG,KAAK,CAAC,YAAY,GAAG,IAAI,CAoCjD"}
@@ -0,0 +1,36 @@
1
+ import * as React from "react";
2
+ export function InferenceBadge({ inferenceMode, browserStatus, }) {
3
+ if (inferenceMode === "cloud")
4
+ return null;
5
+ let label;
6
+ let dotColor;
7
+ let showProgress = false;
8
+ if (inferenceMode === "server-local") {
9
+ label = "Running locally";
10
+ dotColor = "bg-green-500";
11
+ }
12
+ else if (browserStatus === "downloading-model") {
13
+ label = "Downloading model...";
14
+ dotColor = "bg-amber-500";
15
+ showProgress = true;
16
+ }
17
+ else if (browserStatus === "loading-runtime") {
18
+ label = "Loading AI runtime...";
19
+ dotColor = "bg-amber-500";
20
+ }
21
+ else if (browserStatus === "generating") {
22
+ label = "Running in browser";
23
+ dotColor = "bg-green-500";
24
+ }
25
+ else if (browserStatus === "error") {
26
+ label = "Local model failed";
27
+ dotColor = "bg-red-500";
28
+ }
29
+ else {
30
+ label = "Running locally";
31
+ dotColor = "bg-green-500";
32
+ }
33
+ return (React.createElement("div", { className: "flex items-center gap-1.5 px-3 py-1 text-xs text-neutral-500 dark:text-neutral-400" },
34
+ React.createElement("span", { className: `size-1.5 rounded-full ${dotColor} ${showProgress ? "animate-pulse" : ""}` }),
35
+ React.createElement("span", null, label)));
36
+ }
@@ -0,0 +1,7 @@
1
+ import * as React from "react";
2
+ import type { InferenceMode } from "../../../../../agent/react/index.js";
3
+ export interface UpgradeCTAProps {
4
+ inferenceMode: InferenceMode;
5
+ }
6
+ export declare function UpgradeCTA({ inferenceMode }: UpgradeCTAProps): React.ReactElement | null;
7
+ //# sourceMappingURL=upgrade-cta.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upgrade-cta.d.ts","sourceRoot":"","sources":["../../../../../../../src/src/react/components/ai/chat/components/upgrade-cta.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qCAAqC,CAAC;AAIzE,MAAM,WAAW,eAAe;IAC9B,aAAa,EAAE,aAAa,CAAC;CAC9B;AAED,wBAAgB,UAAU,CAAC,EAAE,aAAa,EAAE,EAAE,eAAe,GAAG,KAAK,CAAC,YAAY,GAAG,IAAI,CA8CxF"}
@@ -0,0 +1,33 @@
1
+ import * as React from "react";
2
+ const DISMISS_KEY = "vf-upgrade-cta-dismissed";
3
+ export function UpgradeCTA({ inferenceMode }) {
4
+ const [dismissed, setDismissed] = React.useState(() => {
5
+ try {
6
+ return localStorage.getItem(DISMISS_KEY) === "1";
7
+ }
8
+ catch {
9
+ return false;
10
+ }
11
+ });
12
+ if (inferenceMode === "cloud" || dismissed)
13
+ return null;
14
+ const handleDismiss = () => {
15
+ setDismissed(true);
16
+ try {
17
+ localStorage.setItem(DISMISS_KEY, "1");
18
+ }
19
+ catch {
20
+ // localStorage may be unavailable
21
+ }
22
+ };
23
+ return (React.createElement("div", { className: "w-full max-w-2xl mx-auto mt-4 px-4 py-3 bg-blue-50 dark:bg-blue-900/20 rounded-xl text-sm text-blue-700 dark:text-blue-300 flex items-start gap-3" },
24
+ React.createElement("span", { className: "flex-1" },
25
+ "Using a lightweight local model. Add an API key to your",
26
+ " ",
27
+ React.createElement("code", { className: "px-1 py-0.5 bg-blue-100 dark:bg-blue-900/40 rounded text-xs" }, ".env"),
28
+ " ",
29
+ "for GPT-4o or Claude."),
30
+ React.createElement("button", { type: "button", onClick: handleDismiss, className: "text-blue-400 hover:text-blue-600 dark:hover:text-blue-200 transition-colors flex-shrink-0", "aria-label": "Dismiss" },
31
+ React.createElement("svg", { className: "size-4", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "2" },
32
+ React.createElement("path", { d: "M4 4l8 8M12 4l-8 8" })))));
33
+ }
@@ -1,5 +1,5 @@
1
1
  import * as React from "react";
2
- import type { DynamicToolUIPart, ToolUIPart, UIMessage } from "../../../../agent/react/index.js";
2
+ import type { BrowserInferenceStatus, DynamicToolUIPart, InferenceMode, ToolUIPart, UIMessage } from "../../../../agent/react/index.js";
3
3
  import { type ChatTheme } from "../theme.js";
4
4
  import { type ModelOption } from "../model-selector.js";
5
5
  export { Loader, Shimmer } from "./components/animations.js";
@@ -7,6 +7,8 @@ export { ReasoningCard } from "./components/reasoning.js";
7
7
  export { ConversationEmptyState, type ConversationEmptyStateProps, ConversationScrollButton, type ConversationScrollButtonProps, Suggestion, type SuggestionProps, Suggestions, type SuggestionsProps, } from "./components/empty-state.js";
8
8
  export { MessageActions, type MessageActionsProps } from "./components/message-actions.js";
9
9
  export { ToolCallCard, ToolStatusBadge } from "./components/tool-ui.js";
10
+ export { InferenceBadge, type InferenceBadgeProps } from "./components/inference-badge.js";
11
+ export { UpgradeCTA, type UpgradeCTAProps } from "./components/upgrade-cta.js";
10
12
  export { getTextContent, groupPartsInOrder, isReasoningPart, isToolPart, type PartGroup, } from "./utils/message-parts.js";
11
13
  export { ChatFooter, ChatHeader, ChatInput, ChatMessages } from "./composition/api.js";
12
14
  export interface ChatProps {
@@ -45,6 +47,10 @@ export interface ChatProps {
45
47
  model?: string;
46
48
  /** Called when user changes model */
47
49
  onModelChange?: (model: string) => void;
50
+ /** Where inference is currently happening */
51
+ inferenceMode?: InferenceMode;
52
+ /** Browser-side model loading/inference status */
53
+ browserStatus?: BrowserInferenceStatus | null;
48
54
  }
49
55
  export declare const Chat: any;
50
56
  export declare const ChatComponents: any;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/src/react/components/ai/chat/index.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/src/react/components/ai/chat/index.tsx"],"names":[],"mappings":"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"}
@@ -10,6 +10,8 @@ export { ReasoningCard } from "./components/reasoning.js";
10
10
  export { ConversationEmptyState, ConversationScrollButton, Suggestion, Suggestions, } from "./components/empty-state.js";
11
11
  export { MessageActions } from "./components/message-actions.js";
12
12
  export { ToolCallCard, ToolStatusBadge } from "./components/tool-ui.js";
13
+ export { InferenceBadge } from "./components/inference-badge.js";
14
+ export { UpgradeCTA } from "./components/upgrade-cta.js";
13
15
  export { getTextContent, groupPartsInOrder, isReasoningPart, isToolPart, } from "./utils/message-parts.js";
14
16
  export { ChatFooter, ChatHeader, ChatInput, ChatMessages } from "./composition/api.js";
15
17
  import { ChatFooter, ChatHeader, ChatInput, ChatMessages } from "./composition/api.js";
@@ -17,8 +19,10 @@ import { ConversationEmptyState, ConversationScrollButton, Suggestion, Suggestio
17
19
  import { MessageActions } from "./components/message-actions.js";
18
20
  import { ReasoningCard } from "./components/reasoning.js";
19
21
  import { ToolCallCard } from "./components/tool-ui.js";
22
+ import { InferenceBadge } from "./components/inference-badge.js";
23
+ import { UpgradeCTA } from "./components/upgrade-cta.js";
20
24
  import { getTextContent, groupPartsInOrder } from "./utils/message-parts.js";
21
- export const Chat = React.forwardRef(function Chat({ messages, input, onChange, handleInputChange, onSubmit, handleSubmit, stop, reload, enableVoice = false, onVoice, setInput, isLoading, error, placeholder = "Type a message...", maxHeight = "100%", className, theme: userTheme, renderMessage, renderTool, multiline = false, suggestions, onSuggestionClick, emptyState, showScrollButton = false, showMessageActions = true, models, model, onModelChange, }, ref) {
25
+ export const Chat = React.forwardRef(function Chat({ messages, input, onChange, handleInputChange, onSubmit, handleSubmit, stop, reload, enableVoice = false, onVoice, setInput, isLoading, error, placeholder = "Type a message...", maxHeight = "100%", className, theme: userTheme, renderMessage, renderTool, multiline = false, suggestions, onSuggestionClick, emptyState, showScrollButton = false, showMessageActions = true, models, model, onModelChange, inferenceMode, browserStatus, }, ref) {
22
26
  const theme = mergeThemes(defaultChatTheme, userTheme);
23
27
  const messagesEndRef = React.useRef(null);
24
28
  const inputChangeHandler = onChange ?? handleInputChange ?? (() => { });
@@ -50,6 +54,7 @@ export const Chat = React.forwardRef(function Chat({ messages, input, onChange,
50
54
  React.createElement(ConversationEmptyState, { icon: emptyState?.icon ?? React.createElement(MessageSquareIcon, { className: "size-10" }), title: emptyState?.title ?? "What can I help with?", description: emptyState?.description }),
51
55
  showSuggestions && (React.createElement("div", { className: "w-full max-w-2xl mt-6 mb-8" },
52
56
  React.createElement(Suggestions, { layout: "grid" }, suggestions?.map((suggestion) => (React.createElement(Suggestion, { key: suggestion, suggestion: suggestion, onClick: onSuggestionClick })))))),
57
+ inferenceMode && inferenceMode !== "cloud" && (React.createElement(UpgradeCTA, { inferenceMode: inferenceMode })),
53
58
  React.createElement("div", { className: "flex-1" })))
54
59
  : (React.createElement("div", { className: "max-w-2xl mx-auto px-4 py-4 space-y-2" },
55
60
  messages.map((msg) => {
@@ -80,11 +85,16 @@ export const Chat = React.forwardRef(function Chat({ messages, input, onChange,
80
85
  showMessageActions && textContent && (React.createElement(MessageActions, { content: textContent })))));
81
86
  }),
82
87
  isLoading && (React.createElement("div", { className: "flex justify-start" },
83
- React.createElement("div", { className: "bg-neutral-100 dark:bg-neutral-800 rounded-[20px] rounded-bl-[4px] px-4 py-3" },
84
- React.createElement("div", { className: "flex gap-1.5 items-center" },
88
+ React.createElement("div", { className: "bg-neutral-100 dark:bg-neutral-800 rounded-[20px] rounded-bl-[4px] px-4 py-3" }, browserStatus === "downloading-model" || browserStatus === "loading-runtime"
89
+ ? (React.createElement("div", { className: "flex items-center gap-2 text-xs text-neutral-500 dark:text-neutral-400" },
90
+ React.createElement("span", { className: "size-1.5 rounded-full bg-amber-500 animate-pulse" }),
91
+ React.createElement("span", null, browserStatus === "downloading-model"
92
+ ? "Downloading model..."
93
+ : "Loading AI...")))
94
+ : (React.createElement("div", { className: "flex gap-1.5 items-center" },
85
95
  React.createElement("span", { className: cn(theme.loading) }),
86
96
  React.createElement("span", { className: cn(theme.loading), style: { animationDelay: "0.15s" } }),
87
- React.createElement("span", { className: cn(theme.loading), style: { animationDelay: "0.3s" } }))))),
97
+ React.createElement("span", { className: cn(theme.loading), style: { animationDelay: "0.3s" } })))))),
88
98
  React.createElement("div", { ref: messagesEndRef }))),
89
99
  showScrollButton && (React.createElement(ConversationScrollButton, { onClick: () => messagesEndRef.current?.scrollIntoView({ behavior: "smooth" }) }))),
90
100
  error && (React.createElement("div", { className: "max-w-2xl mx-auto px-4 pb-2" },
@@ -94,6 +104,8 @@ export const Chat = React.forwardRef(function Chat({ messages, input, onChange,
94
104
  React.createElement(RefreshCwIcon, { className: "size-3" }),
95
105
  "Retry"))))),
96
106
  React.createElement("div", { className: "flex-shrink-0 bg-white dark:bg-neutral-900 border-t border-neutral-200 dark:border-neutral-800" },
107
+ inferenceMode && inferenceMode !== "cloud" && (React.createElement("div", { className: "max-w-2xl mx-auto" },
108
+ React.createElement(InferenceBadge, { inferenceMode: inferenceMode, browserStatus: browserStatus }))),
97
109
  React.createElement("form", { onSubmit: submitHandler, className: "max-w-2xl mx-auto px-4 py-3" },
98
110
  models && models.length > 0 && onModelChange && (React.createElement("div", { className: "mb-2" },
99
111
  React.createElement(ModelSelector, { models: models, value: model, onChange: onModelChange, disabled: isLoading }))),
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Sandbox module for ephemeral compute environments.
3
+ *
4
+ * Provides the `Sandbox` class for creating and interacting with
5
+ * isolated execution environments, and re-exports `createBashTool`
6
+ * for AI agent integration.
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * import { Sandbox } from "veryfront/sandbox";
11
+ *
12
+ * const sandbox = await Sandbox.create({ authToken: userJwt });
13
+ * const result = await sandbox.executeCommand("echo hello");
14
+ * console.log(result.stdout); // "hello\n"
15
+ * await sandbox.close();
16
+ * ```
17
+ *
18
+ * @example With bash-tool for AI agents:
19
+ * ```ts
20
+ * import { Sandbox, createBashTool } from "veryfront/sandbox";
21
+ *
22
+ * const sandbox = await Sandbox.create({ authToken });
23
+ * const { tools } = await createBashTool({ sandbox });
24
+ * // Pass tools to agent...
25
+ * ```
26
+ *
27
+ * @module
28
+ */
29
+ import "../../_dnt.polyfills.js";
30
+ export { type ExecResult, type ExecStreamEvent, Sandbox, type SandboxOptions } from "./sandbox.js";
31
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/src/sandbox/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,OAAO,yBAAyB,CAAC;AAGjC,OAAO,EAAE,KAAK,UAAU,EAAE,KAAK,eAAe,EAAE,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Sandbox module for ephemeral compute environments.
3
+ *
4
+ * Provides the `Sandbox` class for creating and interacting with
5
+ * isolated execution environments, and re-exports `createBashTool`
6
+ * for AI agent integration.
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * import { Sandbox } from "veryfront/sandbox";
11
+ *
12
+ * const sandbox = await Sandbox.create({ authToken: userJwt });
13
+ * const result = await sandbox.executeCommand("echo hello");
14
+ * console.log(result.stdout); // "hello\n"
15
+ * await sandbox.close();
16
+ * ```
17
+ *
18
+ * @example With bash-tool for AI agents:
19
+ * ```ts
20
+ * import { Sandbox, createBashTool } from "veryfront/sandbox";
21
+ *
22
+ * const sandbox = await Sandbox.create({ authToken });
23
+ * const { tools } = await createBashTool({ sandbox });
24
+ * // Pass tools to agent...
25
+ * ```
26
+ *
27
+ * @module
28
+ */
29
+ import "../../_dnt.polyfills.js";
30
+ export { Sandbox } from "./sandbox.js";
@@ -0,0 +1,48 @@
1
+ export interface SandboxOptions {
2
+ /** Base URL of the Veryfront API. Defaults to VERYFRONT_API_URL env. */
3
+ apiUrl?: string;
4
+ /** User's JWT for authentication. */
5
+ authToken: string;
6
+ }
7
+ export interface ExecResult {
8
+ stdout: string;
9
+ stderr: string;
10
+ exitCode: number;
11
+ }
12
+ export interface ExecStreamEvent {
13
+ type: "stdout" | "stderr" | "exit" | "error";
14
+ data?: string;
15
+ exitCode?: number;
16
+ }
17
+ export declare class Sandbox {
18
+ private endpoint;
19
+ private sessionId;
20
+ private authToken;
21
+ private apiUrl;
22
+ private constructor();
23
+ /** Create a new sandbox session. Claims a warm pod or creates a new one. */
24
+ static create(options: SandboxOptions): Promise<Sandbox>;
25
+ /** Reconnect to an existing sandbox session. */
26
+ static get(id: string, options: SandboxOptions): Promise<Sandbox>;
27
+ private static waitForReady;
28
+ /** Execute a bash command in the sandbox and return buffered result. */
29
+ executeCommand(command: string): Promise<ExecResult>;
30
+ /** Execute a bash command with streaming output (NDJSON). */
31
+ executeStream(command: string): AsyncGenerator<ExecStreamEvent>;
32
+ /** Read a file from the sandbox workspace. */
33
+ readFile(path: string): Promise<string>;
34
+ /** Write files to the sandbox workspace. */
35
+ writeFiles(files: Array<{
36
+ path: string;
37
+ content: string;
38
+ }>): Promise<void>;
39
+ /** Send a heartbeat to prevent idle timeout. */
40
+ heartbeat(): Promise<void>;
41
+ /** Close the sandbox session and mark for deletion. */
42
+ close(): Promise<void>;
43
+ /** Get the session ID. */
44
+ get id(): string;
45
+ /** Get the sandbox endpoint URL. */
46
+ get url(): string;
47
+ }
48
+ //# sourceMappingURL=sandbox.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sandbox.d.ts","sourceRoot":"","sources":["../../../src/src/sandbox/sandbox.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,cAAc;IAC7B,wEAAwE;IACxE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,qCAAqC;IACrC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;IAC7C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,OAAO;IAEhB,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,MAAM;IAJhB,OAAO;IAOP,4EAA4E;WAC/D,MAAM,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC;IA6B9D,gDAAgD;WACnC,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC;mBAmBlD,YAAY;IA0BjC,wEAAwE;IAClE,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAsB1D,6DAA6D;IACtD,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,CAAC,eAAe,CAAC;IAsCtE,8CAA8C;IACxC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAe7C,4CAA4C;IACtC,UAAU,CACd,KAAK,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,GAC9C,OAAO,CAAC,IAAI,CAAC;IAehB,gDAAgD;IAC1C,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAOhC,uDAAuD;IACjD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAO5B,0BAA0B;IAC1B,IAAI,EAAE,IAAI,MAAM,CAEf;IAED,oCAAoC;IACpC,IAAI,GAAG,IAAI,MAAM,CAEhB;CACF"}
@@ -0,0 +1,178 @@
1
+ /**
2
+ * Sandbox client SDK for ephemeral compute environments.
3
+ *
4
+ * Implements the bash-tool Sandbox interface for seamless integration
5
+ * with AI agent tool loops.
6
+ *
7
+ * @module
8
+ */
9
+ import * as dntShim from "../../_dnt.shims.js";
10
+ export class Sandbox {
11
+ endpoint;
12
+ sessionId;
13
+ authToken;
14
+ apiUrl;
15
+ constructor(endpoint, sessionId, authToken, apiUrl) {
16
+ this.endpoint = endpoint;
17
+ this.sessionId = sessionId;
18
+ this.authToken = authToken;
19
+ this.apiUrl = apiUrl;
20
+ }
21
+ /** Create a new sandbox session. Claims a warm pod or creates a new one. */
22
+ static async create(options) {
23
+ const apiUrl = options.apiUrl ||
24
+ (typeof dntShim.Deno !== "undefined"
25
+ ? dntShim.Deno.env.get("VERYFRONT_API_URL")
26
+ : process.env.VERYFRONT_API_URL) ||
27
+ "https://api.veryfront.com";
28
+ const res = await dntShim.fetch(`${apiUrl}/sandbox-sessions`, {
29
+ method: "POST",
30
+ headers: {
31
+ Authorization: `Bearer ${options.authToken}`,
32
+ "Content-Type": "application/json",
33
+ },
34
+ });
35
+ if (!res.ok) {
36
+ throw new Error(`Failed to create sandbox: ${res.status} ${await res.text()}`);
37
+ }
38
+ const { id, endpoint, status } = await res.json();
39
+ // If not yet running, poll until ready
40
+ if (status !== "running") {
41
+ await Sandbox.waitForReady(apiUrl, id, options.authToken);
42
+ }
43
+ return new Sandbox(endpoint, id, options.authToken, apiUrl);
44
+ }
45
+ /** Reconnect to an existing sandbox session. */
46
+ static async get(id, options) {
47
+ const apiUrl = options.apiUrl ||
48
+ (typeof dntShim.Deno !== "undefined"
49
+ ? dntShim.Deno.env.get("VERYFRONT_API_URL")
50
+ : process.env.VERYFRONT_API_URL) ||
51
+ "https://api.veryfront.com";
52
+ const res = await dntShim.fetch(`${apiUrl}/sandbox-sessions/${id}`, {
53
+ headers: { Authorization: `Bearer ${options.authToken}` },
54
+ });
55
+ if (!res.ok) {
56
+ throw new Error(`Failed to get sandbox: ${res.status} ${await res.text()}`);
57
+ }
58
+ const { endpoint } = await res.json();
59
+ return new Sandbox(endpoint, id, options.authToken, apiUrl);
60
+ }
61
+ static async waitForReady(apiUrl, id, authToken, maxWaitMs = 60_000, pollIntervalMs = 2_000) {
62
+ const start = Date.now();
63
+ while (Date.now() - start < maxWaitMs) {
64
+ await new Promise((r) => dntShim.setTimeout(r, pollIntervalMs));
65
+ const res = await dntShim.fetch(`${apiUrl}/sandbox-sessions/${id}`, {
66
+ headers: { Authorization: `Bearer ${authToken}` },
67
+ });
68
+ if (res.ok) {
69
+ const data = await res.json();
70
+ if (data.status === "running")
71
+ return;
72
+ if (data.status === "error" || data.status === "deleting") {
73
+ throw new Error(`Sandbox failed to start: status=${data.status}`);
74
+ }
75
+ }
76
+ }
77
+ throw new Error("Sandbox did not become ready within timeout");
78
+ }
79
+ /** Execute a bash command in the sandbox and return buffered result. */
80
+ async executeCommand(command) {
81
+ let stdout = "";
82
+ let stderr = "";
83
+ let exitCode = 1;
84
+ for await (const event of this.executeStream(command)) {
85
+ switch (event.type) {
86
+ case "stdout":
87
+ stdout += event.data ?? "";
88
+ break;
89
+ case "stderr":
90
+ stderr += event.data ?? "";
91
+ break;
92
+ case "exit":
93
+ exitCode = event.exitCode ?? 1;
94
+ break;
95
+ }
96
+ }
97
+ return { stdout, stderr, exitCode };
98
+ }
99
+ /** Execute a bash command with streaming output (NDJSON). */
100
+ async *executeStream(command) {
101
+ const res = await dntShim.fetch(`${this.endpoint}/exec`, {
102
+ method: "POST",
103
+ headers: {
104
+ Authorization: `Bearer ${this.authToken}`,
105
+ "Content-Type": "application/json",
106
+ },
107
+ body: JSON.stringify({ command }),
108
+ });
109
+ if (!res.ok) {
110
+ throw new Error(`Exec failed: ${res.status} ${await res.text()}`);
111
+ }
112
+ const reader = res.body.getReader();
113
+ const decoder = new TextDecoder();
114
+ let buffer = "";
115
+ while (true) {
116
+ const { done, value } = await reader.read();
117
+ if (done)
118
+ break;
119
+ buffer += decoder.decode(value, { stream: true });
120
+ const lines = buffer.split("\n");
121
+ buffer = lines.pop();
122
+ for (const line of lines) {
123
+ if (line.trim()) {
124
+ yield JSON.parse(line);
125
+ }
126
+ }
127
+ }
128
+ if (buffer.trim()) {
129
+ yield JSON.parse(buffer);
130
+ }
131
+ }
132
+ /** Read a file from the sandbox workspace. */
133
+ async readFile(path) {
134
+ const res = await dntShim.fetch(`${this.endpoint}/file?path=${encodeURIComponent(path)}`, {
135
+ headers: { Authorization: `Bearer ${this.authToken}` },
136
+ });
137
+ if (!res.ok) {
138
+ throw new Error(`Read file failed: ${res.status} ${await res.text()}`);
139
+ }
140
+ return res.text();
141
+ }
142
+ /** Write files to the sandbox workspace. */
143
+ async writeFiles(files) {
144
+ const res = await dntShim.fetch(`${this.endpoint}/files`, {
145
+ method: "POST",
146
+ headers: {
147
+ Authorization: `Bearer ${this.authToken}`,
148
+ "Content-Type": "application/json",
149
+ },
150
+ body: JSON.stringify({ files }),
151
+ });
152
+ if (!res.ok) {
153
+ throw new Error(`Write files failed: ${res.status} ${await res.text()}`);
154
+ }
155
+ }
156
+ /** Send a heartbeat to prevent idle timeout. */
157
+ async heartbeat() {
158
+ await dntShim.fetch(`${this.apiUrl}/sandbox-sessions/${this.sessionId}/heartbeat`, {
159
+ method: "POST",
160
+ headers: { Authorization: `Bearer ${this.authToken}` },
161
+ });
162
+ }
163
+ /** Close the sandbox session and mark for deletion. */
164
+ async close() {
165
+ await dntShim.fetch(`${this.apiUrl}/sandbox-sessions/${this.sessionId}`, {
166
+ method: "DELETE",
167
+ headers: { Authorization: `Bearer ${this.authToken}` },
168
+ });
169
+ }
170
+ /** Get the session ID. */
171
+ get id() {
172
+ return this.sessionId;
173
+ }
174
+ /** Get the sandbox endpoint URL. */
175
+ get url() {
176
+ return this.endpoint;
177
+ }
178
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"import-finder.d.ts","sourceRoot":"","sources":["../../../../../../src/src/transforms/pipeline/stages/ssr-vf-modules/import-finder.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAY1D;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAU1D"}
1
+ {"version":3,"file":"import-finder.d.ts","sourceRoot":"","sources":["../../../../../../src/src/transforms/pipeline/stages/ssr-vf-modules/import-finder.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAY1D;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAiB1D"}
@@ -22,9 +22,15 @@ export function findVfModuleImports(code) {
22
22
  */
23
23
  export function findRelativeImports(code) {
24
24
  const imports = [];
25
- const pattern = /from\s*["'](\.\.?\/[^"']+)["']/g;
25
+ // Match: from "./foo" or from "../bar"
26
+ const fromPattern = /from\s*["'](\.\.?\/[^"']+)["']/g;
27
+ // Match side-effect imports: import "./foo" or import "../bar" (no `from`)
28
+ const sideEffectPattern = /import\s*["'](\.\.?\/[^"']+)["']/g;
26
29
  let match;
27
- while ((match = pattern.exec(code)) !== null) {
30
+ while ((match = fromPattern.exec(code)) !== null) {
31
+ imports.push(match[1]);
32
+ }
33
+ while ((match = sideEffectPattern.exec(code)) !== null) {
28
34
  imports.push(match[1]);
29
35
  }
30
36
  return [...new Set(imports)];