@builder.io/ai-utils 0.22.2 → 0.22.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.22.2",
3
+ "version": "0.22.3",
4
4
  "description": "Builder.io AI utils",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
package/src/codegen.d.ts CHANGED
@@ -2,7 +2,7 @@ import type { Attachment, ContentMessageItemToolResult } from "./messages";
2
2
  import type { BuilderContent } from "./completion";
3
3
  import type { Options as PrettierOptions } from "prettier";
4
4
  import type { UserContext } from "./mapping";
5
- import type { ForcedBackup, SetupDependency } from "./projects";
5
+ import type { ForcedBackup, SetupDependency, GitDiagnostics } from "./projects";
6
6
  import type { Feature } from "./features";
7
7
  import type { CpuKind } from "./projects";
8
8
  export type ImportType = "named" | "default";
@@ -192,7 +192,7 @@ export interface BuilderEditToolInput {
192
192
  new_str: string;
193
193
  }
194
194
  export interface GetScreenshotToolInput {
195
- href: string;
195
+ href?: string;
196
196
  url?: string;
197
197
  selector?: string;
198
198
  width?: number;
@@ -1467,6 +1467,11 @@ export interface FusionConfig {
1467
1467
  * Errors matching these patterns will not show the error popup.
1468
1468
  */
1469
1469
  errorIgnorePatterns?: string[];
1470
+ /**
1471
+ * Maximum number of agent completions before pausing to ask the user to continue.
1472
+ * Read from project settings, with fallback to organization/space settings.
1473
+ */
1474
+ maxAgentCompletions?: number;
1470
1475
  /** @deprecated use devCommand */
1471
1476
  command?: string;
1472
1477
  }
@@ -1512,6 +1517,7 @@ export interface InitState {
1512
1517
  success: boolean;
1513
1518
  currentStep: InitStateStep;
1514
1519
  error: string | undefined;
1520
+ gitDiagnostics?: GitDiagnostics;
1515
1521
  repos: {
1516
1522
  repoName: string;
1517
1523
  enabledGit: boolean;
@@ -1,6 +1,6 @@
1
1
  export type { Source, TestId, Test, RunChecksInput, ProgressEvent, CheckResult, CheckReport, ConnectivityErrorCode, CheckType, Recommendation, LikelyCause, ConnectivityStatus, AnalysisResult, AnalyzeConnectivityInput, } from "./types.js";
2
2
  export { runChecks } from "./run-checks.browser.js";
3
- export { mapNodeErrorToConnectivityCode, mapHttpStatusToErrorCode, mapFetchErrorToConnectivityCode, SELF_SIGNED_CERT_ERRORS, CERT_EXPIRED_ERRORS, CERT_NOT_YET_VALID_ERRORS, CERT_INVALID_ERRORS, CERT_HOSTNAME_MISMATCH_ERRORS, SSL_PROTOCOL_ERRORS, SSL_HANDSHAKE_ERRORS, NETWORK_UNREACHABLE_ERRORS, TIMEOUT_ERRORS, PROXY_ERRORS, DNS_ERRORS, } from "./error-codes.js";
3
+ export { mapNodeErrorToConnectivityCode, mapHttpStatusToErrorCode, mapFetchErrorToConnectivityCode, connectivityErrorCodeToLikelyCause, mapConnectivityErrorMessage, SELF_SIGNED_CERT_ERRORS, CERT_EXPIRED_ERRORS, CERT_NOT_YET_VALID_ERRORS, CERT_INVALID_ERRORS, CERT_HOSTNAME_MISMATCH_ERRORS, SSL_PROTOCOL_ERRORS, SSL_HANDSHAKE_ERRORS, NETWORK_UNREACHABLE_ERRORS, TIMEOUT_ERRORS, PROXY_ERRORS, DNS_ERRORS, } from "./error-codes.js";
4
4
  export { BUILDER_TARGETS, DEFAULT_PORTS, resolveTarget, extractHostname, extractPort, } from "./targets.js";
5
5
  export { isBrowser, isNode, getCheckTypeForTestId, isCheckAvailable, getUnavailabilityReason, } from "./environment.js";
6
6
  export { httpCheck } from "./checks/http-check.js";
@@ -1,5 +1,5 @@
1
1
  export { runChecks } from "./run-checks.browser.js";
2
- export { mapNodeErrorToConnectivityCode, mapHttpStatusToErrorCode, mapFetchErrorToConnectivityCode, SELF_SIGNED_CERT_ERRORS, CERT_EXPIRED_ERRORS, CERT_NOT_YET_VALID_ERRORS, CERT_INVALID_ERRORS, CERT_HOSTNAME_MISMATCH_ERRORS, SSL_PROTOCOL_ERRORS, SSL_HANDSHAKE_ERRORS, NETWORK_UNREACHABLE_ERRORS, TIMEOUT_ERRORS, PROXY_ERRORS, DNS_ERRORS, } from "./error-codes.js";
2
+ export { mapNodeErrorToConnectivityCode, mapHttpStatusToErrorCode, mapFetchErrorToConnectivityCode, connectivityErrorCodeToLikelyCause, mapConnectivityErrorMessage, SELF_SIGNED_CERT_ERRORS, CERT_EXPIRED_ERRORS, CERT_NOT_YET_VALID_ERRORS, CERT_INVALID_ERRORS, CERT_HOSTNAME_MISMATCH_ERRORS, SSL_PROTOCOL_ERRORS, SSL_HANDSHAKE_ERRORS, NETWORK_UNREACHABLE_ERRORS, TIMEOUT_ERRORS, PROXY_ERRORS, DNS_ERRORS, } from "./error-codes.js";
3
3
  export { BUILDER_TARGETS, DEFAULT_PORTS, resolveTarget, extractHostname, extractPort, } from "./targets.js";
4
4
  export { isBrowser, isNode, getCheckTypeForTestId, isCheckAvailable, getUnavailabilityReason, } from "./environment.js";
5
5
  export { httpCheck } from "./checks/http-check.js";
@@ -1,4 +1,4 @@
1
- import type { ConnectivityErrorCode } from "./types.js";
1
+ import type { ConnectivityErrorCode, CheckType, LikelyCause } from "./types.js";
2
2
  export declare const SELF_SIGNED_CERT_ERRORS: Set<string>;
3
3
  export declare const CERT_EXPIRED_ERRORS: Set<string>;
4
4
  export declare const CERT_NOT_YET_VALID_ERRORS: Set<string>;
@@ -19,3 +19,18 @@ export declare function mapFetchErrorToConnectivityCode(error: Error & {
19
19
  code?: string;
20
20
  };
21
21
  }): ConnectivityErrorCode;
22
+ /**
23
+ * Map a connectivity error code to a likely cause for recommendations.
24
+ * Shared by the connectivity analyzer and git error diagnostics so both
25
+ * show consistent likely-cause messaging.
26
+ */
27
+ export declare function connectivityErrorCodeToLikelyCause(errorCode: ConnectivityErrorCode | undefined): LikelyCause | undefined;
28
+ /**
29
+ * Map a connectivity error message string (e.g. from a simple DNS/TCP check)
30
+ * to a connectivity error code and check type. Used when building GitDiagnostics
31
+ * from checks that don't use the full runChecks/CheckResult pipeline.
32
+ */
33
+ export declare function mapConnectivityErrorMessage(errorMessage: string): {
34
+ connectivityErrorCode: ConnectivityErrorCode;
35
+ checkType: CheckType;
36
+ } | null;
@@ -165,3 +165,104 @@ export function mapFetchErrorToConnectivityCode(error) {
165
165
  }
166
166
  return "unknown_error";
167
167
  }
168
+ /**
169
+ * Map a connectivity error code to a likely cause for recommendations.
170
+ * Shared by the connectivity analyzer and git error diagnostics so both
171
+ * show consistent likely-cause messaging.
172
+ */
173
+ export function connectivityErrorCodeToLikelyCause(errorCode) {
174
+ if (!errorCode)
175
+ return undefined;
176
+ const timeoutCodes = [
177
+ "tcp_connection_timeout",
178
+ "tcp_host_unreachable",
179
+ "tcp_network_unreachable",
180
+ ];
181
+ if (timeoutCodes.includes(errorCode))
182
+ return "ip_whitelisting_required";
183
+ const dnsCodes = [
184
+ "dns_resolution_failed",
185
+ "dns_timeout",
186
+ "dns_wrong_ip",
187
+ ];
188
+ if (dnsCodes.includes(errorCode))
189
+ return "dns_misconfiguration";
190
+ const tlsCodes = [
191
+ "tls_self_signed_cert",
192
+ "tls_cert_expired",
193
+ "tls_cert_not_yet_valid",
194
+ "tls_cert_invalid",
195
+ "tls_cert_hostname_mismatch",
196
+ "tls_handshake_failed",
197
+ "tls_protocol_error",
198
+ ];
199
+ if (tlsCodes.includes(errorCode))
200
+ return "self_signed_certificate";
201
+ const firewallCodes = [
202
+ "tcp_connection_refused",
203
+ "tcp_connection_reset",
204
+ ];
205
+ if (firewallCodes.includes(errorCode))
206
+ return "firewall_blocking";
207
+ const proxyCodes = [
208
+ "proxy_auth_required",
209
+ "proxy_connection_failed",
210
+ "proxy_tunnel_failed",
211
+ ];
212
+ if (proxyCodes.includes(errorCode))
213
+ return "corporate_proxy_required";
214
+ if (errorCode === "http_service_unavailable" ||
215
+ errorCode === "http_server_error") {
216
+ return "server_unavailable";
217
+ }
218
+ return undefined;
219
+ }
220
+ /**
221
+ * Map a connectivity error message string (e.g. from a simple DNS/TCP check)
222
+ * to a connectivity error code and check type. Used when building GitDiagnostics
223
+ * from checks that don't use the full runChecks/CheckResult pipeline.
224
+ */
225
+ export function mapConnectivityErrorMessage(errorMessage) {
226
+ const lower = errorMessage.toLowerCase();
227
+ if (lower.includes("dns resolution failed") ||
228
+ lower.includes("dns resolution") ||
229
+ lower.includes("no addresses found")) {
230
+ return {
231
+ connectivityErrorCode: "dns_resolution_failed",
232
+ checkType: "dns",
233
+ };
234
+ }
235
+ if (lower.includes("connection attempt failed") ||
236
+ lower.includes("connection timed out") ||
237
+ lower.includes("connection timeout") ||
238
+ lower.includes("etimedout") ||
239
+ lower.includes("timed out")) {
240
+ return {
241
+ connectivityErrorCode: "tcp_connection_timeout",
242
+ checkType: "tcp",
243
+ };
244
+ }
245
+ if (lower.includes("econnrefused") || lower.includes("connection refused")) {
246
+ return {
247
+ connectivityErrorCode: "tcp_connection_refused",
248
+ checkType: "tcp",
249
+ };
250
+ }
251
+ // ENOTFOUND, getaddrinfo, EAI_AGAIN, ENODATA are DNS resolution errors (aligned with DNS_ERRORS and mapNodeErrorToConnectivityCode)
252
+ if (lower.includes("enotfound") ||
253
+ lower.includes("getaddrinfo") ||
254
+ lower.includes("eai_again") ||
255
+ lower.includes("enodata")) {
256
+ return {
257
+ connectivityErrorCode: "dns_resolution_failed",
258
+ checkType: "dns",
259
+ };
260
+ }
261
+ if (lower.includes("network unreachable")) {
262
+ return {
263
+ connectivityErrorCode: "tcp_network_unreachable",
264
+ checkType: "tcp",
265
+ };
266
+ }
267
+ return null;
268
+ }
@@ -1,6 +1,6 @@
1
1
  export type { Source, TestId, Test, RunChecksInput, ProgressEvent, CheckResult, CheckReport, ConnectivityErrorCode, CheckType, Recommendation, LikelyCause, ConnectivityStatus, AnalysisResult, AnalyzeConnectivityInput, } from "./types.js";
2
2
  export { runChecks } from "./run-checks.js";
3
- export { mapNodeErrorToConnectivityCode, mapHttpStatusToErrorCode, mapFetchErrorToConnectivityCode, SELF_SIGNED_CERT_ERRORS, CERT_EXPIRED_ERRORS, CERT_NOT_YET_VALID_ERRORS, CERT_INVALID_ERRORS, CERT_HOSTNAME_MISMATCH_ERRORS, SSL_PROTOCOL_ERRORS, SSL_HANDSHAKE_ERRORS, NETWORK_UNREACHABLE_ERRORS, TIMEOUT_ERRORS, PROXY_ERRORS, DNS_ERRORS, } from "./error-codes.js";
3
+ export { mapNodeErrorToConnectivityCode, mapHttpStatusToErrorCode, mapFetchErrorToConnectivityCode, connectivityErrorCodeToLikelyCause, mapConnectivityErrorMessage, SELF_SIGNED_CERT_ERRORS, CERT_EXPIRED_ERRORS, CERT_NOT_YET_VALID_ERRORS, CERT_INVALID_ERRORS, CERT_HOSTNAME_MISMATCH_ERRORS, SSL_PROTOCOL_ERRORS, SSL_HANDSHAKE_ERRORS, NETWORK_UNREACHABLE_ERRORS, TIMEOUT_ERRORS, PROXY_ERRORS, DNS_ERRORS, } from "./error-codes.js";
4
4
  export { BUILDER_TARGETS, DEFAULT_PORTS, resolveTarget, extractHostname, extractPort, } from "./targets.js";
5
5
  export { isBrowser, isNode, getCheckTypeForTestId, isCheckAvailable, getUnavailabilityReason, } from "./environment.js";
6
6
  export { httpCheck } from "./checks/http-check.js";
@@ -1,5 +1,5 @@
1
1
  export { runChecks } from "./run-checks.js";
2
- export { mapNodeErrorToConnectivityCode, mapHttpStatusToErrorCode, mapFetchErrorToConnectivityCode, SELF_SIGNED_CERT_ERRORS, CERT_EXPIRED_ERRORS, CERT_NOT_YET_VALID_ERRORS, CERT_INVALID_ERRORS, CERT_HOSTNAME_MISMATCH_ERRORS, SSL_PROTOCOL_ERRORS, SSL_HANDSHAKE_ERRORS, NETWORK_UNREACHABLE_ERRORS, TIMEOUT_ERRORS, PROXY_ERRORS, DNS_ERRORS, } from "./error-codes.js";
2
+ export { mapNodeErrorToConnectivityCode, mapHttpStatusToErrorCode, mapFetchErrorToConnectivityCode, connectivityErrorCodeToLikelyCause, mapConnectivityErrorMessage, SELF_SIGNED_CERT_ERRORS, CERT_EXPIRED_ERRORS, CERT_NOT_YET_VALID_ERRORS, CERT_INVALID_ERRORS, CERT_HOSTNAME_MISMATCH_ERRORS, SSL_PROTOCOL_ERRORS, SSL_HANDSHAKE_ERRORS, NETWORK_UNREACHABLE_ERRORS, TIMEOUT_ERRORS, PROXY_ERRORS, DNS_ERRORS, } from "./error-codes.js";
3
3
  export { BUILDER_TARGETS, DEFAULT_PORTS, resolveTarget, extractHostname, extractPort, } from "./targets.js";
4
4
  export { isBrowser, isNode, getCheckTypeForTestId, isCheckAvailable, getUnavailabilityReason, } from "./environment.js";
5
5
  export { httpCheck } from "./checks/http-check.js";
package/src/index.d.ts CHANGED
@@ -10,3 +10,4 @@ export * from "./organization.js";
10
10
  export * from "./features.js";
11
11
  export * from "./vscode-tunnel.js";
12
12
  export * from "./connectivity/types.js";
13
+ export { connectivityErrorCodeToLikelyCause, mapConnectivityErrorMessage, } from "./connectivity/error-codes.js";
package/src/index.js CHANGED
@@ -10,3 +10,4 @@ export * from "./organization.js";
10
10
  export * from "./features.js";
11
11
  export * from "./vscode-tunnel.js";
12
12
  export * from "./connectivity/types.js";
13
+ export { connectivityErrorCodeToLikelyCause, mapConnectivityErrorMessage, } from "./connectivity/error-codes.js";
@@ -79,6 +79,7 @@ interface OrganizationSettings {
79
79
  fusionPrLabel?: string;
80
80
  fusionPrQuietMode?: boolean;
81
81
  runInPty?: boolean;
82
+ maxAgentCompletions?: number;
82
83
  privacyMode?: Pick<PrivacyMode, "mcpServers" | "redactUserMessages" | "redactLLMMessages"> & {
83
84
  enabled?: boolean;
84
85
  };
package/src/projects.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import type { ConnectivityErrorCode, CheckType, LikelyCause } from "./connectivity/types.js";
1
2
  import type { FileOverride, EnvironmentVariable, LaunchServerState, LaunchServerStatus, BranchBackup, CommitMode, CustomInstruction, CustomAgentDefinition } from "./codegen";
2
3
  import type { FallbackTokensPrivate } from "./organization";
3
4
  /**
@@ -148,6 +149,54 @@ export interface ReadyMessage extends BaseMessage {
148
149
  export type MachineState = "unknown" | "created" | "starting" | "started" | "stopping" | "stopped" | "suspending" | "suspended" | "replacing" | "destroying" | "destroyed" | "not-found" | "running" | "failed";
149
150
  export type FlyVolumeState = "unknown" | "creating" | "created" | "extending" | "restoring" | "enabling_remote_export" | "hydrating" | "recovering" | "scheduling_destroy" | "pending_destroy" | "failed";
150
151
  export type GitAuthErrorCode = "git-auth-failed" | "git-auth-failed-root-repo" | "git-auth-failed-folder-added-by" | "git-auth-failed-folder-created-by" | "git-auth-failed-repo-not-found" | "git-auth-failed-repo-renamed" | "git-auth-failed-folder-server-token" | "git-auth-failed-root-repo-server-token" | "git-auth-failed-ghes-unreachable";
152
+ /**
153
+ * Git provider types for diagnostics.
154
+ */
155
+ export type GitDiagnosticsProvider = "github" | "bitbucket" | "gitlab" | "azure" | "unknown";
156
+ /**
157
+ * Detect git provider from a repository URL (HTTPS or SSH).
158
+ * Used by both error diagnostics and connectivity checks for consistent provider labeling.
159
+ */
160
+ export declare function getGitProviderFromUrl(url: string): GitDiagnosticsProvider;
161
+ /**
162
+ * Issue classification for git-related errors.
163
+ * - access: Repository access issues (404, repo doesn't exist, insufficient permissions)
164
+ * - auth: Authentication issues (token expired, invalid credentials)
165
+ * - network: Network issues (timeouts, connection failures, unreachable hosts)
166
+ * - unknown: Should be avoided - not helpful for debugging
167
+ */
168
+ export type GitDiagnosticsIssue = "access" | "auth" | "network" | "unknown";
169
+ /**
170
+ * Diagnostic information for git-related errors.
171
+ * Helps frontend display actionable error messages.
172
+ * Optional connectivity fields align with the connectivity check feature so that
173
+ * when a git error is due to network/connectivity, we can pass through granular
174
+ * error codes and likely causes for better UX and recommendations.
175
+ */
176
+ export interface GitDiagnostics {
177
+ provider: GitDiagnosticsProvider;
178
+ hostname: string;
179
+ /**
180
+ * Source IP for debugging network issues: when using an HTTP proxy for outbound
181
+ * git requests, use the proxy host/IP; otherwise the egress IP of the running machine if known.
182
+ */
183
+ sourceIp: string;
184
+ repoName: string;
185
+ issue: GitDiagnosticsIssue;
186
+ /**
187
+ * When issue is "network" (or from a connectivity check), the specific
188
+ * connectivity error code from the check result, if available.
189
+ */
190
+ connectivityErrorCode?: ConnectivityErrorCode;
191
+ /**
192
+ * Which kind of check failed (dns, tcp, tls, http, ssh). Omitted when not from a connectivity check.
193
+ */
194
+ checkType?: CheckType;
195
+ /**
196
+ * Suggested likely cause for the failure; can drive recommendations (e.g. whitelist IP, fix DNS).
197
+ */
198
+ likelyCause?: LikelyCause;
199
+ }
151
200
  export type EnsureContainerErrorCode = "FAILED_TO_START_MACHINE_ERROR" | "FLY_APP_CHECK_ERROR" | "FLY_CAPACITY_ERROR" | "FLY_PERMISSIONS_TOKEN_ERROR" | "FLY_VOLUME_CREATE_ERROR" | "FLY_VOLUME_FORK_ERROR" | "FLY_VOLUME_DELETE_RECENTLY_FORKED_ERROR" | "FLY_MACHINE_CREATE_ERROR" | "FLY_VOLUME_CHECK_ERROR" | "FLY_NON_MOUNTABLE_VOLUME_ERROR" | "FLY_DEPRECATED_REGION_ERROR" | "FLY_VOLUME_NOT_FOUND" | "FLY_MACHINE_LIMIT_ERROR" | "KUBE_CAPACITY_ERROR" | "KUBE_PERMISSIONS_ERROR" | "KUBE_POD_LIMIT_ERROR" | "KUBE_RESOURCE_QUOTA_ERROR" | "KUBE_NAMESPACE_CHECK_ERROR" | "KUBE_PVC_CREATE_ERROR" | "KUBE_PVC_CHECK_ERROR" | "KUBE_POD_CREATE_ERROR" | "KUBE_SERVICE_CREATE_ERROR" | "KUBE_INGRESS_CREATE_ERROR" | "KUBE_POD_FAILED_TO_START_ERROR" | "ensure-checking-existing-machines" | "found-multiple-failed-machine" | "maximun-retries-machine-creation" | GitAuthErrorCode | "unknown" | "project-bad-state" | "project-not-found" | "project-deleted" | "project-branch-not-found" | "project-branch-deleted" | "project-branch-no-session-id" | "project-repo-full-name-not-found" | "project-org-not-found" | "invalid-project-repo-url-already-in-use" | "no-available-regions" | "invalid-backup-without-volume-id" | "missing-app-with-machine-or-volume" | "update-branch-info-in-firebase" | "update-branch-app-name-in-firebase" | `machine-status-polling-${MachineState}` | `machine-image-exited-immediately` | `volume-not-found-${FlyVolumeState}` | "trying-to-remove-used-volume" | "missing-container-url" | "timeout" | "fatal:zod-validation-error" | `fatal:${string}`;
152
201
  export interface ErrorStateMessage extends BaseMessage {
153
202
  state: "error";
@@ -210,6 +259,13 @@ export interface GitBackupRecordOptions {
210
259
  forced: ForcedBackup;
211
260
  metadata?: Record<string, string | string[] | undefined>;
212
261
  }
262
+ export interface RecordScreenshotOptions {
263
+ projectId: string;
264
+ branchName: string;
265
+ completionId?: string;
266
+ screenshotUrl: string;
267
+ meta?: Record<string, any>;
268
+ }
213
269
  export interface GitBackupRecordResult {
214
270
  success: boolean;
215
271
  }
@@ -391,6 +447,7 @@ interface BranchSharedData {
391
447
  lastActivityAt?: number;
392
448
  /** Whether the branch has unpushed changes (ahead > 0 or dirty working directory) */
393
449
  hasUnpushedChanges?: boolean;
450
+ screenshot?: string | null;
394
451
  }
395
452
  /**
396
453
  * fields that are required in the new branch format, but optional in the legacy branch format.
@@ -500,7 +557,7 @@ export interface Project {
500
557
  autoStop?: MachineAutoStop;
501
558
  mainBranchName?: string;
502
559
  minMachinesRunning?: number;
503
- volumeSize?: 5 | 10 | 12 | 15 | 20;
560
+ volumeSize?: 5 | 10 | 12 | 15 | 20 | 25 | 30 | 50;
504
561
  includePath?: string;
505
562
  includePatterns?: string[];
506
563
  environmentVariables?: EnvironmentVariable[];
@@ -541,6 +598,7 @@ export interface Project {
541
598
  };
542
599
  postMergeMemories?: boolean;
543
600
  commitInstructions?: string;
601
+ maxAgentCompletions?: number;
544
602
  httpsServerKeyPath?: string;
545
603
  httpsServerCertPath?: string;
546
604
  httpsServerCaPath?: string;
package/src/projects.js CHANGED
@@ -1,3 +1,25 @@
1
+ /**
2
+ * Detect git provider from a repository URL (HTTPS or SSH).
3
+ * Used by both error diagnostics and connectivity checks for consistent provider labeling.
4
+ */
5
+ export function getGitProviderFromUrl(url) {
6
+ try {
7
+ const lower = url.toLowerCase();
8
+ // Prefer canonical hostnames to avoid false positives (e.g. custom host with "github" in name)
9
+ if (lower.includes("github.com"))
10
+ return "github";
11
+ if (lower.includes("gitlab.com"))
12
+ return "gitlab";
13
+ if (lower.includes("bitbucket.org"))
14
+ return "bitbucket";
15
+ if (lower.includes("dev.azure.com"))
16
+ return "azure";
17
+ return "unknown";
18
+ }
19
+ catch (_a) {
20
+ return "unknown";
21
+ }
22
+ }
1
23
  export const EXAMPLE_REPOS = [
2
24
  "steve8708/mui-vite",
3
25
  "steve8708/carbon-vite",