@builder.io/ai-utils 0.81.1 → 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.1",
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 {
@@ -1735,4 +1737,9 @@ export declare const DuplicateBranchOptionsSchema: z.ZodObject<{
1735
1737
  friendlyName: z.ZodOptional<z.ZodString>;
1736
1738
  }, z.core.$strip>;
1737
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>;
1738
1745
  export {};
package/src/projects.js CHANGED
@@ -659,3 +659,11 @@ export const DuplicateBranchOptionsSchema = z.object({
659
659
  description: "Optional friendly (display) name for the new branch.",
660
660
  }),
661
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
+ });