catalyst-core 1.2.0-canary.1 → 1.2.0-canary.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/bin/catalyst.js +54 -6
- package/dist/errors/registry.js +306 -18
- package/dist/errors-index.json +273 -70
- package/dist/native/androidProject/app/build.gradle.kts +53 -79
- package/dist/native/androidProject/app/src/main/AndroidManifest.xml +1 -1
- package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/CatalystConstants.kt +3 -1
- package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/CustomWebview.kt +0 -72
- package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/MainActivity.kt +32 -4
- package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/utils/KeyboardUtil.kt +5 -1
- package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/ConfigMappingTest.kt +25 -0
- package/dist/native/androidSetup.js +76 -170
- package/dist/native/androidToolchain.js +642 -0
- package/dist/native/appIcon.js +100 -0
- package/dist/native/buildAndroid/assets.js +48 -30
- package/dist/native/buildAndroid/build.js +152 -223
- package/dist/native/buildAndroid/config.js +57 -65
- package/dist/native/buildAndroid/devices.js +176 -0
- package/dist/native/buildAndroid/index.js +305 -50
- package/dist/native/buildAndroid/output.js +205 -0
- package/dist/native/buildAndroid/signing.js +456 -0
- package/dist/native/buildAppAndroid.js +52 -7
- package/dist/native/buildAppIos.js +267 -20
- package/dist/native/buildIos/assets.js +76 -4
- package/dist/native/buildIos/build.js +31 -181
- package/dist/native/buildIos/config.js +135 -19
- package/dist/native/buildIos/index.js +383 -34
- package/dist/native/buildIos/localhostCert.js +87 -0
- package/dist/native/buildIos/output.js +28 -0
- package/dist/native/buildIos/signing.js +1120 -0
- package/dist/native/credentials.js +309 -0
- package/dist/native/exportCredentials.js +51 -0
- package/dist/native/iosToolchain.js +583 -0
- package/dist/native/iosnativeWebView/Configurations/Shared.xcconfig +1 -3
- package/dist/native/iosnativeWebView/iosnativeWebView/Info-Release.plist +2 -0
- package/dist/native/iosnativeWebView/iosnativeWebView/PrivacyInfo.xcprivacy +40 -0
- package/dist/native/iosnativeWebView/iosnativeWebView/iosnativeWebView.entitlements +0 -2
- package/dist/native/iosnativeWebView/iosnativeWebView.xcodeproj/project.pbxproj +4 -4
- package/dist/native/localState.js +148 -0
- package/dist/native/nativeConfig.js +640 -0
- package/dist/native/releaseOutput.js +86 -0
- package/dist/native/renameAndroidProject.js +168 -368
- package/dist/native/setupEmulatorIos.js +58 -275
- package/dist/native/setupServer.js +765 -117
- package/dist/native/splashConfig.js +64 -0
- package/dist/native/utils.js +418 -115
- package/dist/offline/registerServiceWorker.js +0 -2
- package/dist/otel.js +14 -503
- package/dist/scripts/build.js +22 -30
- package/dist/scripts/preServerInit.js +14 -1
- package/dist/server/renderer/document/Body.jsx +4 -5
- package/dist/server/renderer/document/Head.jsx +1 -2
- package/dist/server/renderer/extract.d.ts +4 -11
- package/dist/server/renderer/extract.js +7 -21
- package/dist/server/renderer/handler.jsx +14 -32
- package/dist/server/utils/validator.d.ts +8 -1
- package/dist/server/utils/validator.js +20 -1
- package/dist/vite/FastRefresh.jsx +1 -2
- package/dist/vite/resolveDevServerConfig.js +21 -0
- package/dist/vite/vite.config.js +3 -33
- package/dist/web-router/components/MetaTag.jsx +17 -2
- package/dist/web-router/components/MetaTag.test.jsx +95 -0
- package/dist/web-router/components/RouterDataProvider.jsx +3 -5
- package/dist/web-router/components/RouterDataProvider.server.test.jsx +1 -16
- package/dist/web-router/components/RouterDataProvider.test.jsx +1 -3
- package/mcp_v2/knowledge-base.json +13 -11
- package/mcp_v2/test/build.test.ts +104 -0
- package/mcp_v2/test/config.test.ts +153 -0
- package/mcp_v2/tools/build.js +118 -105
- package/mcp_v2/tools/config.js +233 -174
- package/package.json +1 -1
- package/test/cli/nativeFlags.test.ts +97 -0
- package/test/native/androidDevices.test.ts +230 -0
- package/test/native/androidElfAlignment.test.ts +148 -0
- package/test/native/androidOutput.test.ts +228 -0
- package/test/native/androidSigning.test.ts +650 -0
- package/test/native/androidToolchain.test.ts +766 -0
- package/test/native/appIcon.test.ts +124 -0
- package/test/native/credentials.test.ts +241 -0
- package/test/native/interaction.test.ts +179 -0
- package/test/native/iosConfigPhase.test.ts +624 -0
- package/test/native/iosInstalledSigning.test.ts +607 -0
- package/test/native/iosSigning.test.ts +1152 -0
- package/test/native/iosToolchain.test.ts +821 -0
- package/test/native/localState.test.ts +79 -0
- package/test/native/nativeConfig.test.ts +695 -0
- package/test/native/setupServer.test.ts +780 -0
- package/test/native/splashConfig.test.ts +177 -0
- package/test/native/utils.test.ts +102 -127
- package/test/server/handler.assets.test.ts +0 -77
- package/test/server/otel.test.ts +2 -3
- package/test/server/validator.test.ts +37 -0
- package/test/vite/resolveDevServerConfig.test.js +25 -0
- package/dist/native/androidProject/keystore/Untitled +0 -0
- package/dist/native/androidProject/keystore/release-key.jks +0 -0
- package/dist/native/iosnativeWebView/iosnativeWebView/localhost.p12 +0 -0
- package/test/native/locationPermissions.test.js +0 -56
package/bin/catalyst.js
CHANGED
|
@@ -17,6 +17,7 @@ const platformScripts = {
|
|
|
17
17
|
"setupEmulator:android": "../dist/native/androidSetup.js",
|
|
18
18
|
"buildApp:ios": "../dist/native/buildAppIos.js",
|
|
19
19
|
"buildApp:android": "../dist/native/buildAppAndroid.js",
|
|
20
|
+
"credentials:export": "../dist/native/exportCredentials.js",
|
|
20
21
|
}
|
|
21
22
|
const validCommands = new Set([...webCommands, "buildApp", "setupEmulator", ...Object.keys(platformScripts)])
|
|
22
23
|
|
|
@@ -46,10 +47,11 @@ const HELP = [
|
|
|
46
47
|
[
|
|
47
48
|
"Native",
|
|
48
49
|
[
|
|
49
|
-
["setupEmulator:android", "
|
|
50
|
-
["setupEmulator:ios", "
|
|
50
|
+
["setupEmulator:android", "Install the Android tools and start the emulator"],
|
|
51
|
+
["setupEmulator:ios", "Install the iOS simulator and finish Xcode setup"],
|
|
51
52
|
["buildApp:android", "Build and install the Android app"],
|
|
52
53
|
["buildApp:ios", "Build and install the iOS app"],
|
|
54
|
+
["credentials:export", "Print credentials/<android|ios>/ as one CI secret"],
|
|
53
55
|
],
|
|
54
56
|
],
|
|
55
57
|
[
|
|
@@ -79,6 +81,21 @@ function printHelp() {
|
|
|
79
81
|
lines.push(
|
|
80
82
|
`${GUTTER} ${"--debug".padEnd(width)}${paint("dim", "Also print stacks and the environment")}`
|
|
81
83
|
)
|
|
84
|
+
lines.push(
|
|
85
|
+
`${GUTTER} ${"--release".padEnd(width)}${paint("dim", "buildApp: build the signed store release")}`
|
|
86
|
+
)
|
|
87
|
+
lines.push(
|
|
88
|
+
`${GUTTER} ${"--device".padEnd(width)}${paint("dim", "buildApp: run on the connected phone")}`
|
|
89
|
+
)
|
|
90
|
+
lines.push(
|
|
91
|
+
`${GUTTER} ${"--url <url>".padEnd(width)}${paint("dim", "buildApp: the release's production URL")}`
|
|
92
|
+
)
|
|
93
|
+
lines.push(
|
|
94
|
+
`${GUTTER} ${"--yes".padEnd(width)}${paint("dim", "Confirm installs and downloads without asking")}`
|
|
95
|
+
)
|
|
96
|
+
lines.push(
|
|
97
|
+
`${GUTTER} ${"--accept-licenses".padEnd(width)}${paint("dim", "Accept the Android SDK and Xcode licences")}`
|
|
98
|
+
)
|
|
82
99
|
lines.push(`${GUTTER} ${"-h, --help".padEnd(width)}${paint("dim", "Show this help")}`)
|
|
83
100
|
lines.push(`${GUTTER} ${"-v, --version".padEnd(width)}${paint("dim", "Print the version")}`)
|
|
84
101
|
console.log(`${lines.join("\n")}\n`)
|
|
@@ -117,10 +134,41 @@ if (args[0] === "--version" || args[0] === "-v") {
|
|
|
117
134
|
process.exit(0)
|
|
118
135
|
}
|
|
119
136
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
137
|
+
// Native flags, with how many values each takes. They are pulled out before
|
|
138
|
+
// dispatch wherever they appear, so `--url build` can't be read as the build
|
|
139
|
+
// command and a flag before the command isn't handed to node. Agents and CI
|
|
140
|
+
// answer every question with these; nothing else is ever asked.
|
|
141
|
+
const nativeFlags = {
|
|
142
|
+
"--release": 0,
|
|
143
|
+
"--device": 0,
|
|
144
|
+
"--url": 1,
|
|
145
|
+
"--yes": 0,
|
|
146
|
+
"--accept-licenses": 0,
|
|
147
|
+
}
|
|
148
|
+
const forwardedFlags = []
|
|
149
|
+
const commandArgs = []
|
|
150
|
+
for (let i = 0; i < args.length; i++) {
|
|
151
|
+
const arg = args[i]
|
|
152
|
+
const name = arg.split("=")[0]
|
|
153
|
+
if (name in nativeFlags) {
|
|
154
|
+
const takesValue = nativeFlags[name] > 0 && !arg.includes("=")
|
|
155
|
+
forwardedFlags.push(...args.slice(i, i + 1 + (takesValue ? 1 : 0)))
|
|
156
|
+
if (takesValue) i++
|
|
157
|
+
} else {
|
|
158
|
+
commandArgs.push(arg)
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const scriptIndex = commandArgs.findIndex((arg) => validCommands.has(arg))
|
|
163
|
+
const script = scriptIndex === -1 ? commandArgs[0] : commandArgs[scriptIndex]
|
|
164
|
+
const nodeArgs = scriptIndex > 0 ? commandArgs.slice(0, scriptIndex) : []
|
|
165
|
+
const scriptArgs = [...forwardedFlags, ...commandArgs.slice(scriptIndex + 1)]
|
|
166
|
+
|
|
167
|
+
if (!script) {
|
|
168
|
+
// Only flags, no command.
|
|
169
|
+
printHelp()
|
|
170
|
+
process.exit(1)
|
|
171
|
+
}
|
|
124
172
|
|
|
125
173
|
function handleProcessResult(result) {
|
|
126
174
|
if (result.signal) {
|
package/dist/errors/registry.js
CHANGED
|
@@ -30,8 +30,38 @@ export const ERROR_CODES = {
|
|
|
30
30
|
BUNDLE_UPSTREAM_ERROR: "BUNDLE-000",
|
|
31
31
|
IOS_UPSTREAM_ERROR: "IOS-000",
|
|
32
32
|
IOS_SIMULATOR_APP_NOT_FOUND: "IOS-001",
|
|
33
|
+
IOS_XCODE_NOT_INSTALLED: "IOS-002",
|
|
34
|
+
IOS_XCODE_SETUP_PENDING: "IOS-003",
|
|
35
|
+
IOS_SIMULATOR_RUNTIME_MISSING: "IOS-004",
|
|
36
|
+
IOS_APP_ICON_INVALID: "IOS-005",
|
|
37
|
+
IOS_APP_ICON_HAS_ALPHA: "IOS-006",
|
|
38
|
+
IOS_SIGNING_NOT_SET_UP: "IOS-010",
|
|
39
|
+
IOS_ASC_API_KEY_INVALID: "IOS-011",
|
|
40
|
+
IOS_MANUAL_SIGNING_INVALID: "IOS-012",
|
|
41
|
+
IOS_EXPORT_METHOD_INVALID: "IOS-013",
|
|
42
|
+
IOS_DEVICE_NOT_FOUND: "IOS-014",
|
|
43
|
+
IOS_DEVICE_HOST_UNREACHABLE: "IOS-015",
|
|
33
44
|
ANDROID_UPSTREAM_ERROR: "ANDROID-000",
|
|
34
45
|
ANDROID_EMULATOR_BOOT_TIMEOUT: "ANDROID-001",
|
|
46
|
+
ANDROID_UPLOAD_KEY_MISSING: "ANDROID-005",
|
|
47
|
+
ANDROID_UPLOAD_KEY_INVALID: "ANDROID-006",
|
|
48
|
+
ANDROID_JDK_NOT_FOUND: "ANDROID-007",
|
|
49
|
+
ANDROID_SDK_SETUP_DECLINED: "ANDROID-008",
|
|
50
|
+
ANDROID_CMDLINE_TOOLS_INSTALL_FAILED: "ANDROID-009",
|
|
51
|
+
ANDROID_APP_ICON_INVALID: "ANDROID-010",
|
|
52
|
+
ANDROID_NO_DEVICE: "ANDROID-011",
|
|
53
|
+
|
|
54
|
+
NATIVE_RELEASE_PRIVATE_HOST: "NATIVE-001",
|
|
55
|
+
NATIVE_INVALID_BUILD_NUMBER: "NATIVE-002",
|
|
56
|
+
NATIVE_PLACEHOLDER_APP_ID: "NATIVE-003",
|
|
57
|
+
NATIVE_INVALID_URL: "NATIVE-004",
|
|
58
|
+
NATIVE_ANSWER_NEEDS_TERMINAL: "NATIVE-005",
|
|
59
|
+
NATIVE_DEV_SERVER_NOT_ANSWERING: "NATIVE-006",
|
|
60
|
+
NATIVE_CREDENTIALS_SECRET_INVALID: "NATIVE-007",
|
|
61
|
+
NATIVE_CREDENTIALS_MISSING: "NATIVE-008",
|
|
62
|
+
NATIVE_CREDENTIALS_TOO_LARGE: "NATIVE-009",
|
|
63
|
+
NATIVE_INVALID_APP_ID: "NATIVE-010",
|
|
64
|
+
NATIVE_RELEASE_OUTPUT_EXISTS: "NATIVE-011",
|
|
35
65
|
|
|
36
66
|
RUNTIME_NATIVE_PERMISSION_DENIED: "RUNTIME-NATIVE-001",
|
|
37
67
|
RUNTIME_NATIVE_PERMISSION_REQUIRED: "RUNTIME-NATIVE-002",
|
|
@@ -82,7 +112,8 @@ export const ERROR_DEFINITIONS = {
|
|
|
82
112
|
category: "PREFLIGHT",
|
|
83
113
|
defaultMessage: "config not found in config folder",
|
|
84
114
|
defaultDetails: "A config object must be exported from the config folder in your project root.",
|
|
85
|
-
suggestedAction:
|
|
115
|
+
suggestedAction:
|
|
116
|
+
"Create config/config.json (or config/index.js) exporting the required config object.",
|
|
86
117
|
},
|
|
87
118
|
[ERROR_CODES.PREFLIGHT_CONFIG_NOT_OBJECT]: {
|
|
88
119
|
category: "PREFLIGHT",
|
|
@@ -137,7 +168,8 @@ export const ERROR_DEFINITIONS = {
|
|
|
137
168
|
category: "PREFLIGHT",
|
|
138
169
|
defaultMessage: "preServerInit named function should be defined in server/index.js",
|
|
139
170
|
defaultDetails: "server/index.js must export a preServerInit function.",
|
|
140
|
-
suggestedAction:
|
|
171
|
+
suggestedAction:
|
|
172
|
+
"Export a preServerInit function from server/index.js, or remove the reference to it.",
|
|
141
173
|
},
|
|
142
174
|
[ERROR_CODES.PREFLIGHT_PRE_SERVER_INIT_NOT_FUNCTION]: {
|
|
143
175
|
category: "PREFLIGHT",
|
|
@@ -238,15 +270,109 @@ export const ERROR_DEFINITIONS = {
|
|
|
238
270
|
[ERROR_CODES.IOS_UPSTREAM_ERROR]: {
|
|
239
271
|
category: "IOS",
|
|
240
272
|
defaultMessage: "iOS build failed in an upstream toolchain step",
|
|
241
|
-
defaultDetails:
|
|
242
|
-
|
|
273
|
+
defaultDetails:
|
|
274
|
+
"This wraps an error from Xcode/CocoaPods. See the printed upstream output for the cause.",
|
|
275
|
+
suggestedAction:
|
|
276
|
+
"Read the upstream Xcode/CocoaPods error printed above and fix the underlying issue.",
|
|
243
277
|
},
|
|
244
278
|
[ERROR_CODES.IOS_SIMULATOR_APP_NOT_FOUND]: {
|
|
245
279
|
category: "IOS",
|
|
246
280
|
defaultMessage: "Could not find an installed iOS Simulator app",
|
|
247
281
|
defaultDetails:
|
|
248
282
|
"Neither DeviceHub.app (Xcode 27+, bundle id com.apple.dt.Devices) nor the legacy Simulator.app (bundle id com.apple.iphonesimulator) is installed under Xcode's Contents/Applications. The simulator itself may still boot headlessly via simctl, but catalyst-core cannot open or focus its window.",
|
|
249
|
-
suggestedAction:
|
|
283
|
+
suggestedAction:
|
|
284
|
+
"Confirm a full Xcode.app (not just Command Line Tools) is installed and selected via xcode-select -p, then reopen it once from Spotlight so macOS registers its app bundle.",
|
|
285
|
+
},
|
|
286
|
+
// The messages and suggested actions of IOS-002..006 and IOS-010..015 are
|
|
287
|
+
// copied into src/native/utils.js NATIVE_ERRORS;
|
|
288
|
+
// test/native/nativeConfig.test.ts keeps the two equal.
|
|
289
|
+
[ERROR_CODES.IOS_XCODE_NOT_INSTALLED]: {
|
|
290
|
+
category: "IOS",
|
|
291
|
+
defaultMessage: "Full Xcode is not installed or selected",
|
|
292
|
+
defaultDetails:
|
|
293
|
+
"setupEmulator:ios and buildApp:ios need Xcode.app, not only the Command Line Tools. xcode-select -p does not point inside an Xcode app bundle, so there is no simulator, iOS SDK or app-building xcodebuild.",
|
|
294
|
+
suggestedAction:
|
|
295
|
+
"Install Xcode from the Mac App Store, then run sudo xcode-select -s /Applications/Xcode.app/Contents/Developer.",
|
|
296
|
+
},
|
|
297
|
+
[ERROR_CODES.IOS_XCODE_SETUP_PENDING]: {
|
|
298
|
+
category: "IOS",
|
|
299
|
+
defaultMessage: "Xcode setup is not finished",
|
|
300
|
+
defaultDetails:
|
|
301
|
+
"The Xcode licence has not been accepted or its first-launch components are not installed, so xcodebuild and simctl refuse to run. Both steps need an administrator password: in a terminal they run after a yes, and without one --accept-licenses (the licence) and --yes (first launch) run them with sudo -n, which works only where sudo needs no password.",
|
|
302
|
+
suggestedAction:
|
|
303
|
+
"Run sudo xcodebuild -license accept and sudo xcodebuild -runFirstLaunch, then retry.",
|
|
304
|
+
},
|
|
305
|
+
[ERROR_CODES.IOS_SIMULATOR_RUNTIME_MISSING]: {
|
|
306
|
+
category: "IOS",
|
|
307
|
+
defaultMessage: "No iOS simulator runtime installed",
|
|
308
|
+
defaultDetails:
|
|
309
|
+
"Xcode has no available iOS simulator runtime, so there is no simulator to create or boot. The runtime is a download of several gigabytes and is only fetched after a yes in an interactive terminal or with --yes.",
|
|
310
|
+
suggestedAction:
|
|
311
|
+
"Run catalyst setupEmulator:ios in a terminal or with --yes, or run xcodebuild -downloadPlatform iOS yourself.",
|
|
312
|
+
},
|
|
313
|
+
[ERROR_CODES.IOS_APP_ICON_INVALID]: {
|
|
314
|
+
category: "IOS",
|
|
315
|
+
defaultMessage: "App icon is not usable",
|
|
316
|
+
defaultDetails:
|
|
317
|
+
"public/icon.png becomes the app's single 1024x1024 universal AppIcon, so it must be a PNG file, square, and at least 1024 by 1024 pixels.",
|
|
318
|
+
suggestedAction:
|
|
319
|
+
"Replace public/icon.png with a square PNG of at least 1024x1024 pixels, or add the sized icons in public/ios/appIcons.",
|
|
320
|
+
},
|
|
321
|
+
[ERROR_CODES.IOS_APP_ICON_HAS_ALPHA]: {
|
|
322
|
+
category: "IOS",
|
|
323
|
+
defaultMessage: "App icon has transparency",
|
|
324
|
+
defaultDetails:
|
|
325
|
+
"App Store Connect rejects app icons with an alpha channel (ITMS-90717). public/icon.png has an alpha channel or a transparency chunk, which fails an iOS release build. Debug builds only warn.",
|
|
326
|
+
suggestedAction:
|
|
327
|
+
"Export public/icon.png without an alpha channel (flatten it onto a solid background), then rebuild.",
|
|
328
|
+
},
|
|
329
|
+
[ERROR_CODES.IOS_SIGNING_NOT_SET_UP]: {
|
|
330
|
+
category: "IOS",
|
|
331
|
+
defaultMessage: "iOS code signing is not set up",
|
|
332
|
+
defaultDetails:
|
|
333
|
+
"A device or release build needs a signing identity and provisioning profile. A release signs with the first of: a .p12 and its profile in credentials/ios/, an installed ios.provisioningProfile, an App Store Connect API key in credentials/ios/, an App Store profile installed on this Mac for the app id (with its certificate in the keychain), or the Apple account signed in to Xcode for WEBVIEW_CONFIG.ios.developmentTeam. xcodebuild reported a signing failure, or a release build has no team to sign for.",
|
|
334
|
+
suggestedAction:
|
|
335
|
+
"Sign in to Xcode (Xcode > Settings > Accounts) with the Apple account that has your team, or install that team's App Store profile for your appId. In CI, put the signing files in credentials/ios/ and set CATALYST_IOS_CREDENTIALS to the output of catalyst credentials:export ios.",
|
|
336
|
+
},
|
|
337
|
+
[ERROR_CODES.IOS_ASC_API_KEY_INVALID]: {
|
|
338
|
+
category: "IOS",
|
|
339
|
+
defaultMessage: "App Store Connect API key settings are incomplete or wrong",
|
|
340
|
+
defaultDetails:
|
|
341
|
+
"Cloud signing uses an App Store Connect API key from credentials/ios/ (in CI, unpacked from CATALYST_IOS_CREDENTIALS), which takes three values: the AuthKey_*.p8 file, its key ID and the issuer ID. Some of them are there but not all, there is more than one .p8 file, or the key ID is not letters and digits.",
|
|
342
|
+
suggestedAction:
|
|
343
|
+
"Put the AuthKey_*.p8 file in credentials/ios/, and an ascIssuerId line (plus ascKeyId when the file is renamed) in credentials/ios/signing.properties. In CI, run catalyst credentials:export ios again and paste the value into CATALYST_IOS_CREDENTIALS.",
|
|
344
|
+
},
|
|
345
|
+
[ERROR_CODES.IOS_MANUAL_SIGNING_INVALID]: {
|
|
346
|
+
category: "IOS",
|
|
347
|
+
defaultMessage: "Manual signing inputs are incomplete or wrong",
|
|
348
|
+
defaultDetails:
|
|
349
|
+
"Local signing imports the .p12 from credentials/ios/ into a temporary keychain and installs its provisioning profile for the build. Only one of the .p12 and the .mobileprovision is there, there are several of either, the p12Password in signing.properties is wrong, the p12 has no code signing identity, or the profile is unreadable, expired or for another bundle ID.",
|
|
350
|
+
suggestedAction:
|
|
351
|
+
"Keep one distribution .p12 and the .mobileprovision for WEBVIEW_CONFIG.appId in credentials/ios/, with a p12Password line in credentials/ios/signing.properties, and check that they belong together. In CI, run catalyst credentials:export ios again and paste the value into CATALYST_IOS_CREDENTIALS.",
|
|
352
|
+
},
|
|
353
|
+
[ERROR_CODES.IOS_EXPORT_METHOD_INVALID]: {
|
|
354
|
+
category: "IOS",
|
|
355
|
+
defaultMessage: "Unknown iOS export method",
|
|
356
|
+
defaultDetails:
|
|
357
|
+
"WEBVIEW_CONFIG.ios.exportMethod picks how the release archive is exported to an IPA. Xcode 26 accepts app-store-connect, release-testing, enterprise and debugging; the older names app-store, ad-hoc and development are mapped to them with a warning.",
|
|
358
|
+
suggestedAction:
|
|
359
|
+
"Set WEBVIEW_CONFIG.ios.exportMethod to app-store-connect (the default), release-testing, enterprise or debugging.",
|
|
360
|
+
},
|
|
361
|
+
[ERROR_CODES.IOS_DEVICE_NOT_FOUND]: {
|
|
362
|
+
category: "IOS",
|
|
363
|
+
defaultMessage: "No connected iPhone found",
|
|
364
|
+
defaultDetails:
|
|
365
|
+
"buildApp:ios --device builds for a connected iPhone, and xcrun devicectl lists none that is paired and reachable. An iPhone shows up once it is unlocked, trusts this Mac and has Developer Mode on.",
|
|
366
|
+
suggestedAction:
|
|
367
|
+
"Connect the iPhone with a cable, unlock it, accept Trust This Computer and turn on Developer Mode (Settings > Privacy & Security), then retry; or leave out --device to use the simulator.",
|
|
368
|
+
},
|
|
369
|
+
[ERROR_CODES.IOS_DEVICE_HOST_UNREACHABLE]: {
|
|
370
|
+
category: "IOS",
|
|
371
|
+
defaultMessage: "No address the iPhone can reach this Mac on",
|
|
372
|
+
defaultDetails:
|
|
373
|
+
"A debug build on a physical iPhone loads the dev server from this Mac over the local network, at the Mac's Bonjour name (its Local Hostname plus .local) or its LAN IP address. This Mac has neither a Local Hostname nor a private IPv4 address on an active interface.",
|
|
374
|
+
suggestedAction:
|
|
375
|
+
"Join the Mac and the iPhone to the same Wi-Fi network and check the Local Hostname in System Settings > General > Sharing, then retry.",
|
|
250
376
|
},
|
|
251
377
|
[ERROR_CODES.ANDROID_UPSTREAM_ERROR]: {
|
|
252
378
|
category: "ANDROID",
|
|
@@ -262,7 +388,156 @@ export const ERROR_DEFINITIONS = {
|
|
|
262
388
|
suggestedAction:
|
|
263
389
|
"Try booting the AVD manually first (emulator -avd <name>) to see the actual startup error, check available disk space/RAM, or increase the emulator's cold-boot allowance if the device is unusually slow.",
|
|
264
390
|
},
|
|
391
|
+
// The messages and suggested actions of ANDROID-005..011 are copied into
|
|
392
|
+
// src/native/utils.js NATIVE_ERRORS (the CJS native subtree can't import
|
|
393
|
+
// this module); test/native/nativeConfig.test.ts keeps the two equal.
|
|
394
|
+
[ERROR_CODES.ANDROID_UPLOAD_KEY_MISSING]: {
|
|
395
|
+
category: "ANDROID",
|
|
396
|
+
defaultMessage: "No upload key for the release build",
|
|
397
|
+
defaultDetails:
|
|
398
|
+
"A release build signs the app bundle with the app's upload key. None was found in credentials/android/ or in the CATALYST_ANDROID_CREDENTIALS secret. A new key is only created after a yes in an interactive terminal, and never for an app that is already on Google Play.",
|
|
399
|
+
suggestedAction:
|
|
400
|
+
"Run catalyst buildApp:android --release once in a terminal to create credentials/android/upload.jks, then back it up with catalyst credentials:export android. In CI, set the CATALYST_ANDROID_CREDENTIALS secret to the output of catalyst credentials:export android.",
|
|
401
|
+
},
|
|
402
|
+
[ERROR_CODES.ANDROID_UPLOAD_KEY_INVALID]: {
|
|
403
|
+
category: "ANDROID",
|
|
404
|
+
defaultMessage: "Upload key settings are incomplete or wrong",
|
|
405
|
+
defaultDetails:
|
|
406
|
+
"An upload key was found but cannot be used: the keystore or its keystore.properties is missing, no store password was given, or keytool rejected the password or alias.",
|
|
407
|
+
suggestedAction:
|
|
408
|
+
"Check credentials/android/keystore.properties against credentials/android/upload.jks. In CI, run catalyst credentials:export android again and update the CATALYST_ANDROID_CREDENTIALS secret.",
|
|
409
|
+
},
|
|
410
|
+
[ERROR_CODES.ANDROID_JDK_NOT_FOUND]: {
|
|
411
|
+
category: "ANDROID",
|
|
412
|
+
defaultMessage: "No JDK 17 to 23 found",
|
|
413
|
+
defaultDetails:
|
|
414
|
+
"Gradle 8.13 and the Android SDK tools need JDK 17 to 23. None was found in JAVA_HOME, /usr/libexec/java_home or Android Studio's bundled runtime (a JDK 24 or newer is skipped), and none could be installed: this is not macOS, Homebrew is missing, or the install was declined.",
|
|
415
|
+
suggestedAction:
|
|
416
|
+
"Install JDK 17 or 21 (macOS: brew install --cask zulu@17; Linux: your distribution's openjdk-17-jdk package) and set JAVA_HOME, or run catalyst buildApp:android in a terminal, or with --yes, to install it.",
|
|
417
|
+
},
|
|
418
|
+
[ERROR_CODES.ANDROID_SDK_SETUP_DECLINED]: {
|
|
419
|
+
category: "ANDROID",
|
|
420
|
+
defaultMessage: "Android SDK setup was declined",
|
|
421
|
+
defaultDetails:
|
|
422
|
+
"buildApp:android or setupEmulator:android found Android SDK pieces to download (command-line tools, packages or a system image), an emulator to create, or SDK licences to accept, and the answer was no. Without them the app cannot be built or run.",
|
|
423
|
+
suggestedAction:
|
|
424
|
+
"Run the command again and answer yes, or pass --yes to allow the downloads and --accept-licenses to accept the Android SDK licences.",
|
|
425
|
+
},
|
|
426
|
+
[ERROR_CODES.ANDROID_CMDLINE_TOOLS_INSTALL_FAILED]: {
|
|
427
|
+
category: "ANDROID",
|
|
428
|
+
defaultMessage: "Could not install the Android command-line tools",
|
|
429
|
+
defaultDetails:
|
|
430
|
+
"The pinned Android command-line tools archive could not be downloaded, did not match its published SHA-256, or could not be unpacked into <sdk>/cmdline-tools/latest.",
|
|
431
|
+
suggestedAction:
|
|
432
|
+
"Check your network or proxy and retry, or download the command-line tools from https://developer.android.com/studio#command-tools and unzip them so that <sdk>/cmdline-tools/latest/bin/sdkmanager exists.",
|
|
433
|
+
},
|
|
434
|
+
[ERROR_CODES.ANDROID_APP_ICON_INVALID]: {
|
|
435
|
+
category: "ANDROID",
|
|
436
|
+
defaultMessage: "App icon is not usable",
|
|
437
|
+
defaultDetails:
|
|
438
|
+
"public/icon.png becomes the Android launcher icon when public/android/appIcons has no per-density icons, so it must be a PNG file, square, and at least 1024 by 1024 pixels.",
|
|
439
|
+
suggestedAction:
|
|
440
|
+
"Replace public/icon.png with a square PNG of at least 1024x1024 pixels, or add per-density icons in public/android/appIcons.",
|
|
441
|
+
},
|
|
442
|
+
[ERROR_CODES.ANDROID_NO_DEVICE]: {
|
|
443
|
+
category: "ANDROID",
|
|
444
|
+
defaultMessage: "No Android phone connected",
|
|
445
|
+
defaultDetails:
|
|
446
|
+
"buildApp:android --device installs the app on a phone that adb can reach, but adb lists none that is ready: no phone is connected, USB debugging is off, the phone has not allowed this computer yet (adb shows it as unauthorized), or ANDROID_SERIAL names a phone that is not connected.",
|
|
447
|
+
suggestedAction:
|
|
448
|
+
"Connect the phone, turn on USB debugging in Developer options, accept the Allow USB debugging prompt on the phone and check that adb devices lists it. Or drop --device to use the emulator.",
|
|
449
|
+
},
|
|
265
450
|
|
|
451
|
+
// NATIVE-001..009 are shared by the Android and iOS builds. Their messages and
|
|
452
|
+
// suggested actions are copied into src/native/utils.js NATIVE_ERRORS;
|
|
453
|
+
// test/native/nativeConfig.test.ts keeps the two equal.
|
|
454
|
+
[ERROR_CODES.NATIVE_RELEASE_PRIVATE_HOST]: {
|
|
455
|
+
category: "NATIVE",
|
|
456
|
+
defaultMessage: "Release build points at a local or private host",
|
|
457
|
+
defaultDetails:
|
|
458
|
+
"A release build (buildApp:android --release or buildApp:ios --release) would open a start URL on localhost, a loopback, private (RFC 1918), link-local or .local address, this machine's own address, or a reserved placeholder domain such as example.com. Users' devices cannot reach it, so the store build would open on an error page. The start URL comes from --url, then WEBVIEW_CONFIG.url, then the older LOCAL_IP, port and useHttps keys.",
|
|
459
|
+
suggestedAction:
|
|
460
|
+
"Set WEBVIEW_CONFIG.url to your production origin (e.g. https://shop.acme.com) or pass --url, or set WEBVIEW_CONFIG.allowPrivateHost to true for an internal app on a private network.",
|
|
461
|
+
},
|
|
462
|
+
[ERROR_CODES.NATIVE_INVALID_BUILD_NUMBER]: {
|
|
463
|
+
category: "NATIVE",
|
|
464
|
+
defaultMessage: "Invalid build number",
|
|
465
|
+
defaultDetails:
|
|
466
|
+
"The build number becomes the Android versionCode and the iOS CFBundleVersion. It is the whole minutes since 2024-01-01T00:00:00Z unless CATALYST_BUILD_NUMBER is set, and CATALYST_BUILD_NUMBER is not a whole number from 1 to 2100000000 (the largest value Google Play accepts).",
|
|
467
|
+
suggestedAction:
|
|
468
|
+
"Unset CATALYST_BUILD_NUMBER to use the automatic build number, or set it to a whole number from 1 to 2100000000 that is higher than the last one you uploaded.",
|
|
469
|
+
},
|
|
470
|
+
[ERROR_CODES.NATIVE_PLACEHOLDER_APP_ID]: {
|
|
471
|
+
category: "NATIVE",
|
|
472
|
+
defaultMessage: "Release build uses a placeholder app id",
|
|
473
|
+
defaultDetails:
|
|
474
|
+
"The app id becomes the Android application id and the iOS bundle id, and a store listing is tied to it for good. It is a com.example.* id or one of the template defaults (io.yourname.androidproject, com.catalyst.framework.app, com.debug.webview), or none is set, so the template's default would ship.",
|
|
475
|
+
suggestedAction:
|
|
476
|
+
"Set WEBVIEW_CONFIG.appId in config/config.json to your own reverse-DNS id, e.g. com.acme.shop.",
|
|
477
|
+
},
|
|
478
|
+
[ERROR_CODES.NATIVE_INVALID_URL]: {
|
|
479
|
+
category: "NATIVE",
|
|
480
|
+
defaultMessage: "Invalid production URL",
|
|
481
|
+
defaultDetails:
|
|
482
|
+
"WEBVIEW_CONFIG.url and --url take an origin: an http:// or https:// scheme, a host and an optional port, with no path, query, fragment or user name. HTTPS must use port 443, because the iOS app always loads HTTPS on 443.",
|
|
483
|
+
suggestedAction:
|
|
484
|
+
"Use an origin such as https://shop.acme.com, without a path or a port other than 443.",
|
|
485
|
+
},
|
|
486
|
+
[ERROR_CODES.NATIVE_ANSWER_NEEDS_TERMINAL]: {
|
|
487
|
+
category: "NATIVE",
|
|
488
|
+
defaultMessage: "A step needs your answer and there is no terminal to ask on",
|
|
489
|
+
defaultDetails:
|
|
490
|
+
"Native commands only ask questions when stdin and stdout are terminals and CI is not set. This step needs an answer: --yes confirms installs and downloads, --accept-licenses accepts licences, and creating a signing key always needs a person at a terminal.",
|
|
491
|
+
suggestedAction: "Pass the flag named in the message, or run the command in an interactive terminal.",
|
|
492
|
+
},
|
|
493
|
+
[ERROR_CODES.NATIVE_DEV_SERVER_NOT_ANSWERING]: {
|
|
494
|
+
category: "NATIVE",
|
|
495
|
+
defaultMessage: "The dev server did not answer",
|
|
496
|
+
defaultDetails:
|
|
497
|
+
"A debug build loads the app from the dev server. The CLI started it with catalyst start and waited for it to answer, but it exited, did not answer in time, or is running where the device cannot reach it.",
|
|
498
|
+
suggestedAction:
|
|
499
|
+
"Run npm start on its own to see why the server does not start, then run the build again.",
|
|
500
|
+
},
|
|
501
|
+
[ERROR_CODES.NATIVE_CREDENTIALS_SECRET_INVALID]: {
|
|
502
|
+
category: "NATIVE",
|
|
503
|
+
defaultMessage: "The credentials secret could not be unpacked",
|
|
504
|
+
defaultDetails:
|
|
505
|
+
"CATALYST_ANDROID_CREDENTIALS and CATALYST_IOS_CREDENTIALS hold a base64 gzipped tar of credentials/<platform>/, as printed by catalyst credentials:export. The value is not one, is cut short, or holds links or paths outside the folder.",
|
|
506
|
+
suggestedAction:
|
|
507
|
+
"Run catalyst credentials:export <android|ios> where credentials/<platform>/ exists and paste the whole value into the secret again.",
|
|
508
|
+
},
|
|
509
|
+
[ERROR_CODES.NATIVE_CREDENTIALS_MISSING]: {
|
|
510
|
+
category: "NATIVE",
|
|
511
|
+
defaultMessage: "No credentials to export",
|
|
512
|
+
defaultDetails:
|
|
513
|
+
"catalyst credentials:export packs credentials/<platform>/ in the app root, and that folder is missing or empty. A first release build creates it (the Android upload key), or you add the iOS signing files to it.",
|
|
514
|
+
suggestedAction:
|
|
515
|
+
"Run the command from the app root after a release build has created credentials/<platform>/.",
|
|
516
|
+
},
|
|
517
|
+
[ERROR_CODES.NATIVE_CREDENTIALS_TOO_LARGE]: {
|
|
518
|
+
category: "NATIVE",
|
|
519
|
+
defaultMessage: "Credentials are too large for one secret",
|
|
520
|
+
defaultDetails:
|
|
521
|
+
"A GitHub Actions secret holds at most 48 KB, and credentials/<platform>/ packs to more than that.",
|
|
522
|
+
suggestedAction:
|
|
523
|
+
"Remove files the build does not need from credentials/<platform>/ (only signing keys, profiles and their settings belong there), then export again.",
|
|
524
|
+
},
|
|
525
|
+
[ERROR_CODES.NATIVE_INVALID_APP_ID]: {
|
|
526
|
+
category: "NATIVE",
|
|
527
|
+
defaultMessage: "Invalid app id",
|
|
528
|
+
defaultDetails:
|
|
529
|
+
"The app id (WEBVIEW_CONFIG.appId, android.packageName or ios.bundleIdentifier / appBundleId) is not a valid id for the platform. Android needs a Java package name: two or more dot-separated parts, each starting with a letter and using only letters, digits and _, none a Java keyword. iOS needs two or more parts of letters, digits and -.",
|
|
530
|
+
suggestedAction:
|
|
531
|
+
"Set WEBVIEW_CONFIG.appId in config/config.json to a reverse-DNS id such as com.acme.shop: letters and digits only, each part starting with a letter.",
|
|
532
|
+
},
|
|
533
|
+
[ERROR_CODES.NATIVE_RELEASE_OUTPUT_EXISTS]: {
|
|
534
|
+
category: "NATIVE",
|
|
535
|
+
defaultMessage: "A release with this version and build number already exists",
|
|
536
|
+
defaultDetails:
|
|
537
|
+
"build-output/<platform>/<version>-<build>/ already holds a store artifact. The build number counts whole minutes, so two releases in the same minute get the same number, and a store refuses a build number it has already seen.",
|
|
538
|
+
suggestedAction:
|
|
539
|
+
"Wait a minute and run the release again, or set CATALYST_BUILD_NUMBER to a higher number. To rebuild the same build on purpose, delete that folder first.",
|
|
540
|
+
},
|
|
266
541
|
[ERROR_CODES.RUNTIME_NATIVE_PERMISSION_DENIED]: {
|
|
267
542
|
category: "RUNTIME-NATIVE",
|
|
268
543
|
defaultMessage: "Permission denied",
|
|
@@ -369,8 +644,10 @@ export const ERROR_DEFINITIONS = {
|
|
|
369
644
|
[ERROR_CODES.RUNTIME_NATIVE_BRIDGE_INVALID_CALLBACK]: {
|
|
370
645
|
category: "RUNTIME-NATIVE",
|
|
371
646
|
defaultMessage: "Invalid callback interface",
|
|
372
|
-
defaultDetails:
|
|
373
|
-
|
|
647
|
+
defaultDetails:
|
|
648
|
+
"The native platform invoked WebBridge.callback() with an interface name that isn't recognized.",
|
|
649
|
+
suggestedAction:
|
|
650
|
+
"Check the interface name against the registered NATIVE_CALLBACKS list; this usually indicates a native/JS version mismatch.",
|
|
374
651
|
},
|
|
375
652
|
[ERROR_CODES.RUNTIME_NATIVE_BRIDGE_HANDLER_NOT_REGISTERED]: {
|
|
376
653
|
category: "RUNTIME-NATIVE",
|
|
@@ -382,13 +659,15 @@ export const ERROR_DEFINITIONS = {
|
|
|
382
659
|
[ERROR_CODES.RUNTIME_NATIVE_BRIDGE_HANDLER_THREW]: {
|
|
383
660
|
category: "RUNTIME-NATIVE",
|
|
384
661
|
defaultMessage: "A registered bridge callback handler threw",
|
|
385
|
-
defaultDetails:
|
|
662
|
+
defaultDetails:
|
|
663
|
+
"The JS handler registered for this native callback interface threw an error while processing the callback.",
|
|
386
664
|
suggestedAction: "Fix the error thrown inside the registered handler (see the cause above).",
|
|
387
665
|
},
|
|
388
666
|
[ERROR_CODES.RUNTIME_NATIVE_BRIDGE_INVALID_REGISTRATION]: {
|
|
389
667
|
category: "RUNTIME-NATIVE",
|
|
390
668
|
defaultMessage: "Invalid bridge callback registration",
|
|
391
|
-
defaultDetails:
|
|
669
|
+
defaultDetails:
|
|
670
|
+
"WebBridge.register() was called with a non-function callback or an unrecognized interface name.",
|
|
392
671
|
suggestedAction: "Pass a function as the callback and a valid interface name from NATIVE_CALLBACKS.",
|
|
393
672
|
},
|
|
394
673
|
[ERROR_CODES.RUNTIME_NATIVE_BRIDGE_INIT_FAILED]: {
|
|
@@ -403,7 +682,8 @@ export const ERROR_DEFINITIONS = {
|
|
|
403
682
|
defaultMessage: "AI provider request failed",
|
|
404
683
|
defaultDetails:
|
|
405
684
|
"This is a wrapper around a non-2xx response or thrown error from the upstream AI provider (OpenAI/Gemini). See the printed upstream status/message for the actual cause — catalyst-ai does not reinterpret it.",
|
|
406
|
-
suggestedAction:
|
|
685
|
+
suggestedAction:
|
|
686
|
+
"Read the upstream provider error printed above and fix the underlying issue (auth, rate limit, invalid request).",
|
|
407
687
|
},
|
|
408
688
|
[ERROR_CODES.AI_DISABLED]: {
|
|
409
689
|
category: "AI",
|
|
@@ -414,31 +694,37 @@ export const ERROR_DEFINITIONS = {
|
|
|
414
694
|
[ERROR_CODES.AI_PROVIDER_NOT_CONFIGURED]: {
|
|
415
695
|
category: "AI",
|
|
416
696
|
defaultMessage: "AI provider not configured",
|
|
417
|
-
defaultDetails:
|
|
697
|
+
defaultDetails:
|
|
698
|
+
"The requested provider is unknown, or has no apiKey configured in AI_CONFIG.providers.",
|
|
418
699
|
suggestedAction: "Add the provider's apiKey to AI_CONFIG.providers, or use a configured provider.",
|
|
419
700
|
},
|
|
420
701
|
[ERROR_CODES.AI_INVALID_REQUEST_BODY]: {
|
|
421
702
|
category: "AI",
|
|
422
703
|
defaultMessage: "Invalid AI request body",
|
|
423
|
-
defaultDetails:
|
|
704
|
+
defaultDetails:
|
|
705
|
+
"The request body is missing a non-empty messages array, or no model could be resolved.",
|
|
424
706
|
suggestedAction: "Pass a non-empty messages array, and either a model or a provider defaultModel.",
|
|
425
707
|
},
|
|
426
708
|
[ERROR_CODES.AI_NATIVE_BRIDGE_UNAVAILABLE]: {
|
|
427
709
|
category: "AI",
|
|
428
710
|
defaultMessage: "Native AI bridge unavailable",
|
|
429
|
-
defaultDetails:
|
|
430
|
-
|
|
711
|
+
defaultDetails:
|
|
712
|
+
"window.NativeBridge.initAI or window.WebBridge was not found when useNativeAI mounted.",
|
|
713
|
+
suggestedAction:
|
|
714
|
+
"Update catalyst-core to >=0.2.0, add the native AI module, and call WebBridge.init() before mounting useNativeAI.",
|
|
431
715
|
},
|
|
432
716
|
[ERROR_CODES.AI_NATIVE_STREAM_NOT_READY]: {
|
|
433
717
|
category: "AI",
|
|
434
718
|
defaultMessage: "Native AI stream not ready",
|
|
435
|
-
defaultDetails:
|
|
719
|
+
defaultDetails:
|
|
720
|
+
"generate() was called before the native side reported a ready stream URL (initAI has not fired ON_AI_READY yet).",
|
|
436
721
|
suggestedAction: "Wait for modelReady to become true before calling generate().",
|
|
437
722
|
},
|
|
438
723
|
[ERROR_CODES.AI_NATIVE_REQUEST_FAILED]: {
|
|
439
724
|
category: "AI",
|
|
440
725
|
defaultMessage: "Native AI request failed",
|
|
441
|
-
defaultDetails:
|
|
726
|
+
defaultDetails:
|
|
727
|
+
"The native AI HTTP endpoint returned a non-ok status or reported an error in its response body.",
|
|
442
728
|
suggestedAction: "See the cause above for the native-reported status/message.",
|
|
443
729
|
},
|
|
444
730
|
[ERROR_CODES.AI_NATIVE_CALLBACK_ERROR]: {
|
|
@@ -451,7 +737,8 @@ export const ERROR_DEFINITIONS = {
|
|
|
451
737
|
[ERROR_CODES.AI_WEB_WORKER_UNAVAILABLE]: {
|
|
452
738
|
category: "AI",
|
|
453
739
|
defaultMessage: "Web AI worker unavailable",
|
|
454
|
-
defaultDetails:
|
|
740
|
+
defaultDetails:
|
|
741
|
+
"Constructing the module Worker for in-browser AI failed — module workers may be unsupported in this browser.",
|
|
455
742
|
suggestedAction: "Use a browser with module Worker support, or fall back to useCloudAI/useNativeAI.",
|
|
456
743
|
},
|
|
457
744
|
[ERROR_CODES.AI_WEB_WORKER_CRASHED]: {
|
|
@@ -459,7 +746,8 @@ export const ERROR_DEFINITIONS = {
|
|
|
459
746
|
defaultMessage: "Web AI worker crashed",
|
|
460
747
|
defaultDetails:
|
|
461
748
|
"The in-browser AI worker threw during model load or generation (e.g. all device backends failed, or an uncaught exception). See the cause above for the worker's reported message.",
|
|
462
|
-
suggestedAction:
|
|
749
|
+
suggestedAction:
|
|
750
|
+
"Check that the model is compatible with this browser/device, or use useCloudAI/useNativeAI instead.",
|
|
463
751
|
},
|
|
464
752
|
|
|
465
753
|
[ERROR_CODES.RUNTIME_WEB_RENDER_FAILED]: {
|