@builder.io/ai-utils 0.81.0 → 0.81.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@builder.io/ai-utils",
3
- "version": "0.81.0",
3
+ "version": "0.81.3",
4
4
  "description": "Builder.io AI utils",
5
5
  "files": [
6
6
  "src"
@@ -20,18 +20,18 @@ export declare const BuilderConfigDatabaseSchema: z.ZodObject<{
20
20
  export type BuilderConfigDatabase = z.infer<typeof BuilderConfigDatabaseSchema>;
21
21
  /** `hosting` block in `builder.config.json` — see First Class Hosting spec. */
22
22
  export declare const BuilderConfigHostingEnvironmentSchema: z.ZodObject<{
23
- build: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
24
- prod: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
23
+ build: z.ZodCatch<z.ZodOptional<z.ZodPreprocess<z.ZodRecord<z.ZodString, z.ZodString>>>>;
24
+ prod: z.ZodCatch<z.ZodOptional<z.ZodPreprocess<z.ZodRecord<z.ZodString, z.ZodString>>>>;
25
25
  }, z.core.$strip>;
26
26
  export type BuilderConfigHostingEnvironment = z.infer<typeof BuilderConfigHostingEnvironmentSchema>;
27
27
  export declare const BuilderConfigHostingSchema: z.ZodObject<{
28
- buildCommand: z.ZodOptional<z.ZodString>;
29
- nodeVersion: z.ZodOptional<z.ZodString>;
30
- buildOutputDir: z.ZodOptional<z.ZodString>;
31
- environment: z.ZodOptional<z.ZodObject<{
32
- build: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
33
- prod: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
34
- }, z.core.$strip>>;
28
+ buildCommand: z.ZodCatch<z.ZodOptional<z.ZodString>>;
29
+ nodeVersion: z.ZodCatch<z.ZodOptional<z.ZodPipe<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>, z.ZodTransform<string, string | number>>>>;
30
+ buildOutputDir: z.ZodCatch<z.ZodOptional<z.ZodString>>;
31
+ environment: z.ZodCatch<z.ZodOptional<z.ZodObject<{
32
+ build: z.ZodCatch<z.ZodOptional<z.ZodPreprocess<z.ZodRecord<z.ZodString, z.ZodString>>>>;
33
+ prod: z.ZodCatch<z.ZodOptional<z.ZodPreprocess<z.ZodRecord<z.ZodString, z.ZodString>>>>;
34
+ }, z.core.$strip>>>;
35
35
  }, z.core.$strip>;
36
36
  export type BuilderConfigHosting = z.infer<typeof BuilderConfigHostingSchema>;
37
37
  export declare const BuilderConfigSchema: z.ZodObject<{
@@ -41,13 +41,13 @@ export declare const BuilderConfigSchema: z.ZodObject<{
41
41
  schemaDir: z.ZodDefault<z.ZodString>;
42
42
  }, z.core.$strip>>;
43
43
  hosting: z.ZodOptional<z.ZodObject<{
44
- buildCommand: z.ZodOptional<z.ZodString>;
45
- nodeVersion: z.ZodOptional<z.ZodString>;
46
- buildOutputDir: z.ZodOptional<z.ZodString>;
47
- environment: z.ZodOptional<z.ZodObject<{
48
- build: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
49
- prod: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
50
- }, z.core.$strip>>;
44
+ buildCommand: z.ZodCatch<z.ZodOptional<z.ZodString>>;
45
+ nodeVersion: z.ZodCatch<z.ZodOptional<z.ZodPipe<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>, z.ZodTransform<string, string | number>>>>;
46
+ buildOutputDir: z.ZodCatch<z.ZodOptional<z.ZodString>>;
47
+ environment: z.ZodCatch<z.ZodOptional<z.ZodObject<{
48
+ build: z.ZodCatch<z.ZodOptional<z.ZodPreprocess<z.ZodRecord<z.ZodString, z.ZodString>>>>;
49
+ prod: z.ZodCatch<z.ZodOptional<z.ZodPreprocess<z.ZodRecord<z.ZodString, z.ZodString>>>>;
50
+ }, z.core.$strip>>>;
51
51
  }, z.core.$strip>>;
52
52
  }, z.core.$strip>;
53
53
  export type BuilderConfig = z.infer<typeof BuilderConfigSchema>;
@@ -17,16 +17,45 @@ export const BuilderConfigDatabaseSchema = z.object({
17
17
  migrations: z.literal("drizzle"),
18
18
  schemaDir: z.string().default("drizzle"),
19
19
  });
20
+ /**
21
+ * Env values are always strings at runtime, but JSON authors commonly write
22
+ * booleans/numbers (e.g. `"DISABLE_AUTH": true`). Coerce them to strings rather
23
+ * than rejecting, and drop any single value that can't be coerced (object/array/
24
+ * null) instead of failing the whole map — a malformed value must not silently
25
+ * discard the entire hosting config downstream.
26
+ */
27
+ const HostingEnvRecordSchema = z.preprocess((input) => {
28
+ if (!input || typeof input !== "object" || Array.isArray(input)) {
29
+ return input;
30
+ }
31
+ const result = {};
32
+ for (const [key, value] of Object.entries(input)) {
33
+ if (typeof value === "string" ||
34
+ typeof value === "number" ||
35
+ typeof value === "boolean") {
36
+ result[key] = String(value);
37
+ }
38
+ }
39
+ return result;
40
+ }, z.record(z.string(), z.string()));
20
41
  /** `hosting` block in `builder.config.json` — see First Class Hosting spec. */
21
42
  export const BuilderConfigHostingEnvironmentSchema = z.object({
22
- build: z.record(z.string(), z.string()).optional(),
23
- prod: z.record(z.string(), z.string()).optional(),
43
+ build: HostingEnvRecordSchema.optional().catch(undefined),
44
+ prod: HostingEnvRecordSchema.optional().catch(undefined),
24
45
  });
46
+ // `nodeVersion` is commonly authored as a JSON number (e.g. `"nodeVersion": 20`),
47
+ // so coerce it to a string. `buildCommand`/`buildOutputDir` accept strings only.
48
+ const NodeVersionSchema = z
49
+ .union([z.string(), z.number()])
50
+ .transform((value) => String(value));
51
+ // `.catch(undefined)` per field so one malformed field (e.g. an object-valued
52
+ // buildOutputDir) is dropped individually instead of invalidating the whole
53
+ // hosting block.
25
54
  export const BuilderConfigHostingSchema = z.object({
26
- buildCommand: z.string().optional(),
27
- nodeVersion: z.string().optional(),
28
- buildOutputDir: z.string().optional(),
29
- environment: BuilderConfigHostingEnvironmentSchema.optional(),
55
+ buildCommand: z.string().optional().catch(undefined),
56
+ nodeVersion: NodeVersionSchema.optional().catch(undefined),
57
+ buildOutputDir: z.string().optional().catch(undefined),
58
+ environment: BuilderConfigHostingEnvironmentSchema.optional().catch(undefined),
30
59
  });
31
60
  export const BuilderConfigSchema = z.object({
32
61
  database: BuilderConfigDatabaseSchema.optional(),
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,57 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { BuilderConfigHostingSchema } from "./builder-config";
3
+ describe("BuilderConfigHostingSchema", () => {
4
+ it("coerces boolean/number env values to strings", () => {
5
+ var _a, _b;
6
+ const parsed = BuilderConfigHostingSchema.parse({
7
+ buildOutputDir: "dist",
8
+ environment: {
9
+ prod: { DISABLE_AUTH: true },
10
+ build: { PORT: 3000, NITRO_PRESET: "netlify" },
11
+ },
12
+ });
13
+ expect(parsed.buildOutputDir).toBe("dist");
14
+ expect((_a = parsed.environment) === null || _a === void 0 ? void 0 : _a.prod).toEqual({ DISABLE_AUTH: "true" });
15
+ expect((_b = parsed.environment) === null || _b === void 0 ? void 0 : _b.build).toEqual({
16
+ PORT: "3000",
17
+ NITRO_PRESET: "netlify",
18
+ });
19
+ });
20
+ it("coerces a numeric nodeVersion to a string", () => {
21
+ const parsed = BuilderConfigHostingSchema.parse({
22
+ nodeVersion: 20,
23
+ buildOutputDir: "dist",
24
+ });
25
+ expect(parsed.nodeVersion).toBe("20");
26
+ expect(parsed.buildOutputDir).toBe("dist");
27
+ });
28
+ it("does not coerce numeric buildCommand/buildOutputDir (strings only)", () => {
29
+ const parsed = BuilderConfigHostingSchema.parse({
30
+ buildCommand: 123,
31
+ buildOutputDir: 456,
32
+ nodeVersion: "20",
33
+ });
34
+ expect(parsed.buildCommand).toBeUndefined();
35
+ expect(parsed.buildOutputDir).toBeUndefined();
36
+ expect(parsed.nodeVersion).toBe("20");
37
+ });
38
+ it("drops a single uncoercible env value but keeps the rest of the block", () => {
39
+ var _a;
40
+ const parsed = BuilderConfigHostingSchema.parse({
41
+ buildOutputDir: "dist",
42
+ environment: {
43
+ prod: { GOOD: "yes", BAD: { nested: "object" } },
44
+ },
45
+ });
46
+ expect(parsed.buildOutputDir).toBe("dist");
47
+ expect((_a = parsed.environment) === null || _a === void 0 ? void 0 : _a.prod).toEqual({ GOOD: "yes" });
48
+ });
49
+ it("drops a malformed field instead of invalidating the whole block", () => {
50
+ const parsed = BuilderConfigHostingSchema.parse({
51
+ buildCommand: "npm run build",
52
+ buildOutputDir: { nested: "object" },
53
+ });
54
+ expect(parsed.buildCommand).toBe("npm run build");
55
+ expect(parsed.buildOutputDir).toBeUndefined();
56
+ });
57
+ });
package/src/projects.d.ts CHANGED
@@ -487,7 +487,9 @@ export interface OrgAgentConfig {
487
487
  enabledTools: string[];
488
488
  longLived: boolean;
489
489
  }
490
- export type BranchType = "code-review" | "setup-project" | "org-agent" | "snapshot-build" | "design-system-indexing" | "deploy" | "default";
490
+ export type BranchType = "code-review" | "setup-project"
491
+ /** Hidden branch the webapp creates when the user picks manual setup. */
492
+ | "manual-setup" | "org-agent" | "snapshot-build" | "design-system-indexing" | "deploy" | "default";
491
493
  /** Category of work a branch represents, auto-assigned during prompt analysis. */
492
494
  export type BranchCategory = "feature" | "fix" | "research" | "other";
493
495
  export interface BranchSharedData {
@@ -1613,6 +1615,8 @@ export type DeployListItem = z.infer<typeof DeployListItemSchema>;
1613
1615
  export declare const DeployArtifactManifestSchema: z.ZodObject<{
1614
1616
  files: z.ZodRecord<z.ZodString, z.ZodString>;
1615
1617
  functions: z.ZodRecord<z.ZodString, z.ZodString>;
1618
+ functions_config: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
1619
+ function_invocation_modes: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
1616
1620
  }, z.core.$strip>;
1617
1621
  export type DeployArtifactManifest = z.infer<typeof DeployArtifactManifestSchema>;
1618
1622
  /**
@@ -1733,4 +1737,9 @@ export declare const DuplicateBranchOptionsSchema: z.ZodObject<{
1733
1737
  friendlyName: z.ZodOptional<z.ZodString>;
1734
1738
  }, z.core.$strip>;
1735
1739
  export type DuplicateBranchOptions = z.infer<typeof DuplicateBranchOptionsSchema>;
1740
+ export declare const EnsureMainBranchExistsOptionsSchema: z.ZodObject<{
1741
+ projectId: z.ZodString;
1742
+ branchName: z.ZodString;
1743
+ }, z.core.$strip>;
1744
+ export type EnsureMainBranchExistsOptions = z.infer<typeof EnsureMainBranchExistsOptionsSchema>;
1736
1745
  export {};
package/src/projects.js CHANGED
@@ -462,6 +462,20 @@ export const DeployArtifactManifestSchema = z.object({
462
462
  functions: z.record(z.string(), z.string()).meta({
463
463
  description: "serverless function name → sha256 hash",
464
464
  }),
465
+ // Netlify Functions v2 routing config: function name → config object.
466
+ // Kept as a loose record so ai-utils does not need to depend on the Netlify
467
+ // API package for the exact functionConfig schema.
468
+ functions_config: z
469
+ .record(z.string(), z.record(z.string(), z.unknown()))
470
+ .optional()
471
+ .meta({
472
+ description: "Netlify Functions v2 routing config per function name",
473
+ }),
474
+ // Lambda invocation mode per function: "stream" for v2 functions using
475
+ // awslambda.streamifyResponse bootstrap; absent/undefined means buffered.
476
+ function_invocation_modes: z.record(z.string(), z.string()).optional().meta({
477
+ description: 'Lambda invocation mode per function name (e.g. "stream" for v2 streaming functions)',
478
+ }),
465
479
  });
466
480
  /**
467
481
  * Per-deploy overrides passed from ai-services to the deploy pod's build-and-upload endpoint.
@@ -645,3 +659,11 @@ export const DuplicateBranchOptionsSchema = z.object({
645
659
  description: "Optional friendly (display) name for the new branch.",
646
660
  }),
647
661
  });
662
+ export const EnsureMainBranchExistsOptionsSchema = z.object({
663
+ projectId: z.string().min(1).meta({
664
+ description: "Project to ensure the main branch exists for.",
665
+ }),
666
+ branchName: z.string().min(1).meta({
667
+ description: "Branch whose head ref seeds the main branch when it doesn't exist yet. No-op for non-internalHost projects.",
668
+ }),
669
+ });