veryfront 0.1.283 → 0.1.285

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 (112) hide show
  1. package/esm/deno.d.ts +0 -8
  2. package/esm/deno.js +8 -11
  3. package/esm/src/agent/agent-service.d.ts +28 -6
  4. package/esm/src/agent/agent-service.d.ts.map +1 -1
  5. package/esm/src/agent/agent-service.js +23 -1
  6. package/esm/src/agent/index.d.ts +1 -1
  7. package/esm/src/agent/index.d.ts.map +1 -1
  8. package/esm/src/embedding/resolve.d.ts.map +1 -1
  9. package/esm/src/embedding/resolve.js +15 -2
  10. package/esm/src/embedding/veryfront-cloud/provider.d.ts.map +1 -1
  11. package/esm/src/embedding/veryfront-cloud/provider.js +2 -7
  12. package/esm/src/extensions/contracts.js +3 -1
  13. package/esm/src/extensions/interfaces/ai-provider.d.ts +50 -0
  14. package/esm/src/extensions/interfaces/ai-provider.d.ts.map +1 -0
  15. package/esm/src/extensions/interfaces/ai-provider.js +13 -0
  16. package/esm/src/extensions/interfaces/code-parser.d.ts +11 -0
  17. package/esm/src/extensions/interfaces/code-parser.d.ts.map +1 -1
  18. package/esm/src/extensions/interfaces/css-processor.d.ts +41 -22
  19. package/esm/src/extensions/interfaces/css-processor.d.ts.map +1 -1
  20. package/esm/src/extensions/interfaces/css-processor.js +10 -1
  21. package/esm/src/extensions/interfaces/index.d.ts +5 -4
  22. package/esm/src/extensions/interfaces/index.d.ts.map +1 -1
  23. package/esm/src/extensions/interfaces/index.js +1 -0
  24. package/esm/src/extensions/interfaces/schema-validator.d.ts +84 -5
  25. package/esm/src/extensions/interfaces/schema-validator.d.ts.map +1 -1
  26. package/esm/src/extensions/interfaces/schema-validator.js +5 -0
  27. package/esm/src/extensions/loader.d.ts +7 -0
  28. package/esm/src/extensions/loader.d.ts.map +1 -1
  29. package/esm/src/extensions/loader.js +12 -0
  30. package/esm/src/extensions/orchestrate.d.ts +2 -0
  31. package/esm/src/extensions/orchestrate.d.ts.map +1 -1
  32. package/esm/src/extensions/orchestrate.js +3 -0
  33. package/esm/src/extensions/recommendations.d.ts.map +1 -1
  34. package/esm/src/extensions/recommendations.js +4 -1
  35. package/esm/src/extensions/registries/ai-provider-registry.d.ts +11 -0
  36. package/esm/src/extensions/registries/ai-provider-registry.d.ts.map +1 -0
  37. package/esm/src/extensions/registries/ai-provider-registry.js +40 -0
  38. package/esm/src/html/styles-builder/plugin-loader.d.ts.map +1 -1
  39. package/esm/src/html/styles-builder/plugin-loader.js +4 -16
  40. package/esm/src/html/styles-builder/tailwind-compiler-cache.d.ts +8 -2
  41. package/esm/src/html/styles-builder/tailwind-compiler-cache.d.ts.map +1 -1
  42. package/esm/src/html/styles-builder/tailwind-compiler-cache.js +20 -3
  43. package/esm/src/provider/model-registry.d.ts.map +1 -1
  44. package/esm/src/provider/model-registry.js +33 -6
  45. package/esm/src/provider/runtime-loader/provider-embedding-responses.d.ts +1 -0
  46. package/esm/src/provider/runtime-loader/provider-embedding-responses.d.ts.map +1 -1
  47. package/esm/src/provider/runtime-loader/provider-embedding-responses.js +1 -1
  48. package/esm/src/provider/runtime-loader/provider-http.d.ts +9 -0
  49. package/esm/src/provider/runtime-loader/provider-http.d.ts.map +1 -1
  50. package/esm/src/provider/runtime-loader/provider-http.js +2 -2
  51. package/esm/src/provider/runtime-loader.d.ts +120 -9
  52. package/esm/src/provider/runtime-loader.d.ts.map +1 -1
  53. package/esm/src/provider/runtime-loader.js +13 -943
  54. package/esm/src/provider/veryfront-cloud/provider.d.ts.map +1 -1
  55. package/esm/src/provider/veryfront-cloud/provider.js +30 -15
  56. package/esm/src/sandbox/index.d.ts +1 -1
  57. package/esm/src/sandbox/index.d.ts.map +1 -1
  58. package/esm/src/sandbox/index.js +1 -1
  59. package/esm/src/sandbox/lazy-sandbox.d.ts +3 -0
  60. package/esm/src/sandbox/lazy-sandbox.d.ts.map +1 -1
  61. package/esm/src/sandbox/lazy-sandbox.js +22 -1
  62. package/esm/src/schemas/define.d.ts +31 -0
  63. package/esm/src/schemas/define.d.ts.map +1 -0
  64. package/esm/src/schemas/define.js +42 -0
  65. package/esm/src/schemas/index.d.ts +7 -2
  66. package/esm/src/schemas/index.d.ts.map +1 -1
  67. package/esm/src/schemas/index.js +10 -2
  68. package/esm/src/schemas/zod-adapter.d.ts +25 -0
  69. package/esm/src/schemas/zod-adapter.d.ts.map +1 -0
  70. package/esm/src/schemas/zod-adapter.js +120 -0
  71. package/esm/src/server/bootstrap.d.ts.map +1 -1
  72. package/esm/src/server/bootstrap.js +5 -0
  73. package/esm/src/transforms/plugins/babel-node-positions.d.ts +6 -7
  74. package/esm/src/transforms/plugins/babel-node-positions.d.ts.map +1 -1
  75. package/esm/src/transforms/plugins/babel-node-positions.js +10 -123
  76. package/esm/src/utils/version-constant.d.ts +1 -1
  77. package/esm/src/utils/version-constant.js +1 -1
  78. package/package.json +1 -6
  79. package/src/deno.js +8 -11
  80. package/src/src/agent/agent-service.ts +91 -7
  81. package/src/src/agent/index.ts +4 -0
  82. package/src/src/embedding/resolve.ts +18 -7
  83. package/src/src/embedding/veryfront-cloud/provider.ts +4 -10
  84. package/src/src/extensions/contracts.ts +3 -3
  85. package/src/src/extensions/interfaces/ai-provider.ts +54 -0
  86. package/src/src/extensions/interfaces/code-parser.ts +12 -0
  87. package/src/src/extensions/interfaces/css-processor.ts +43 -22
  88. package/src/src/extensions/interfaces/index.ts +15 -11
  89. package/src/src/extensions/interfaces/schema-validator.ts +112 -5
  90. package/src/src/extensions/loader.ts +14 -0
  91. package/src/src/extensions/orchestrate.ts +5 -0
  92. package/src/src/extensions/recommendations.ts +4 -1
  93. package/src/src/extensions/registries/ai-provider-registry.ts +53 -0
  94. package/src/src/html/styles-builder/plugin-loader.ts +4 -16
  95. package/src/src/html/styles-builder/tailwind-compiler-cache.ts +27 -6
  96. package/src/src/provider/model-registry.ts +34 -15
  97. package/src/src/provider/runtime-loader/provider-embedding-responses.ts +1 -1
  98. package/src/src/provider/runtime-loader/provider-http.ts +2 -2
  99. package/src/src/provider/runtime-loader.ts +41 -1189
  100. package/src/src/provider/veryfront-cloud/provider.ts +35 -19
  101. package/src/src/sandbox/index.ts +5 -1
  102. package/src/src/sandbox/lazy-sandbox.ts +25 -1
  103. package/src/src/schemas/define.ts +48 -0
  104. package/src/src/schemas/index.ts +13 -2
  105. package/src/src/schemas/zod-adapter.ts +180 -0
  106. package/src/src/server/bootstrap.ts +5 -0
  107. package/src/src/transforms/plugins/babel-node-positions.ts +11 -173
  108. package/src/src/utils/version-constant.ts +1 -1
  109. package/esm/src/extensions/interfaces/ai-model-provider.d.ts +0 -94
  110. package/esm/src/extensions/interfaces/ai-model-provider.d.ts.map +0 -1
  111. package/esm/src/extensions/interfaces/ai-model-provider.js +0 -8
  112. package/src/src/extensions/interfaces/ai-model-provider.ts +0 -100
