catalyst-core 0.2.0-beta.3 → 0.3.0-beta.2
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/babel.native.config.cjs +8 -0
- package/bin/catalyst.js +49 -105
- package/changelog.md +8 -0
- package/dist/caching.js +1 -1
- package/dist/globals.d.ts +7 -0
- package/dist/index.jsx +8 -0
- package/dist/logger.js +74 -3
- package/dist/native/androidProject/app/build.gradle.kts +45 -4
- package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/NativeBridge.kt +86 -0
- package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/utils/BridgeUtils.kt +8 -0
- package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/utils/FrameworkServerUtils.kt +173 -13
- package/dist/native/androidProject/settings.gradle.kts +10 -0
- package/dist/native/androidSetup.js +300 -8
- package/dist/native/bridge/WebBridge.js +481 -59
- package/dist/native/bridge/constants/NativeInterfaces.js +304 -45
- package/dist/native/bridge/errors.js +250 -26
- package/dist/native/bridge/hooks/index.js +132 -1
- package/dist/native/bridge/hooks/useAI.js +94 -0
- package/dist/native/bridge/hooks/useCamera.js +347 -9
- package/dist/native/bridge/hooks/useDataProtection.js +200 -2
- package/dist/native/bridge/hooks/useDeviceInfo.js +71 -2
- package/dist/native/bridge/hooks/useFilePicker.js +429 -2
- package/dist/native/bridge/hooks/useGoogleSignIn.js +81 -1
- package/dist/native/bridge/hooks/useHapticFeedback.js +196 -1
- package/dist/native/bridge/hooks/useIntent.js +95 -1
- package/dist/native/bridge/hooks/useNativeTransition.js +202 -27
- package/dist/native/bridge/hooks/useNetworkStatus.js +84 -3
- package/dist/native/bridge/hooks/useNotification.js +318 -2
- package/dist/native/bridge/hooks/useSafeArea.js +84 -2
- package/dist/native/bridge/hooks/useVideoStream.js +434 -6
- package/dist/native/bridge/hooks/utils.js +27 -1
- package/dist/native/bridge/hooks.js +16 -1
- package/dist/native/bridge/perf/collectors/ApiCollector.js +66 -3
- package/dist/native/bridge/perf/collectors/CacheCollector.js +186 -11
- package/dist/native/bridge/perf/collectors/HookCollector.js +141 -19
- package/dist/native/bridge/perf/collectors/InsightsCollector.js +481 -23
- package/dist/native/bridge/perf/collectors/InteractionCollector.js +245 -10
- package/dist/native/bridge/perf/collectors/KeyboardCollector.js +107 -8
- package/dist/native/bridge/perf/collectors/NavigationCollector.js +273 -32
- package/dist/native/bridge/perf/collectors/NetworkTimingCollector.js +178 -2
- package/dist/native/bridge/perf/collectors/RenderCollector.js +258 -14
- package/dist/native/bridge/perf/collectors/ScrollCollector.js +95 -9
- package/dist/native/bridge/perf/collectors/ThreadCollector.js +90 -6
- package/dist/native/bridge/perf/core/constants.js +103 -20
- package/dist/native/bridge/perf/core/measure.js +179 -30
- package/dist/native/bridge/perf/core/session.js +89 -23
- package/dist/native/bridge/perf/core/store.js +554 -1
- package/dist/native/bridge/perf/core/summary.js +174 -1
- package/dist/native/bridge/perf/core/traceExport.js +240 -1
- package/dist/native/bridge/perf/core/waterfalls.js +146 -1
- package/dist/native/bridge/perf/index.js +359 -38
- package/dist/native/bridge/safeArea.js +53 -5
- package/dist/native/bridge/standardizedHooks.js +595 -82
- package/dist/native/bridge/useBaseHook.js +274 -38
- package/dist/native/bridge/utils/CameraUtils.js +201 -56
- package/dist/native/bridge/utils/FileObjectConverter.js +129 -18
- package/dist/native/bridge/utils/NativeBridge.js +425 -141
- package/dist/native/buildAndroid/assets.js +510 -13
- package/dist/native/buildAndroid/build.js +296 -19
- package/dist/native/buildAndroid/config.js +87 -1
- package/dist/native/buildAndroid/index.js +406 -1
- package/dist/native/buildAppAndroid.js +34 -2
- package/dist/native/buildAppIos.js +62 -2
- package/dist/native/buildIos/assets.js +609 -8
- package/dist/native/buildIos/build.js +639 -20
- package/dist/native/buildIos/config.js +294 -12
- package/dist/native/buildIos/index.js +343 -6
- package/dist/native/buildIos/plugins.js +343 -16
- package/dist/native/internal-plugins/device-info-plugin/android/DeviceInfoPlugin.kt +43 -0
- package/dist/native/internal-plugins/device-info-plugin/ios/DeviceInfoPlugin.swift +28 -0
- package/dist/native/internal-plugins/device-info-plugin/manifest.json +19 -0
- package/dist/native/internalPluginUtils.js +232 -7
- package/dist/native/package.json +3 -0
- package/dist/native/plugin-bridge/PluginBridge.js +227 -1
- package/dist/native/pluginComposerAndroid.js +407 -23
- package/dist/native/pluginComposerIos.js +435 -11
- package/dist/native/renameAndroidProject.js +1094 -88
- package/dist/native/setupEmulatorIos.js +289 -22
- package/dist/native/setupServer.js +160 -19
- package/dist/native/terminalProgress.js +199 -11
- package/dist/native/utils.js +193 -15
- package/dist/offline/catalyst-sw.js +145 -1
- package/dist/offline/registerServiceWorker.js +33 -1
- package/dist/otel.js +375 -46
- package/dist/router/ClientRouter.js +14 -2
- package/dist/router/ServerRouter.js +9 -1
- package/dist/router.js +1 -1
- package/dist/scripts/build.js +112 -3
- package/dist/scripts/checkVersion.js +3 -1
- package/dist/scripts/cleanCache.js +30 -1
- package/dist/scripts/generateOfflineManifest.js +116 -1
- package/dist/scripts/loadEnvironmentVariables.js +32 -6
- package/dist/scripts/plugins.js +309 -1
- package/dist/scripts/preServerInit.js +13 -0
- package/dist/scripts/scriptUtils.js +54 -3
- package/dist/scripts/serve.js +51 -4
- package/dist/scripts/start.js +47 -10
- package/dist/scripts/validator.js +149 -1
- package/dist/sentry.cjs +127 -0
- package/dist/sentry.js +125 -5
- package/dist/server/expressServer.js +296 -5
- package/dist/server/manifestCache.js +36 -0
- package/dist/server/renderer/ChunkExtractor.js +144 -0
- package/dist/server/renderer/document/Body.jsx +59 -0
- package/dist/server/renderer/document/FastRefresh.jsx +20 -0
- package/dist/server/renderer/document/Head.jsx +60 -0
- package/dist/server/renderer/document/index.jsx +2 -0
- package/dist/server/renderer/extract.js +149 -31
- package/dist/server/renderer/handler.jsx +450 -0
- package/dist/server/renderer/index.js +8 -1
- package/dist/server/renderer/render.js +47 -0
- package/dist/server/utils/botDetectionMiddleware.js +29 -0
- package/dist/server/utils/cjsRequire.js +10 -0
- package/dist/server/utils/userAgentUtil.js +87 -9
- package/dist/server/utils/validator.js +164 -1
- package/dist/vite/FastRefresh.jsx +20 -0
- package/dist/vite/inject-cache-key-plugin.js +276 -0
- package/dist/vite/loadCustomViteConfig.js +22 -0
- package/dist/vite/manifest-categorization-plugin.js +455 -0
- package/dist/vite/node-loader.mjs +458 -0
- package/dist/vite/scssParams.js +21 -0
- package/dist/vite/vite.config.client.js +130 -0
- package/dist/vite/vite.config.js +498 -0
- package/dist/vite/vite.config.server.js +84 -0
- package/dist/web-router/components/MetaTag.jsx +34 -0
- package/dist/web-router/components/RouterDataProvider.jsx +332 -0
- package/dist/web-router/components/Split.jsx +200 -0
- package/dist/web-router/components/SplitInview.jsx +106 -0
- package/dist/web-router/components/SsrRequestContext.jsx +14 -0
- package/dist/web-router/context.jsx +12 -0
- package/dist/web-router/hooks.jsx +72 -0
- package/dist/web-router/types/components/MetaTag.d.ts +2 -0
- package/dist/web-router/types/components/RouterDataProvider.d.ts +95 -0
- package/dist/web-router/types/context.d.ts +14 -0
- package/dist/web-router/types/hooks.d.ts +1 -0
- package/dist/web-router/types/index.d.ts +3 -0
- package/dist/web-router/types/utils/metaDataUtils.d.ts +24 -0
- package/dist/web-router/utils/metaDataUtils.jsx +119 -0
- package/mcp_v2/conversion-tasks.json +35 -17
- package/mcp_v2/knowledge-base.json +176 -17
- package/mcp_v2/lib/helpers.js +10 -0
- package/mcp_v2/mcp.js +40 -8
- package/mcp_v2/package.json +1 -0
- package/mcp_v2/tools/build.js +161 -37
- package/mcp_v2/tools/conversion.js +106 -5
- package/mcp_v2/tools/tasks.js +18 -14
- package/package.json +35 -68
- package/babel.config.js +0 -32
- package/dist/index.js +0 -1
- package/dist/scripts/devBuild.js +0 -3
- package/dist/scripts/devServe.js +0 -3
- package/dist/scripts/loadScriptsBeforeServerStarts.js +0 -4
- package/dist/scripts/registerAliases.js +0 -6
- package/dist/server/renderer/document/Body.js +0 -11
- package/dist/server/renderer/document/Head.js +0 -9
- package/dist/server/renderer/document/index.js +0 -1
- package/dist/server/renderer/handler.js +0 -47
- package/dist/server/startServer.js +0 -57
- package/dist/webpack/babel-plugins/remove-client.plugin.js +0 -5
- package/dist/webpack/babel-plugins/remove-ssr.plugin.js +0 -5
- package/dist/webpack/babel.config.client.js +0 -1
- package/dist/webpack/babel.config.ssr.js +0 -1
- package/dist/webpack/base.babel.js +0 -7
- package/dist/webpack/development.client.babel.js +0 -10
- package/dist/webpack/production.client.babel.js +0 -4
- package/dist/webpack/production.ssr.babel.js +0 -8
- package/dist/webpack/scssParams.js +0 -9
package/bin/catalyst.js
CHANGED
|
@@ -1,128 +1,72 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
"use strict"
|
|
3
|
-
process.on("unhandledRejection", (err) => {
|
|
4
|
-
throw err
|
|
5
|
-
})
|
|
6
|
-
const { spawnSync } = require("node:child_process")
|
|
7
|
-
const args = process.argv.slice(2)
|
|
8
2
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
"plugin",
|
|
17
|
-
"plugins",
|
|
18
|
-
"buildApp",
|
|
19
|
-
"buildApp:ios",
|
|
20
|
-
"buildApp:android",
|
|
21
|
-
"setupEmulator",
|
|
22
|
-
"setupEmulator:ios",
|
|
23
|
-
"setupEmulator:android",
|
|
24
|
-
]
|
|
3
|
+
import { spawnSync } from "node:child_process"
|
|
4
|
+
import { dirname, resolve } from "node:path"
|
|
5
|
+
import { fileURLToPath } from "node:url"
|
|
6
|
+
|
|
7
|
+
process.on("unhandledRejection", (error) => {
|
|
8
|
+
throw error
|
|
9
|
+
})
|
|
25
10
|
|
|
26
|
-
|
|
11
|
+
const __dirname = dirname(fileURLToPath(import.meta.url))
|
|
12
|
+
const args = process.argv.slice(2)
|
|
13
|
+
const webCommands = new Set(["build", "start", "serve", "serve:inspect", "plugin", "plugins"])
|
|
27
14
|
const platformScripts = {
|
|
28
15
|
"setupEmulator:ios": "../dist/native/setupEmulatorIos.js",
|
|
29
16
|
"setupEmulator:android": "../dist/native/androidSetup.js",
|
|
30
17
|
"buildApp:ios": "../dist/native/buildAppIos.js",
|
|
31
18
|
"buildApp:android": "../dist/native/buildAppAndroid.js",
|
|
32
19
|
}
|
|
20
|
+
const validCommands = new Set([...webCommands, "buildApp", "setupEmulator", ...Object.keys(platformScripts)])
|
|
21
|
+
|
|
22
|
+
const scriptIndex = args.findIndex((arg) => validCommands.has(arg))
|
|
23
|
+
const script = scriptIndex === -1 ? args[0] : args[scriptIndex]
|
|
24
|
+
const nodeArgs = scriptIndex > 0 ? args.slice(0, scriptIndex) : []
|
|
25
|
+
const scriptArgs = args.slice(scriptIndex + 1)
|
|
33
26
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
27
|
+
function handleProcessResult(result) {
|
|
28
|
+
if (result.signal) {
|
|
29
|
+
if (result.signal === "SIGKILL") {
|
|
30
|
+
console.error("The Catalyst process was terminated with SIGKILL.")
|
|
31
|
+
} else if (result.signal === "SIGTERM") {
|
|
32
|
+
console.error("The Catalyst process was terminated with SIGTERM.")
|
|
33
|
+
}
|
|
34
|
+
process.exit(1)
|
|
35
|
+
}
|
|
36
|
+
process.exit(result.status ?? 1)
|
|
39
37
|
}
|
|
40
38
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
const command = `${baseCommand}:${platform}`
|
|
44
|
-
const result = spawnSync(
|
|
39
|
+
function runScript(relativePath, extraArgs = []) {
|
|
40
|
+
return spawnSync(
|
|
45
41
|
process.execPath,
|
|
46
|
-
nodeArgs
|
|
47
|
-
{
|
|
42
|
+
[...nodeArgs, resolve(__dirname, relativePath), ...extraArgs, ...scriptArgs],
|
|
43
|
+
{
|
|
44
|
+
stdio: "inherit",
|
|
45
|
+
}
|
|
48
46
|
)
|
|
49
|
-
return result
|
|
50
47
|
}
|
|
51
48
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
}
|
|
49
|
+
function runPlatformCommand(command) {
|
|
50
|
+
return runScript(platformScripts[command])
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (script === "buildApp" || script === "setupEmulator") {
|
|
54
|
+
for (const platform of ["ios", "android"]) {
|
|
55
|
+
const result = runPlatformCommand(`${script}:${platform}`)
|
|
56
|
+
if (result.status !== 0 || result.signal) handleProcessResult(result)
|
|
61
57
|
}
|
|
62
58
|
process.exit(0)
|
|
63
59
|
}
|
|
64
60
|
|
|
65
|
-
|
|
66
|
-
(
|
|
67
|
-
x === "build" ||
|
|
68
|
-
x === "start" ||
|
|
69
|
-
x === "serve" ||
|
|
70
|
-
x === "devBuild" ||
|
|
71
|
-
x === "devServe" ||
|
|
72
|
-
x === "plugin" ||
|
|
73
|
-
x === "plugins" ||
|
|
74
|
-
isPlatformCommand(x, "buildApp") ||
|
|
75
|
-
isPlatformCommand(x, "setupEmulator")
|
|
76
|
-
)
|
|
77
|
-
const script = scriptIndex === -1 ? args[0] : args[scriptIndex]
|
|
78
|
-
const nodeArgs = scriptIndex > 0 ? args.slice(0, scriptIndex) : []
|
|
79
|
-
const resolvedScript = script === "plugin" ? "plugins" : script
|
|
80
|
-
|
|
81
|
-
if (validCommands.includes(script)) {
|
|
82
|
-
// Handle platform-specific or combined commands
|
|
83
|
-
if (script === "buildApp" || script === "setupEmulator") {
|
|
84
|
-
// Run for all platforms if no specific platform is specified
|
|
85
|
-
runAllPlatforms(script)
|
|
86
|
-
} else if (script in platformScripts) {
|
|
87
|
-
// Run for specific platform
|
|
88
|
-
const result = spawnSync(
|
|
89
|
-
process.execPath,
|
|
90
|
-
nodeArgs.concat(require.resolve(platformScripts[script])).concat(args.slice(scriptIndex + 1)),
|
|
91
|
-
{ stdio: "inherit" }
|
|
92
|
-
)
|
|
93
|
-
handleProcessResult(result)
|
|
94
|
-
} else {
|
|
95
|
-
// Original commands
|
|
96
|
-
const result = spawnSync(
|
|
97
|
-
process.execPath,
|
|
98
|
-
nodeArgs
|
|
99
|
-
.concat(require.resolve("../dist/scripts/" + resolvedScript))
|
|
100
|
-
.concat(args.slice(scriptIndex + 1)),
|
|
101
|
-
{ stdio: "inherit" }
|
|
102
|
-
)
|
|
103
|
-
handleProcessResult(result)
|
|
104
|
-
}
|
|
105
|
-
} else {
|
|
106
|
-
console.log('Unknown script "' + script + '".')
|
|
61
|
+
if (platformScripts[script]) {
|
|
62
|
+
handleProcessResult(runPlatformCommand(script))
|
|
107
63
|
}
|
|
108
64
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
console.log(
|
|
114
|
-
"The build failed because the process exited too early. " +
|
|
115
|
-
"This probably means the system ran out of memory or someone called " +
|
|
116
|
-
"`kill -9` on the process."
|
|
117
|
-
)
|
|
118
|
-
} else if (result.signal === "SIGTERM") {
|
|
119
|
-
console.log(
|
|
120
|
-
"The build failed because the process exited too early. " +
|
|
121
|
-
"Someone might have called `kill` or `killall`, or the system could " +
|
|
122
|
-
"be shutting down."
|
|
123
|
-
)
|
|
124
|
-
}
|
|
125
|
-
process.exit(1)
|
|
126
|
-
}
|
|
127
|
-
process.exit(result.status)
|
|
65
|
+
if (webCommands.has(script)) {
|
|
66
|
+
const scriptName = script === "plugin" ? "plugins" : script === "serve:inspect" ? "serve" : script
|
|
67
|
+
const extraArgs = script === "serve:inspect" ? ["--inspect"] : []
|
|
68
|
+
handleProcessResult(runScript(`../dist/scripts/${scriptName}.js`, extraArgs))
|
|
128
69
|
}
|
|
70
|
+
|
|
71
|
+
console.error(`Unknown script "${script}".`)
|
|
72
|
+
process.exit(1)
|
package/changelog.md
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
# 1.0.0-beta.1
|
|
2
|
+
|
|
3
|
+
- Replaced the Webpack build and SSR pipeline with Vite and ESM.
|
|
4
|
+
- Added React 19 Suspense-aware routing, split components, and manifest-based asset loading.
|
|
5
|
+
- Added opt-in request, compression, flush, and bot-aware OpenTelemetry spans.
|
|
6
|
+
- Preserved native application builds, internal plugins, Sentry exports, and safe-area SSR hydration.
|
|
7
|
+
- Removed the legacy `devBuild` and `devServe` commands.
|
|
8
|
+
|
|
1
9
|
# Changelog
|
|
2
10
|
|
|
3
11
|
## [0.1.0-beta.2] - 2026-05-06
|
package/dist/caching.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
export * from "@tata1mg/api-caching"
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// Injected by webpack DefinePlugin in base.babel.js at build time.
|
|
2
|
+
// Reflects which @catalyst/* packages are present in the app's node_modules.
|
|
3
|
+
declare const __CATALYST_PACKAGES__: {
|
|
4
|
+
readonly ai: boolean
|
|
5
|
+
readonly webAILocal: boolean
|
|
6
|
+
readonly nativeAILocal: boolean
|
|
7
|
+
}
|
package/dist/index.jsx
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export * from "react-router-dom"
|
|
2
|
+
export * from "./web-router/components/RouterDataProvider.jsx"
|
|
3
|
+
export * from "./web-router/components/MetaTag.jsx"
|
|
4
|
+
export { split, hydrationReady } from "./web-router/components/Split.jsx"
|
|
5
|
+
export { split as default } from "./web-router/components/Split.jsx"
|
|
6
|
+
export * from "./web-router/hooks.jsx"
|
|
7
|
+
export * from "./web-router/utils/metaDataUtils.jsx"
|
|
8
|
+
export * from "./server/renderer/document/index.jsx"
|
package/dist/logger.js
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
import pc from "picocolors"
|
|
2
|
+
import winston from "winston"
|
|
3
|
+
import DailyRotateFile from "winston-daily-rotate-file"
|
|
4
|
+
|
|
5
|
+
const { createLogger, format, transports } = winston
|
|
6
|
+
|
|
7
|
+
/**
|
|
2
8
|
* @description Logger library with rotational strategy. Creates a logs folder in root.
|
|
3
9
|
* With debug, error and info log directories with their respective log files.
|
|
4
10
|
*
|
|
@@ -6,5 +12,70 @@
|
|
|
6
12
|
* @param config { @enableDebugLogs: Bool // default: true }
|
|
7
13
|
* @returns loggerInstance
|
|
8
14
|
*
|
|
9
|
-
*/
|
|
10
|
-
|
|
15
|
+
*/
|
|
16
|
+
const configureLogger = (config = {}) => {
|
|
17
|
+
const { enableDebugLogs = true, enableFileLogging = true, enableConsoleLogging = true } = config
|
|
18
|
+
|
|
19
|
+
const consoleTransport = new transports.Console({ level: "debug" })
|
|
20
|
+
|
|
21
|
+
const fileTransport = (type = "info") => {
|
|
22
|
+
return new DailyRotateFile({
|
|
23
|
+
filename: `${process.env.src_path}/logs/${type}/%DATE%.${type}.log`,
|
|
24
|
+
datePattern: "YYYY-MM-DD",
|
|
25
|
+
maxFiles: "3d", // Logs will be removed after 2days,
|
|
26
|
+
loglevel: type,
|
|
27
|
+
level: type,
|
|
28
|
+
})
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const infoLogger = createLogger({
|
|
32
|
+
format: format.combine(format.timestamp({ format: "YYYY-MM-DD HH:mm:ss" }), format.json()),
|
|
33
|
+
defaultMeta: { loglevel: "info" },
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
const debugLogger = createLogger({
|
|
37
|
+
format: format.combine(format.timestamp({ format: "YYYY-MM-DD HH:mm:ss" }), format.json()),
|
|
38
|
+
defaultMeta: { loglevel: "debug" },
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
const errorLogger = createLogger({
|
|
42
|
+
format: format.combine(format.timestamp({ format: "YYYY-MM-DD HH:mm:ss" }), format.json()),
|
|
43
|
+
defaultMeta: { loglevel: "error" },
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
if (enableConsoleLogging && JSON.parse(enableConsoleLogging)) {
|
|
47
|
+
infoLogger.add(consoleTransport)
|
|
48
|
+
debugLogger.add(consoleTransport)
|
|
49
|
+
errorLogger.add(consoleTransport)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (enableFileLogging && JSON.parse(enableFileLogging)) {
|
|
53
|
+
infoLogger.add(fileTransport("info"))
|
|
54
|
+
debugLogger.add(fileTransport("debug"))
|
|
55
|
+
errorLogger.add(fileTransport("error"))
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const Logger = {
|
|
59
|
+
debug: () => {},
|
|
60
|
+
error: (msg) => {
|
|
61
|
+
console.log(pc.red(pc.bold("ERROR: " + JSON.stringify(msg))))
|
|
62
|
+
errorLogger.error(msg)
|
|
63
|
+
},
|
|
64
|
+
info: (msg) => {
|
|
65
|
+
console.log(pc.green(pc.bold("INFO: " + JSON.stringify(msg))))
|
|
66
|
+
infoLogger.info(msg)
|
|
67
|
+
},
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (enableDebugLogs && JSON.parse(enableDebugLogs)) {
|
|
71
|
+
Logger.debug = (msg) => {
|
|
72
|
+
console.log(pc.yellow(pc.bold("DEBUG: " + JSON.stringify(msg))))
|
|
73
|
+
debugLogger.debug(msg)
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (global) global.logger = Logger
|
|
78
|
+
return Logger
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export { configureLogger }
|
|
@@ -60,6 +60,22 @@ fun isNotificationsEnabled(): Boolean {
|
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
+
fun isAIEnabled(): Boolean {
|
|
64
|
+
return try {
|
|
65
|
+
if (configPath == null) return false
|
|
66
|
+
val configFile = File(configPath!!)
|
|
67
|
+
if (!configFile.exists()) return false
|
|
68
|
+
|
|
69
|
+
val json = JSONObject(configFile.readText())
|
|
70
|
+
if (!json.has("WEBVIEW_CONFIG")) return false
|
|
71
|
+
|
|
72
|
+
val webviewConfig = json.getJSONObject("WEBVIEW_CONFIG")
|
|
73
|
+
webviewConfig.optJSONObject("ai")?.optBoolean("enabled", false) ?: false
|
|
74
|
+
} catch (e: Exception) {
|
|
75
|
+
false
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
63
79
|
fun getLocalIpAddress(): String {
|
|
64
80
|
return NetworkInterface.getNetworkInterfaces().toList()
|
|
65
81
|
.flatMap { it.inetAddresses.toList() }
|
|
@@ -151,6 +167,7 @@ android {
|
|
|
151
167
|
|
|
152
168
|
kotlinOptions {
|
|
153
169
|
jvmTarget = "11"
|
|
170
|
+
freeCompilerArgs += "-Xskip-metadata-version-check"
|
|
154
171
|
}
|
|
155
172
|
|
|
156
173
|
buildFeatures {
|
|
@@ -168,8 +185,9 @@ android {
|
|
|
168
185
|
excludes.add("META-INF/io.netty.versions.properties")
|
|
169
186
|
}
|
|
170
187
|
jniLibs {
|
|
171
|
-
//
|
|
172
|
-
useLegacyPackaging
|
|
188
|
+
// libLiteRtClGlAccelerator.so must be extracted to disk for GPU dlopen().
|
|
189
|
+
// This must live in the app module — AGP ignores useLegacyPackaging in library modules.
|
|
190
|
+
useLegacyPackaging = isAIEnabled()
|
|
173
191
|
}
|
|
174
192
|
}
|
|
175
193
|
|
|
@@ -186,7 +204,7 @@ android {
|
|
|
186
204
|
}
|
|
187
205
|
}
|
|
188
206
|
|
|
189
|
-
// Conditional source sets based on
|
|
207
|
+
// Conditional source sets based on feature config
|
|
190
208
|
sourceSets {
|
|
191
209
|
getByName("main") {
|
|
192
210
|
if (isNotificationsEnabled()) {
|
|
@@ -196,6 +214,20 @@ android {
|
|
|
196
214
|
logger.info("SourceSet selected: noFcm (notifications disabled)")
|
|
197
215
|
java.srcDirs("src/noFcm/java")
|
|
198
216
|
}
|
|
217
|
+
// AI has no source-set swap — CatalystAIBridge self-registers via ServiceLoader
|
|
218
|
+
// when @catalyst/cloud-ai is on the classpath.
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
configurations.all {
|
|
224
|
+
resolutionStrategy.eachDependency {
|
|
225
|
+
if (requested.group == "org.jetbrains.kotlin" &&
|
|
226
|
+
(requested.name == "kotlin-stdlib" ||
|
|
227
|
+
requested.name == "kotlin-stdlib-jdk7" ||
|
|
228
|
+
requested.name == "kotlin-stdlib-jdk8" ||
|
|
229
|
+
requested.name == "kotlin-reflect")) {
|
|
230
|
+
useVersion("2.0.21")
|
|
199
231
|
}
|
|
200
232
|
}
|
|
201
233
|
}
|
|
@@ -217,7 +249,16 @@ dependencies {
|
|
|
217
249
|
implementation("io.ktor:ktor-server-core:3.0.3")
|
|
218
250
|
implementation("io.ktor:ktor-server-netty:3.0.3")
|
|
219
251
|
implementation("io.ktor:ktor-server-content-negotiation:3.0.3")
|
|
220
|
-
implementation("
|
|
252
|
+
implementation("io.ktor:ktor-server-sse:3.0.3")
|
|
253
|
+
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.9.0")
|
|
254
|
+
|
|
255
|
+
// Native AI — compileOnly always (for types), implementation only when ai.enabled=true (for runtime bundling)
|
|
256
|
+
if (project.findProject(":catalyst-cloud-ai") != null) {
|
|
257
|
+
compileOnly(project(":catalyst-cloud-ai"))
|
|
258
|
+
if (isAIEnabled()) {
|
|
259
|
+
implementation(project(":catalyst-cloud-ai"))
|
|
260
|
+
}
|
|
261
|
+
}
|
|
221
262
|
|
|
222
263
|
// Security detection dependencies
|
|
223
264
|
implementation("com.scottyab:rootbeer-lib:0.1.1") // Root detection
|
package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/NativeBridge.kt
CHANGED
|
@@ -16,12 +16,15 @@ import androidx.credentials.exceptions.GetCredentialCancellationException
|
|
|
16
16
|
import androidx.credentials.exceptions.GetCredentialException
|
|
17
17
|
import com.google.android.libraries.identity.googleid.GetSignInWithGoogleOption
|
|
18
18
|
import com.google.android.libraries.identity.googleid.GoogleIdTokenCredential
|
|
19
|
+
// LiteRT imports removed — AI logic lives in catalyst-ai (CatalystAIBridge plugin)
|
|
19
20
|
import io.yourname.androidproject.MainActivity
|
|
20
21
|
import io.yourname.androidproject.utils.*
|
|
21
22
|
import kotlinx.coroutines.*
|
|
22
23
|
import org.json.JSONArray
|
|
23
24
|
import org.json.JSONObject
|
|
25
|
+
import java.io.File
|
|
24
26
|
import java.util.Properties
|
|
27
|
+
import java.util.ServiceLoader
|
|
25
28
|
import java.util.concurrent.atomic.AtomicBoolean
|
|
26
29
|
|
|
27
30
|
private data class FilePickerOptions(
|
|
@@ -151,6 +154,61 @@ class NativeBridge(
|
|
|
151
154
|
|
|
152
155
|
private var networkMonitor: NetworkMonitor? = null
|
|
153
156
|
|
|
157
|
+
// AI plugin — loaded via reflection so NativeBridge.kt compiles with no compile-time dep on
|
|
158
|
+
// :catalyst-ai. When the module is absent the try block returns null gracefully.
|
|
159
|
+
private val aiBridge: Any? = try {
|
|
160
|
+
@Suppress("UNCHECKED_CAST")
|
|
161
|
+
run {
|
|
162
|
+
val bridgeClass = Class.forName("io.catalyst.nativeai.AIBridge")
|
|
163
|
+
val callbacksClass = Class.forName("io.catalyst.nativeai.AIBridgeCallbacks")
|
|
164
|
+
@Suppress("UNCHECKED_CAST")
|
|
165
|
+
val loader = ServiceLoader.load(bridgeClass as Class<Any>)
|
|
166
|
+
val bridge = loader.iterator().takeIf { it.hasNext() }?.next() ?: return@run null
|
|
167
|
+
|
|
168
|
+
val callbacksProxy = java.lang.reflect.Proxy.newProxyInstance(
|
|
169
|
+
bridgeClass.classLoader,
|
|
170
|
+
arrayOf(callbacksClass)
|
|
171
|
+
) { _, method, args ->
|
|
172
|
+
val a = args ?: emptyArray()
|
|
173
|
+
when (method.name) {
|
|
174
|
+
"onReady" -> {
|
|
175
|
+
val payload = org.json.JSONObject().apply {
|
|
176
|
+
put("url", a[0]); put("port", a[1]); put("sessionId", a[2])
|
|
177
|
+
}
|
|
178
|
+
BridgeUtils.notifyWebJson(webView, BridgeUtils.WebEvents.ON_AI_READY, payload)
|
|
179
|
+
}
|
|
180
|
+
"onProgress" -> {
|
|
181
|
+
val payload = org.json.JSONObject().apply {
|
|
182
|
+
put("phase", a[0]); put("percent", a[1])
|
|
183
|
+
put("bytesLoaded", a[2]); put("bytesTotal", a[3]); put("detail", a[4])
|
|
184
|
+
}
|
|
185
|
+
BridgeUtils.notifyWebJson(webView, BridgeUtils.WebEvents.ON_AI_PROGRESS, payload)
|
|
186
|
+
}
|
|
187
|
+
"onLog" -> {
|
|
188
|
+
val payload = org.json.JSONObject().apply { put("message", a[0]) }
|
|
189
|
+
BridgeUtils.notifyWebJson(webView, BridgeUtils.WebEvents.ON_AI_LOG, payload)
|
|
190
|
+
}
|
|
191
|
+
"onError" -> BridgeUtils.notifyWebError(webView, BridgeUtils.WebEvents.ON_AI_ERROR, a[0] as String)
|
|
192
|
+
"isFrameworkServerRunning" -> FrameworkServerUtils.isRunning()
|
|
193
|
+
"getFrameworkServerPort" -> FrameworkServerUtils.getServerPort()
|
|
194
|
+
"getFrameworkServerSessionId" -> FrameworkServerUtils.getSessionId()
|
|
195
|
+
"setNativeAiSupplier" -> {
|
|
196
|
+
@Suppress("UNCHECKED_CAST")
|
|
197
|
+
FrameworkServerUtils.setNativeAiSupplier(
|
|
198
|
+
a[0] as suspend (String, org.json.JSONObject, String?) -> Pair<String, kotlinx.coroutines.flow.Flow<String>>
|
|
199
|
+
)
|
|
200
|
+
}
|
|
201
|
+
"setNativeSystemPrompt" -> FrameworkServerUtils.setNativeSystemPrompt(a[0] as String)
|
|
202
|
+
else -> null
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
bridge.javaClass.getMethod("attach", android.app.Activity::class.java, android.webkit.WebView::class.java, callbacksClass)
|
|
207
|
+
.invoke(bridge, mainActivity, webView, callbacksProxy)
|
|
208
|
+
bridge
|
|
209
|
+
}
|
|
210
|
+
} catch (_: Throwable) { null }
|
|
211
|
+
|
|
154
212
|
// Video stream manager
|
|
155
213
|
private var nativeCameraManager: NativeCameraManager? = null
|
|
156
214
|
private var webViewOriginalBackground: Int = android.graphics.Color.WHITE
|
|
@@ -1301,6 +1359,34 @@ class NativeBridge(
|
|
|
1301
1359
|
}
|
|
1302
1360
|
}
|
|
1303
1361
|
|
|
1362
|
+
// -------------------------------------------------------------------------
|
|
1363
|
+
// Native AI bridge methods — delegated to AIBridge plugin (ServiceLoader)
|
|
1364
|
+
// -------------------------------------------------------------------------
|
|
1365
|
+
|
|
1366
|
+
@JavascriptInterface
|
|
1367
|
+
fun isAIAvailable(): Boolean = aiBridge != null
|
|
1368
|
+
|
|
1369
|
+
@JavascriptInterface
|
|
1370
|
+
fun initAI(optionsRaw: String?) {
|
|
1371
|
+
BridgeUtils.safeExecute(webView, BridgeUtils.WebEvents.ON_AI_ERROR, "initialize AI") {
|
|
1372
|
+
aiBridge?.javaClass?.getMethod("initAI", String::class.java)?.invoke(aiBridge, optionsRaw)
|
|
1373
|
+
}
|
|
1374
|
+
}
|
|
1375
|
+
|
|
1376
|
+
@JavascriptInterface
|
|
1377
|
+
fun generateNative(optionsRaw: String?) {
|
|
1378
|
+
BridgeUtils.safeExecute(webView, BridgeUtils.WebEvents.ON_AI_ERROR, "generate with native AI") {
|
|
1379
|
+
aiBridge?.javaClass?.getMethod("generateNative", String::class.java)?.invoke(aiBridge, optionsRaw)
|
|
1380
|
+
}
|
|
1381
|
+
}
|
|
1382
|
+
|
|
1383
|
+
@JavascriptInterface
|
|
1384
|
+
fun clearNativeConversation() {
|
|
1385
|
+
BridgeUtils.safeExecute(webView, BridgeUtils.WebEvents.ON_AI_ERROR, "clear native conversation") {
|
|
1386
|
+
aiBridge?.javaClass?.getMethod("clearConversation")?.invoke(aiBridge)
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1389
|
+
|
|
1304
1390
|
/**
|
|
1305
1391
|
* Cleanup method to be called when the bridge is being destroyed
|
|
1306
1392
|
*/
|
package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/utils/BridgeUtils.kt
CHANGED
|
@@ -97,6 +97,14 @@ object BridgeUtils {
|
|
|
97
97
|
ON_TRANSITION_CANCELLED("ON_TRANSITION_CANCELLED"),
|
|
98
98
|
ON_TRANSITION_TIMEOUT("ON_TRANSITION_TIMEOUT"),
|
|
99
99
|
|
|
100
|
+
// Native AI events
|
|
101
|
+
ON_AI_READY("ON_AI_READY"),
|
|
102
|
+
ON_AI_ERROR("ON_AI_ERROR"),
|
|
103
|
+
ON_AI_TOKEN("ON_AI_TOKEN"),
|
|
104
|
+
ON_AI_DONE("ON_AI_DONE"),
|
|
105
|
+
ON_AI_PROGRESS("ON_AI_PROGRESS"),
|
|
106
|
+
ON_AI_LOG("ON_AI_LOG"),
|
|
107
|
+
|
|
100
108
|
// Perf telemetry
|
|
101
109
|
CATALYST_PERF_EVENT("CATALYST_PERF_EVENT"),
|
|
102
110
|
}
|