@@ -17,6 +17,16 @@ import type { Extension, ExtensionContext, ExtensionLogger, ResolvedExtension }
17
17
  export class ExtensionLoader {
18
18
  private logger: ExtensionLogger;
19
19
  private setupOrder: ResolvedExtension[] = [];
20
+ private primed: Record<string, unknown> = {};
21
+
22
+ /**
23
+ * Register contracts that will be re-applied after each `setupAll()`
24
+ * teardown pass. Used by `orchestrateExtensions()` to seed infrastructure
25
+ * (e.g. `AIProviderRegistry`) before per-extension `setup()` runs.
26
+ */
27
+ primeContracts(contracts: Record<string, unknown>): void {
28
+ this.primed = { ...this.primed, ...contracts };
29
+ }
20
30
 
21
31
  constructor(logger: ExtensionLogger) {
22
32
  this.logger = logger;
@@ -154,6 +164,10 @@ export class ExtensionLoader {
154
164
  // registry even when nothing is loaded yet.
155
165
  await this.teardownAll();
156
166
 
167
+ for (const [name, impl] of Object.entries(this.primed)) {
168
+ register(name, impl);
169
+ }
170
+
157
171
  // Check for contract conflicts before loading
158
172
  const conflicts = detectConflicts(extensions);
159
173
  if (conflicts.length > 0) {
@@ -30,6 +30,8 @@ export interface OrchestrateOptions {
30
30
  projectDir: string;
31
31
  config: { extensions?: ExtensionConfigEntry[] };
32
32
  logger: ExtensionLogger;
33
+ /** Contracts to seed into the registry after teardown, before setup(). */
34
+ primeContracts?: Record<string, unknown>;
33
35
  /** @internal Override discovery functions in tests. */
34
36
  discovery?: {
35
37
  discoverPackageExtensions: typeof defaultDiscovery.discoverPackageExtensions;
@@ -167,6 +169,9 @@ export async function orchestrateExtensions(
167
169
  );
168
170
 
169
171
  const loader = new ExtensionLoader(logger);
172
+ if (options.primeContracts) {
173
+ loader.primeContracts(options.primeContracts);
174
+ }
170
175
  await loader.setupAll(merged, config as Record<string, unknown>);
171
176
  return loader;
172
177
  }
@@ -13,7 +13,10 @@ const recommendations = new Map<string, string>([
13
13
  ["DatabaseClient", "@veryfront/ext-postgres"],
14
14
  ["AuthProvider", "@veryfront/ext-jwt"],
15
15
  ["TracingExporter", "@veryfront/ext-opentelemetry"],
16
- ["AIModelProvider", "@veryfront/ext-openai"],
16
+ ["AIProviderRegistry", "@veryfront/ext-openai"],
17
+ ["AIProvider:openai", "@veryfront/ext-openai"],
18
+ ["AIProvider:anthropic", "@veryfront/ext-anthropic"],
19
+ ["AIProvider:google", "@veryfront/ext-google"],
17
20
  ["EmbeddingProvider", "@veryfront/ext-embeddings"],
18
21
  ["CodeParser", "@veryfront/ext-babel"],
19
22
  ["SchemaValidator", "@veryfront/ext-zod"],
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Default Map-backed implementation of the AIProviderRegistry contract.
3
+ *
4
+ * Preserves insertion order via Map (used by `list()`). Throws on
5
+ * duplicate id to surface silent collisions between extensions.
6
+ *
7
+ * @module extensions/registries/ai-provider-registry
8
+ */
9
+
10
+ import type { AIProvider, AIProviderRegistry } from "../interfaces/ai-provider.js";
11
+
12
+ class AIProviderRegistryImpl implements AIProviderRegistry {
13
+ private readonly providers = new Map<string, AIProvider>();
14
+
15
+ register(provider: AIProvider): void {
16
+ if (this.providers.has(provider.id)) {
17
+ throw new Error(
18
+ `AIProvider "${provider.id}" is already registered. ` +
19
+ `Call unregister("${provider.id}") first if you intend to replace it.`,
20
+ );
21
+ }
22
+ this.providers.set(provider.id, provider);
23
+ }
24
+
25
+ unregister(id: string): void {
26
+ this.providers.delete(id);
27
+ }
28
+
29
+ get(id: string): AIProvider | undefined {
30
+ return this.providers.get(id);
31
+ }
32
+
33
+ require(id: string): AIProvider {
34
+ const p = this.providers.get(id);
35
+ if (p) return p;
36
+ const known = [...this.providers.keys()].join(", ") || "(none)";
37
+ throw new Error(
38
+ `No AIProvider registered for "${id}". Known providers: ${known}.`,
39
+ );
40
+ }
41
+
42
+ has(id: string): boolean {
43
+ return this.providers.has(id);
44
+ }
45
+
46
+ list(): AIProvider[] {
47
+ return [...this.providers.values()];
48
+ }
49
+ }
50
+
51
+ export function createAIProviderRegistry(): AIProviderRegistry {
52
+ return new AIProviderRegistryImpl();
53
+ }
@@ -9,9 +9,6 @@
9
9
  import * as dntShim from "../../../_dnt.shims.js";
10
10
 
11
11
 
12
- import plugin from "tailwindcss/plugin";
13
- import defaultTheme from "tailwindcss/defaultTheme";
14
- import colors from "tailwindcss/colors";
15
12
  import { serverLogger } from "../../utils/index.js";
16
13
  import {
17
14
  type ErrorSlug,
@@ -70,19 +67,10 @@ try {
70
67
  });
71
68
  }
72
69
 
73
- // Set up global shims for tailwindcss subpaths - used by dynamically loaded plugins
74
- (dntShim.dntGlobalThis as Record<string, unknown>).__tailwindPluginShim = {
75
- default: plugin,
76
- __esModule: true,
77
- };
78
- (dntShim.dntGlobalThis as Record<string, unknown>).__tailwindDefaultThemeShim = {
79
- default: defaultTheme,
80
- __esModule: true,
81
- };
82
- (dntShim.dntGlobalThis as Record<string, unknown>).__tailwindColorsShim = {
83
- default: colors,
84
- __esModule: true,
85
- };
70
+ // Global shims for `tailwindcss/plugin`, `tailwindcss/defaultTheme`, and
71
+ // `tailwindcss/colors` used by dynamically loaded plugin bundles are installed
72
+ // by the `@veryfront/ext-tailwind` extension's `setup()` hook — they depend on
73
+ // tailwindcss imports that live in the extension package, not in core.
86
74
 
87
75
  function isRealDenoRuntime(): boolean {
88
76
  return typeof dntShim.Deno !== "undefined" && typeof dntShim.Deno.version === "object";
@@ -5,10 +5,17 @@
5
5
  * stylesheet hash. Prevents race conditions when concurrent requests use
6
6
  * different stylesheets.
7
7
  *
8
+ * The actual tailwindcss `compile()` call is routed through the
9
+ * `CSSProcessor` extension contract (default implementation:
10
+ * `@veryfront/ext-tailwind`). When no `CSSProcessor` is registered, the
11
+ * compile path returns a no-op compiler that emits empty CSS and logs an
12
+ * actionable install message.
13
+ *
8
14
  * @module html/styles-builder/tailwind-compiler-cache
9
15
  */
10
16
 
11
- import { compile } from "tailwindcss";
17
+ import { tryResolve as tryResolveContract } from "../../extensions/contracts.js";
18
+ import type { CSSCompiler, CSSProcessor } from "../../extensions/interfaces/index.js";
12
19
  import { serverLogger } from "../../utils/index.js";
13
20
  import { DEPENDENCY_MISSING, NETWORK_ERROR } from "../../errors/index.js";
14
21
  import { getTailwindCSSUrl } from "../../utils/constants/cdn.js";
@@ -23,7 +30,7 @@ const logger = serverLogger.component("tailwind");
23
30
  * Each entry stores the compiler and its associated plugin state.
24
31
  */
25
32
  interface CompilerCacheEntry {
26
- compiler: Awaited<ReturnType<typeof compile>>;
33
+ compiler: CSSCompiler;
27
34
  createdAt: number;
28
35
  pluginCache: Map<string, unknown>;
29
36
  pluginErrors: Map<string, Error>;
@@ -86,7 +93,7 @@ function evictOldestCompiler(): void {
86
93
  export async function getCompiler(
87
94
  stylesheet: string,
88
95
  projectSlug?: string,
89
- ): Promise<Awaited<ReturnType<typeof compile>>> {
96
+ ): Promise<CSSCompiler> {
90
97
  // Tailwind v4's compile().build() is stateful — it accumulates candidates
91
98
  // across calls. Without per-project isolation, projects sharing the same
92
99
  // stylesheet on the shared pool contaminate each other's CSS output.
@@ -101,11 +108,26 @@ export async function getCompiler(
101
108
 
102
109
  logger.debug("Creating new compiler", { hash, projectSlug });
103
110
 
111
+ const processor = tryResolveContract<CSSProcessor>("CSSProcessor");
112
+ if (!processor) {
113
+ logger.warn(
114
+ "No CSSProcessor extension registered — CSS output will be empty. Install it with: deno add @veryfront/ext-tailwind",
115
+ );
116
+ const noopCompiler: CSSCompiler = { build: () => "" };
117
+ compilerCache.set(hash, {
118
+ compiler: noopCompiler,
119
+ createdAt: Date.now(),
120
+ pluginCache: new Map(),
121
+ pluginErrors: new Map(),
122
+ });
123
+ return noopCompiler;
124
+ }
125
+
104
126
  const tailwindBase = await getTailwindBaseCSS();
105
127
  const pluginCache = new Map<string, unknown>();
106
128
  const pluginErrors = new Map<string, Error>();
107
129
 
108
- const newCompiler = await compile(stylesheet, {
130
+ const newCompiler = await processor.compile(stylesheet, {
109
131
  base: "/",
110
132
  loadStylesheet: (id: string) => {
111
133
  if (id === "tailwindcss") {
@@ -121,8 +143,7 @@ export async function getCompiler(
121
143
  detail: `Failed to load plugin "${id}": plugin not installed`,
122
144
  });
123
145
  }
124
- // deno-lint-ignore no-explicit-any -- dynamically loaded plugin cannot be statically verified against Tailwind's Plugin | Config type
125
- return { module: loaded as any, base: "/", path: "/" };
146
+ return { module: loaded, base: "/", path: "/" };
126
147
  },
127
148
  });
128
149
 
@@ -19,6 +19,9 @@ import {
19
19
  getGoogleGenAIEnvConfig,
20
20
  getOpenAIEnvConfig,
21
21
  } from "../config/env.js";
22
+ import { tryResolve } from "../extensions/contracts.js";
23
+ import type { AIProviderRegistry } from "../extensions/interfaces/index.js";
24
+ import { AIProviderRegistryName } from "../extensions/interfaces/index.js";
22
25
  import { ProjectScopedRegistryManager } from "../registry/project-scoped-registry-manager.js";
23
26
  import { serverLogger } from "../utils/index.js";
24
27
  import { DEFAULT_LOCAL_MODEL } from "./local/model-catalog.js";
@@ -29,11 +32,7 @@ import {
29
32
  getDefaultVeryfrontCloudModel,
30
33
  isVeryfrontCloudEnabled,
31
34
  } from "../platform/cloud/resolver.js";
32
- import {
33
- createAnthropicModelRuntime,
34
- createGoogleModelRuntime,
35
- createOpenAIModelRuntime,
36
- } from "./runtime-loader.js";
35
+ import { createGoogleModelRuntime } from "./runtime-loader.js";
37
36
  import { createVeryfrontCloudModel } from "./veryfront-cloud/provider.js";
38
37
  import { getModelRuntimeId, hasLocalModelRuntimeMarker } from "./runtime-inspection.js";
39
38
  import type { ModelRuntime } from "./types.js";
@@ -92,10 +91,18 @@ function autoInitializeFromEnv(): void {
92
91
  }),
93
92
  );
94
93
  }
95
- return createOpenAIModelRuntime(
96
- { apiKey: config.apiKey, baseURL: config.baseURL },
97
- id,
98
- );
94
+ const registry = tryResolve<AIProviderRegistry>(AIProviderRegistryName);
95
+ const provider = registry?.get("openai");
96
+ if (provider) {
97
+ return provider.createModel(id, {
98
+ credential: config.apiKey,
99
+ baseURL: config.baseURL,
100
+ });
101
+ }
102
+ throw toError(createError({
103
+ type: "config",
104
+ message: "OpenAI provider not installed. Add @veryfront/ext-openai to use openai/* models.",
105
+ }));
99
106
  });
100
107
  }
101
108
 
@@ -111,13 +118,19 @@ function autoInitializeFromEnv(): void {
111
118
  }),
112
119
  );
113
120
  }
114
- return createAnthropicModelRuntime(
115
- {
116
- apiKey: config.apiKey,
121
+ const registry = tryResolve<AIProviderRegistry>(AIProviderRegistryName);
122
+ const provider = registry?.get("anthropic");
123
+ if (provider) {
124
+ return provider.createModel(id, {
125
+ credential: config.apiKey,
117
126
  baseURL: config.baseURL,
118
- },
119
- id,
120
- );
127
+ });
128
+ }
129
+ throw toError(createError({
130
+ type: "config",
131
+ message:
132
+ "Anthropic provider not installed. Add @veryfront/ext-anthropic to use anthropic/* models.",
133
+ }));
121
134
  });
122
135
  }
123
136
 
@@ -207,15 +220,21 @@ function isMissingProviderConfiguration(errorData: ReturnType<typeof fromError>)
207
220
  */
208
221
  export function findAvailableCloudModel(): string | null {
209
222
  autoInitializeFromEnv();
223
+ const registry = tryResolve<AIProviderRegistry>(AIProviderRegistryName);
210
224
  for (const { provider, model, hasKey } of CLOUD_UPGRADE_CANDIDATES) {
211
225
  if (!hasKey()) continue;
212
226
  if (!manager.has(provider)) continue;
227
+ if (registry && !registry.has(provider) && !isBuiltinProvider(provider)) continue;
213
228
  const resolvedModel = typeof model === "function" ? model() : model;
214
229
  return `${provider}/${resolvedModel}`;
215
230
  }
216
231
  return null;
217
232
  }
218
233
 
234
+ function isBuiltinProvider(provider: string): boolean {
235
+ return provider === "google" || provider === "veryfront-cloud";
236
+ }
237
+
219
238
  /**
220
239
  * Resolve a "provider/model" string to a framework-compatible model runtime.
221
240
  *
@@ -1,6 +1,6 @@
1
1
  import { readRecord } from "./provider-records.js";
2
2
 
3
- function isNumberArray(value: unknown): value is number[] {
3
+ export function isNumberArray(value: unknown): value is number[] {
4
4
  return Array.isArray(value) && value.every((entry) => typeof entry === "number");
5
5
  }
6
6
 
@@ -44,7 +44,7 @@ export class ProviderQuotaError extends ProviderError {}
44
44
  /** Non-retryable 4xx/5xx that doesn't fit another bucket. */
45
45
  export class ProviderRequestError extends ProviderError {}
46
46
 
47
- function parseRetryAfterMs(header: string | null): number | undefined {
47
+ export function parseRetryAfterMs(header: string | null): number | undefined {
48
48
  if (!header) return undefined;
49
49
  const asNumber = Number(header);
50
50
  if (Number.isFinite(asNumber) && asNumber >= 0) {
@@ -65,7 +65,7 @@ function parseRetryAfterMs(header: string | null): number | undefined {
65
65
  * where HTTP status alone is ambiguous — notably OpenAI
66
66
  * `insufficient_quota` vs `rate_limit_exceeded` both arriving as 429.
67
67
  */
68
- async function buildProviderError(
68
+ export async function buildProviderError(
69
69
  provider: ProviderKind,
70
70
  response: Response,
71
71
  ): Promise<ProviderError> {