catalyst-core 0.1.0-canary.9 → 0.2.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/README.md +1 -1
- package/bin/catalyst.js +8 -1
- package/changelog.md +6 -0
- package/dist/native/androidProject/app/build.gradle.kts +34 -8
- package/dist/native/androidProject/app/src/main/AndroidManifest.xml +2 -1
- package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/BridgeMessageValidator.kt +1 -1
- package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/CustomWebview.kt +270 -78
- package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/MainActivity.kt +34 -5
- package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/NativeBridge.kt +149 -1
- package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/NativeCameraManager.kt +337 -0
- package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/OfflineCacheService.kt +374 -0
- package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/TransitionManager.kt +202 -0
- package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/WebCacheManager.kt +156 -39
- package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/camera/BarcodeDetector.kt +123 -0
- package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/camera/CameraSessionManager.kt +244 -0
- package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/camera/HoldController.kt +70 -0
- package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/camera/TorchController.kt +57 -0
- package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/camera/VideoStreamState.kt +41 -0
- package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/camera/VideoStreamStateMachine.kt +40 -0
- package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/camera/ViewfinderMapper.kt +75 -0
- package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/camera/ZoomController.kt +156 -0
- package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/plugins/CatalystPlugin.kt +7 -0
- package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/plugins/GeneratedPluginIndex.kt +6 -0
- package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/plugins/PluginBridge.kt +253 -0
- package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/security/FridaDetector.kt +16 -5
- package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/utils/BridgeUtils.kt +42 -5
- package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/utils/FrameworkServerUtils.kt +7 -3
- package/dist/native/androidProject/app/src/main/res/drawable/debug_viewfinder_border.xml +8 -0
- package/dist/native/androidProject/app/src/main/res/layout/activity_main.xml +37 -0
- package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/CustomWebviewTest.kt +7 -2
- package/dist/native/androidProject/app/src/test/java/io/yourname/androidproject/plugins/PluginBridgeTest.kt +139 -0
- package/dist/native/androidSetup.js +1 -0
- package/dist/native/bridge/WebBridge.js +5 -5
- package/dist/native/bridge/constants/NativeInterfaces.js +9 -5
- package/dist/native/bridge/hooks/index.js +1 -0
- package/dist/native/bridge/hooks/useCamera.js +9 -0
- package/dist/native/bridge/hooks/useDataProtection.js +2 -0
- package/dist/native/bridge/hooks/useDeviceInfo.js +2 -0
- package/dist/native/bridge/hooks/useFilePicker.js +2 -0
- package/dist/native/bridge/hooks/useGoogleSignIn.js +1 -0
- package/dist/native/bridge/hooks/useHapticFeedback.js +1 -0
- package/dist/native/bridge/hooks/useIntent.js +1 -0
- package/dist/native/bridge/hooks/useNativeTransition.js +43 -0
- package/dist/native/bridge/hooks/useNetworkStatus.js +3 -0
- package/dist/native/bridge/hooks/useNotification.js +2 -0
- package/dist/native/bridge/hooks/useSafeArea.js +2 -0
- package/dist/native/bridge/hooks/useVideoStream.js +6 -0
- package/dist/native/bridge/hooks/utils.js +1 -0
- package/dist/native/bridge/hooks.js +1 -137
- package/dist/native/bridge/useBaseHook.js +12 -7
- package/dist/native/bridge/utils/NativeBridge.js +41 -6
- package/dist/native/buildAndroid/assets.js +52 -0
- package/dist/native/buildAndroid/build.js +19 -0
- package/dist/native/buildAndroid/config.js +1 -0
- package/dist/native/buildAndroid/index.js +1 -0
- package/dist/native/buildAppAndroid.js +2 -150
- package/dist/native/buildAppIos.js +2 -312
- package/dist/native/buildIos/assets.js +8 -0
- package/dist/native/buildIos/build.js +40 -0
- package/dist/native/buildIos/config.js +71 -0
- package/dist/native/buildIos/index.js +6 -0
- package/dist/native/buildIos/plugins.js +45 -0
- package/dist/native/internalPluginUtils.js +7 -0
- package/dist/native/iosnativeWebView/Package.resolved +36 -0
- package/dist/native/iosnativeWebView/Sources/Core/Camera/BarcodeDetector.swift +116 -0
- package/dist/native/iosnativeWebView/Sources/Core/Camera/CameraPreviewView.swift +58 -0
- package/dist/native/iosnativeWebView/Sources/Core/Camera/CameraSessionManager.swift +308 -0
- package/dist/native/iosnativeWebView/Sources/Core/Camera/HoldController.swift +63 -0
- package/dist/native/iosnativeWebView/Sources/Core/Camera/NativeCameraManager.swift +194 -0
- package/dist/native/iosnativeWebView/Sources/Core/Camera/TorchController.swift +60 -0
- package/dist/native/iosnativeWebView/Sources/Core/Camera/VideoStreamState.swift +44 -0
- package/dist/native/iosnativeWebView/Sources/Core/Camera/VideoStreamStateMachine.swift +60 -0
- package/dist/native/iosnativeWebView/Sources/Core/Camera/ZoomController.swift +130 -0
- package/dist/native/iosnativeWebView/Sources/Core/Constants/CatalystConstants.swift +11 -1
- package/dist/native/iosnativeWebView/Sources/Core/Constants/ConfigConstants.swift +2 -1
- package/dist/native/iosnativeWebView/Sources/Core/Plugins/CatalystPlugin.swift +5 -0
- package/dist/native/iosnativeWebView/Sources/Core/Plugins/GeneratedPluginIndex.swift +6 -0
- package/dist/native/iosnativeWebView/Sources/Core/Plugins/PluginBridge.swift +364 -0
- package/dist/native/iosnativeWebView/Sources/Core/Utils/CacheManager.swift +39 -4
- package/dist/native/iosnativeWebView/Sources/Core/Utils/OfflineCacheService.swift +683 -0
- package/dist/native/iosnativeWebView/Sources/Core/Utils/OfflineURLSchemeHandler.swift +94 -0
- package/dist/native/iosnativeWebView/Sources/Core/Utils/ResourceURLProtocol.swift +19 -6
- package/dist/native/iosnativeWebView/Sources/Core/Utils/SafeAreaUtils.swift +1 -0
- package/dist/native/iosnativeWebView/Sources/Core/WebView/BridgeCommandHandler.swift +1 -0
- package/dist/native/iosnativeWebView/Sources/Core/WebView/BridgeMessageValidator.swift +4 -1
- package/dist/native/iosnativeWebView/Sources/Core/WebView/NativeBridge.swift +227 -4
- package/dist/native/iosnativeWebView/Sources/Core/WebView/TransitionManager.swift +169 -0
- package/dist/native/iosnativeWebView/Sources/Core/WebView/WeakScriptMessageHandler.swift +14 -0
- package/dist/native/iosnativeWebView/Sources/Core/WebView/WebView.swift +53 -8
- package/dist/native/iosnativeWebView/Sources/Core/WebView/WebViewNavigationDelegate.swift +88 -4
- package/dist/native/iosnativeWebView/iosnativeWebView/ContentView.swift +30 -11
- package/dist/native/iosnativeWebView/iosnativeWebView/Info.plist +11 -17
- package/dist/native/iosnativeWebView/iosnativeWebView.xcodeproj/project.pbxproj +8 -2
- package/dist/native/iosnativeWebView/iosnativeWebViewTests/BootTimingUtilityTests.swift +1 -1
- package/dist/native/iosnativeWebView/iosnativeWebViewTests/ConfigMappingTests.swift +4 -2
- package/dist/native/iosnativeWebView/iosnativeWebViewTests/PluginBridgeTests.swift +160 -0
- package/dist/native/plugin-bridge/PluginBridge.js +1 -0
- package/dist/native/pluginComposerAndroid.js +28 -0
- package/dist/native/pluginComposerIos.js +16 -0
- package/dist/native/renameAndroidProject.js +5 -5
- package/dist/native/setupEmulatorIos.js +6 -4
- package/dist/native/setupServer.js +2 -3
- package/dist/native/utils.js +4 -1
- package/dist/offline/catalyst-sw.js +1 -0
- package/dist/offline/registerServiceWorker.js +1 -0
- package/dist/otel.js +70 -2
- package/dist/router/ClientRouter.js +1 -1
- package/dist/scripts/build.js +1 -1
- package/dist/scripts/cleanCache.js +1 -0
- package/dist/scripts/devBuild.js +1 -1
- package/dist/scripts/devServe.js +1 -1
- package/dist/scripts/generateOfflineManifest.js +1 -0
- package/dist/scripts/loadEnvironmentVariables.js +1 -2
- package/dist/scripts/plugins.js +1 -0
- package/dist/scripts/registerAliases.js +6 -2
- package/dist/scripts/scriptUtils.js +2 -1
- package/dist/scripts/serve.js +2 -1
- package/dist/scripts/start.js +7 -2
- package/dist/server/expressServer.js +4 -8
- package/dist/server/renderer/document/Body.js +4 -4
- package/dist/server/renderer/document/Head.js +2 -2
- package/dist/server/renderer/extract.js +31 -27
- package/dist/server/renderer/handler.js +47 -24
- package/dist/server/renderer/index.js +1 -1
- package/dist/server/startServer.js +57 -7
- package/dist/server/utils/userAgentUtil.js +9 -3
- package/dist/server/utils/validator.js +1 -1
- package/dist/webpack/babel-plugins/remove-client.plugin.js +2 -2
- package/dist/webpack/babel-plugins/remove-ssr.plugin.js +2 -2
- package/dist/webpack/babel.config.client.js +1 -1
- package/dist/webpack/babel.config.ssr.js +1 -1
- package/dist/webpack/base.babel.js +7 -8
- package/dist/webpack/development.client.babel.js +7 -16
- package/dist/webpack/production.client.babel.js +1 -1
- package/dist/webpack/production.ssr.babel.js +5 -1
- package/mcp_v2/knowledge-base.json +206 -100
- package/mcp_v2/lib/helpers.js +42 -8
- package/mcp_v2/lib/seed.js +88 -0
- package/mcp_v2/mcp.js +150 -4
- package/mcp_v2/setup.js +30 -193
- package/mcp_v2/tools/build.js +1 -1
- package/mcp_v2/tools/config.js +16 -4
- package/mcp_v2/tools/conversion.js +11 -11
- package/mcp_v2/tools/github.js +1117 -0
- package/mcp_v2/tools/knowledge.js +16 -3
- package/mcp_v2/tools/sync.js +179 -10
- package/mcp_v2/tools/tasks.js +13 -4
- package/package.json +20 -8
package/mcp_v2/lib/helpers.js
CHANGED
|
@@ -38,7 +38,8 @@ function versionOlderThan(a, b) {
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
/**
|
|
41
|
-
* Walk up the directory tree looking for a package.json that depends on Catalyst
|
|
41
|
+
* Walk up the directory tree looking for a package.json that depends on Catalyst,
|
|
42
|
+
* or the catalyst-core package source itself when developing this repo.
|
|
42
43
|
* Returns { dir, pkg, catalystPackageName, catalystVersion, installedVersion, versionMeta } or null.
|
|
43
44
|
*/
|
|
44
45
|
function findCatalystRoot() {
|
|
@@ -54,6 +55,26 @@ function findCatalystRoot() {
|
|
|
54
55
|
if (fs.existsSync(pkgPath)) {
|
|
55
56
|
try {
|
|
56
57
|
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"))
|
|
58
|
+
if (pkg.name === "catalyst-core") {
|
|
59
|
+
const sourceVersion = pkg.version || null
|
|
60
|
+
return {
|
|
61
|
+
dir,
|
|
62
|
+
pkg,
|
|
63
|
+
catalystPackageName: "catalyst-core",
|
|
64
|
+
catalystVersion: sourceVersion,
|
|
65
|
+
version: sourceVersion,
|
|
66
|
+
installedVersion: sourceVersion,
|
|
67
|
+
notInstalled: false,
|
|
68
|
+
isSourcePackage: true,
|
|
69
|
+
versionMeta: {
|
|
70
|
+
declaredRef: sourceVersion,
|
|
71
|
+
isGithubRef: false,
|
|
72
|
+
installedVersion: sourceVersion,
|
|
73
|
+
parsed: parseVersion(sourceVersion),
|
|
74
|
+
},
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
57
78
|
const deps = { ...pkg.dependencies, ...pkg.devDependencies }
|
|
58
79
|
const declaredRef = deps["catalyst-core"]
|
|
59
80
|
if (declaredRef) {
|
|
@@ -77,6 +98,7 @@ function findCatalystRoot() {
|
|
|
77
98
|
pkg,
|
|
78
99
|
catalystPackageName: "catalyst-core",
|
|
79
100
|
catalystVersion: declaredRef, // what package.json says (may be github ref)
|
|
101
|
+
version: declaredRef,
|
|
80
102
|
installedVersion, // what's actually in node_modules e.g. "0.0.3-canary.3"
|
|
81
103
|
notInstalled: !installed,
|
|
82
104
|
versionMeta: {
|
|
@@ -101,21 +123,33 @@ function findCatalystRoot() {
|
|
|
101
123
|
* File-system helpers scoped to a project root.
|
|
102
124
|
*/
|
|
103
125
|
function makeProjectHelpers(root) {
|
|
126
|
+
function safeProjectPath(rel) {
|
|
127
|
+
if (typeof rel !== "string" || path.isAbsolute(rel)) return null
|
|
128
|
+
const normalized = path.normalize(rel)
|
|
129
|
+
if (normalized === ".." || normalized.startsWith(`..${path.sep}`)) return null
|
|
130
|
+
return `${root}${path.sep}${normalized}`
|
|
131
|
+
}
|
|
132
|
+
|
|
104
133
|
function fileExists(rel) {
|
|
105
|
-
|
|
134
|
+
const filePath = safeProjectPath(rel)
|
|
135
|
+
return Boolean(filePath && fs.existsSync(filePath))
|
|
106
136
|
}
|
|
107
137
|
|
|
108
138
|
function readJson(rel) {
|
|
139
|
+
const filePath = safeProjectPath(rel)
|
|
140
|
+
if (!filePath) return null
|
|
109
141
|
try {
|
|
110
|
-
return JSON.parse(fs.readFileSync(
|
|
142
|
+
return JSON.parse(fs.readFileSync(filePath, "utf8"))
|
|
111
143
|
} catch {
|
|
112
144
|
return null
|
|
113
145
|
}
|
|
114
146
|
}
|
|
115
147
|
|
|
116
148
|
function readText(rel) {
|
|
149
|
+
const filePath = safeProjectPath(rel)
|
|
150
|
+
if (!filePath) return null
|
|
117
151
|
try {
|
|
118
|
-
return fs.readFileSync(
|
|
152
|
+
return fs.readFileSync(filePath, "utf8")
|
|
119
153
|
} catch {
|
|
120
154
|
return null
|
|
121
155
|
}
|
|
@@ -125,7 +159,6 @@ function makeProjectHelpers(root) {
|
|
|
125
159
|
* Walk src/**\/*.{js,jsx,ts,tsx} and return relative paths that match pattern.
|
|
126
160
|
*/
|
|
127
161
|
function grepSrc(pattern) {
|
|
128
|
-
const re = new RegExp(pattern)
|
|
129
162
|
const matches = []
|
|
130
163
|
function walk(dir) {
|
|
131
164
|
let entries
|
|
@@ -136,12 +169,13 @@ function makeProjectHelpers(root) {
|
|
|
136
169
|
}
|
|
137
170
|
for (const e of entries) {
|
|
138
171
|
if (e.name === "node_modules" || e.name === ".git") continue
|
|
139
|
-
const full = path.
|
|
172
|
+
const full = `${dir}${path.sep}${e.name}`
|
|
140
173
|
if (e.isDirectory()) {
|
|
141
174
|
walk(full)
|
|
142
175
|
} else if (/\.(js|jsx|ts|tsx)$/.test(e.name)) {
|
|
143
176
|
try {
|
|
144
|
-
|
|
177
|
+
const content = fs.readFileSync(full, "utf8")
|
|
178
|
+
if (pattern.test(content)) {
|
|
145
179
|
matches.push(path.relative(root, full))
|
|
146
180
|
}
|
|
147
181
|
} catch {
|
|
@@ -150,7 +184,7 @@ function makeProjectHelpers(root) {
|
|
|
150
184
|
}
|
|
151
185
|
}
|
|
152
186
|
}
|
|
153
|
-
walk(path.
|
|
187
|
+
walk(`${root}${path.sep}src`)
|
|
154
188
|
return matches
|
|
155
189
|
}
|
|
156
190
|
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use strict"
|
|
2
|
+
|
|
3
|
+
const fs = require("fs")
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Re-seed framework_knowledge (source='static') and known_errors from knowledge-base.json.
|
|
7
|
+
* Caller is responsible for rebuilding fk_fts afterwards (via knowledge.init).
|
|
8
|
+
*
|
|
9
|
+
* @param {import('better-sqlite3').Database} db
|
|
10
|
+
* @param {string} kbPath - absolute path to knowledge-base.json
|
|
11
|
+
* @param {?{ dir: string, pkg: { name?: string }, version: string }} projectInfo
|
|
12
|
+
* When provided, also upserts the project_context row. Pass null at runtime sync
|
|
13
|
+
* when project_context is already populated.
|
|
14
|
+
* @returns {{ knowledgeCount: number, errorCount: number }}
|
|
15
|
+
*/
|
|
16
|
+
function seedKnowledgeBase(db, kbPath, projectInfo = null) {
|
|
17
|
+
const kb = JSON.parse(fs.readFileSync(kbPath, "utf8"))
|
|
18
|
+
if (!Array.isArray(kb)) throw new Error("knowledge-base.json must be a JSON array")
|
|
19
|
+
|
|
20
|
+
const deleteKnowledge = db.prepare(`DELETE FROM framework_knowledge WHERE source = 'static'`)
|
|
21
|
+
const deleteErrors = db.prepare(`DELETE FROM known_errors`)
|
|
22
|
+
|
|
23
|
+
const insertKnowledge = db.prepare(`
|
|
24
|
+
INSERT INTO framework_knowledge (section, title, content, layer, source, tags, github_files)
|
|
25
|
+
VALUES (@section, @title, @content, @layer, @source, @tags, @github_files)
|
|
26
|
+
`)
|
|
27
|
+
|
|
28
|
+
const insertError = db.prepare(`
|
|
29
|
+
INSERT INTO known_errors (symptom, cause, fix, layer, tags)
|
|
30
|
+
VALUES (@symptom, @cause, @fix, @layer, @tags)
|
|
31
|
+
`)
|
|
32
|
+
|
|
33
|
+
let knowledgeCount = 0
|
|
34
|
+
let errorCount = 0
|
|
35
|
+
|
|
36
|
+
const seedAll = db.transaction(() => {
|
|
37
|
+
deleteKnowledge.run()
|
|
38
|
+
deleteErrors.run()
|
|
39
|
+
for (const entry of kb) {
|
|
40
|
+
if (entry.section === "known_errors") {
|
|
41
|
+
// known_errors entries encode symptom/cause/fix in content as:
|
|
42
|
+
// "Symptom: ... Cause: ... Fix: ..."
|
|
43
|
+
const content = entry.content || ""
|
|
44
|
+
const symptomMatch = content.match(/Symptom:\s*([^.]+\.?)/i)
|
|
45
|
+
const causeMatch = content.match(/Cause:\s*([^.]+\.?)/i)
|
|
46
|
+
const fixMatch = content.match(/Fix:\s*([\s\S]+)/i)
|
|
47
|
+
insertError.run({
|
|
48
|
+
symptom: symptomMatch ? symptomMatch[1].trim() : entry.title,
|
|
49
|
+
cause: causeMatch ? causeMatch[1].trim() : "",
|
|
50
|
+
fix: fixMatch ? fixMatch[1].trim() : "",
|
|
51
|
+
layer: entry.layer,
|
|
52
|
+
tags: JSON.stringify(entry.tags || []),
|
|
53
|
+
})
|
|
54
|
+
errorCount++
|
|
55
|
+
} else {
|
|
56
|
+
insertKnowledge.run({
|
|
57
|
+
section: entry.section,
|
|
58
|
+
title: entry.title,
|
|
59
|
+
content: entry.content,
|
|
60
|
+
layer: entry.layer,
|
|
61
|
+
source: "static",
|
|
62
|
+
tags: JSON.stringify(entry.tags || []),
|
|
63
|
+
github_files: entry.github_files ? JSON.stringify(entry.github_files) : null,
|
|
64
|
+
})
|
|
65
|
+
knowledgeCount++
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
seedAll()
|
|
71
|
+
|
|
72
|
+
if (projectInfo) {
|
|
73
|
+
db.prepare(
|
|
74
|
+
`
|
|
75
|
+
INSERT OR REPLACE INTO project_context (id, repo_path, package_name, catalyst_version, detected_at)
|
|
76
|
+
VALUES (1, @repo_path, @package_name, @catalyst_version, datetime('now'))
|
|
77
|
+
`
|
|
78
|
+
).run({
|
|
79
|
+
repo_path: projectInfo.dir,
|
|
80
|
+
package_name: projectInfo.pkg.name || "unknown",
|
|
81
|
+
catalyst_version: projectInfo.version,
|
|
82
|
+
})
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return { knowledgeCount, errorCount }
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
module.exports = { seedKnowledgeBase }
|
package/mcp_v2/mcp.js
CHANGED
|
@@ -25,6 +25,7 @@ const build = require("./tools/build")
|
|
|
25
25
|
const tasks = require("./tools/tasks")
|
|
26
26
|
const sync = require("./tools/sync")
|
|
27
27
|
const knowledge = require("./tools/knowledge")
|
|
28
|
+
const github = require("./tools/github")
|
|
28
29
|
|
|
29
30
|
const MCP_DIR = __dirname
|
|
30
31
|
const DB_PATH = path.join(MCP_DIR, "context.db")
|
|
@@ -87,6 +88,7 @@ build.init(db)
|
|
|
87
88
|
tasks.init(db)
|
|
88
89
|
sync.init(db)
|
|
89
90
|
knowledge.init(db)
|
|
91
|
+
github.init(projectInfo)
|
|
90
92
|
|
|
91
93
|
// ── Intent classification (internal, not exposed as tool) ─────────────────────
|
|
92
94
|
|
|
@@ -97,6 +99,9 @@ const INTENT_PATTERNS = {
|
|
|
97
99
|
guidance:
|
|
98
100
|
/\b(what\s+is|what\s+are|how\s+does|how\s+do|explain|show\s+me|tell\s+me|hook|api|usage|example)\b/i,
|
|
99
101
|
status: /status|done|complet|finish|check.*config|config.*check|what.*(left|remain|todo|next|pending)|how far|progress/i,
|
|
102
|
+
// feedback = wants to raise an issue or discussion on GitHub
|
|
103
|
+
feedback:
|
|
104
|
+
/\b(issue|bug\s+report|report\s+(a\s+)?bug|open\s+(an?\s+)?issue|create\s+(an?\s+)?issue|raise\s+(an?\s+)?issue|discussion|discuss|feature\s+request|proposal|suggest)\b/i,
|
|
100
105
|
debug: /error|fail|broken|not work|crash|issue|bug|why|wrong/i,
|
|
101
106
|
build: /build|compile|webpack|bundle|android|ios|platform/i,
|
|
102
107
|
sync: /sync|update.*doc|fetch.*doc|latest.*doc/i,
|
|
@@ -110,6 +115,8 @@ const INTENT_NEXT_ACTION = {
|
|
|
110
115
|
debug: "answer_only — provide debug guidance. Do NOT call create_task_plan.",
|
|
111
116
|
build: "answer_only — explain build flow. Do NOT call create_task_plan.",
|
|
112
117
|
sync: "answer_only — sync complete. Do NOT call create_task_plan.",
|
|
118
|
+
feedback:
|
|
119
|
+
"answer_only — run the GitHub issue workflow and show the created issue URL or markdown fallback. Do NOT call create_task_plan.",
|
|
113
120
|
unknown: "answer_only — unclear intent. Return what you found. Do NOT call create_task_plan.",
|
|
114
121
|
}
|
|
115
122
|
|
|
@@ -399,9 +406,9 @@ const TOOLS = [
|
|
|
399
406
|
},
|
|
400
407
|
},
|
|
401
408
|
{
|
|
402
|
-
name: "
|
|
409
|
+
name: "sync_knowledge_base",
|
|
403
410
|
description:
|
|
404
|
-
"Use when the developer asks: 'sync docs', 'update framework knowledge', 'fetch latest catalyst docs'. Intent: sync.
|
|
411
|
+
"Use when the developer asks: 'sync docs', 'update framework knowledge', 'fetch latest catalyst docs'. Intent: sync. Pulls the latest knowledge-base.json from tata1mg/catalyst-core@main and re-seeds the KB. Maintenance only — no task planning needed after.",
|
|
405
412
|
inputSchema: {
|
|
406
413
|
type: "object",
|
|
407
414
|
properties: {
|
|
@@ -412,6 +419,144 @@ const TOOLS = [
|
|
|
412
419
|
},
|
|
413
420
|
},
|
|
414
421
|
},
|
|
422
|
+
{
|
|
423
|
+
name: "create_github_issue",
|
|
424
|
+
description:
|
|
425
|
+
"Use when the developer wants to create, raise, report, preview, or publish a GitHub issue for catalyst-core, or after the LLM discovers that a problem is likely caused by catalyst-core framework behavior and the developer agrees to raise an issue. This single tool first asks the developer to select labels when labels are omitted. After labels are supplied, it gathers project context, renders the issue using the selected/suggested template, searches duplicates using duplicate_search_query when provided, supports preview with dry_run:true, publishes only when dry_run:false is explicitly passed, and falls back to a markdown draft on auth/network/API failure. Default to dry_run:true first; if label_selection_required is returned, ask the developer to select labels before collecting/rendering the rest of the issue. Intent: feedback.",
|
|
426
|
+
inputSchema: {
|
|
427
|
+
type: "object",
|
|
428
|
+
properties: {
|
|
429
|
+
dry_run: {
|
|
430
|
+
type: "boolean",
|
|
431
|
+
description:
|
|
432
|
+
"Defaults to true. When true, returns rendered preview, labels, duplicate candidates, and gathered context without publishing. Pass false only after explicit developer approval.",
|
|
433
|
+
},
|
|
434
|
+
project_path: {
|
|
435
|
+
type: "string",
|
|
436
|
+
description: "Path to the catalyst app root. Defaults to detected project root.",
|
|
437
|
+
},
|
|
438
|
+
title: {
|
|
439
|
+
type: "string",
|
|
440
|
+
description:
|
|
441
|
+
"Short, descriptive issue title. E.g. 'RouterDataProvider fails on nested dynamic routes'.",
|
|
442
|
+
},
|
|
443
|
+
body: {
|
|
444
|
+
type: "string",
|
|
445
|
+
description:
|
|
446
|
+
"Full issue description. Plain text is upgraded into the catalyst-core issue style; already structured markdown is preserved.",
|
|
447
|
+
},
|
|
448
|
+
summary: {
|
|
449
|
+
type: "string",
|
|
450
|
+
description: "Structured issue summary if body is not already composed.",
|
|
451
|
+
},
|
|
452
|
+
issue_template: {
|
|
453
|
+
type: "string",
|
|
454
|
+
enum: ["bug", "enhancement", "documentation", "dependencies", "question"],
|
|
455
|
+
description:
|
|
456
|
+
"Optional template to force. Use bug for broken behavior, enhancement for feature requests, documentation for docs/examples, dependencies for package updates, question for clarification.",
|
|
457
|
+
},
|
|
458
|
+
current_behavior: {
|
|
459
|
+
type: "string",
|
|
460
|
+
description: "What happens today.",
|
|
461
|
+
},
|
|
462
|
+
steps_to_reproduce: {
|
|
463
|
+
type: "array",
|
|
464
|
+
items: { type: "string" },
|
|
465
|
+
description: "Steps to reproduce the issue.",
|
|
466
|
+
},
|
|
467
|
+
expected_behavior: {
|
|
468
|
+
type: "string",
|
|
469
|
+
description: "What should happen.",
|
|
470
|
+
},
|
|
471
|
+
actual_behavior: {
|
|
472
|
+
type: "string",
|
|
473
|
+
description: "What actually happens.",
|
|
474
|
+
},
|
|
475
|
+
error_logs: {
|
|
476
|
+
type: "string",
|
|
477
|
+
description: "Error logs or stack traces.",
|
|
478
|
+
},
|
|
479
|
+
preflight_checklist: {
|
|
480
|
+
type: "array",
|
|
481
|
+
items: { type: "string" },
|
|
482
|
+
description:
|
|
483
|
+
"Optional checklist items for bug reports. Defaults to searched issues, single issue, and included repro/environment/logs.",
|
|
484
|
+
},
|
|
485
|
+
what_i_tried: {
|
|
486
|
+
type: "string",
|
|
487
|
+
description: "Troubleshooting already attempted.",
|
|
488
|
+
},
|
|
489
|
+
additional_information: {
|
|
490
|
+
type: "string",
|
|
491
|
+
description: "Additional context that does not fit the primary sections.",
|
|
492
|
+
},
|
|
493
|
+
related_issues: {
|
|
494
|
+
type: "array",
|
|
495
|
+
items: { type: "string" },
|
|
496
|
+
description: "Related GitHub issues or links.",
|
|
497
|
+
},
|
|
498
|
+
root_cause: {
|
|
499
|
+
type: "string",
|
|
500
|
+
description: "Technical notes or suspected root cause.",
|
|
501
|
+
},
|
|
502
|
+
proposed_fix: {
|
|
503
|
+
type: "string",
|
|
504
|
+
description: "Concrete suggested fix.",
|
|
505
|
+
},
|
|
506
|
+
optional_followups: {
|
|
507
|
+
type: "array",
|
|
508
|
+
items: { type: "string" },
|
|
509
|
+
description: "Follow-up cleanup, docs, or test suggestions.",
|
|
510
|
+
},
|
|
511
|
+
environment: {
|
|
512
|
+
type: "object",
|
|
513
|
+
description:
|
|
514
|
+
"Environment details such as platform, OS, browser, device, Node/npm versions.",
|
|
515
|
+
},
|
|
516
|
+
labels: {
|
|
517
|
+
type: "array",
|
|
518
|
+
items: { type: "string" },
|
|
519
|
+
description:
|
|
520
|
+
"Required after the initial label-selection step. Valid catalyst-core labels: bug, dependencies, documentation, duplicate, enhancement, good first issue, help wanted, invalid, question, wontfix. If omitted, the tool returns label_selection_required and does not gather context, render a full preview, search duplicates, or publish.",
|
|
521
|
+
},
|
|
522
|
+
images: {
|
|
523
|
+
type: "array",
|
|
524
|
+
items: { type: "object" },
|
|
525
|
+
description:
|
|
526
|
+
"Optional image URLs or local image paths. URLs are embedded directly; local paths are preserved for fallback/manual upload.",
|
|
527
|
+
},
|
|
528
|
+
duplicate_search_query: {
|
|
529
|
+
type: "string",
|
|
530
|
+
description:
|
|
531
|
+
"Optional focused search query for duplicate detection, supplied by the LLM from the issue context. Use the same query reviewed in the dry_run:true preview.",
|
|
532
|
+
},
|
|
533
|
+
duplicate_review_confirmed: {
|
|
534
|
+
type: "boolean",
|
|
535
|
+
description:
|
|
536
|
+
"Set true only after a dry_run:true preview or blocked publish returned duplicate candidates, those candidates were shown to the developer, and the developer explicitly confirmed this issue is distinct and should still be published.",
|
|
537
|
+
},
|
|
538
|
+
sensitive_data_confirmed: {
|
|
539
|
+
type: "boolean",
|
|
540
|
+
description:
|
|
541
|
+
"Set true only after a dry_run:true preview or blocked publish returned sensitive_data_review.required_before_publish=true, the config/sensitive-looking data warning and rendered issue preview were shown to the developer, and the developer explicitly confirmed this data may be posted to GitHub.",
|
|
542
|
+
},
|
|
543
|
+
duplicate_review_note: {
|
|
544
|
+
type: "string",
|
|
545
|
+
description:
|
|
546
|
+
"Optional short note explaining why the issue is not a duplicate, after the developer confirms publishing.",
|
|
547
|
+
},
|
|
548
|
+
files: {
|
|
549
|
+
type: "array",
|
|
550
|
+
items: { type: "string" },
|
|
551
|
+
description: "Optional explicit project files to include as context snippets.",
|
|
552
|
+
},
|
|
553
|
+
_query: {
|
|
554
|
+
type: "string",
|
|
555
|
+
description: "Original user query for intent classification.",
|
|
556
|
+
},
|
|
557
|
+
},
|
|
558
|
+
},
|
|
559
|
+
},
|
|
415
560
|
]
|
|
416
561
|
|
|
417
562
|
// ── Tool handler dispatch ─────────────────────────────────────────────────────
|
|
@@ -427,8 +572,9 @@ const TOOL_HANDLERS = {
|
|
|
427
572
|
update_task_step: tasks.handle_update_task_step,
|
|
428
573
|
get_active_task: tasks.handle_get_active_task,
|
|
429
574
|
close_task_plan: tasks.handle_close_task_plan,
|
|
430
|
-
|
|
575
|
+
sync_knowledge_base: sync.handle_sync_knowledge_base,
|
|
431
576
|
query_knowledge: knowledge.handle_query_knowledge,
|
|
577
|
+
create_github_issue: github.handle_create_github_issue,
|
|
432
578
|
}
|
|
433
579
|
|
|
434
580
|
// ── MCP JSON-RPC over stdio ───────────────────────────────────────────────────
|
|
@@ -496,7 +642,7 @@ rl.on("line", (line) => {
|
|
|
496
642
|
text: JSON.stringify({
|
|
497
643
|
error: "out_of_scope",
|
|
498
644
|
message:
|
|
499
|
-
"This query is outside Catalyst MCP scope. MCP handles: conversion tracking, debugging, config validation, build flow, architecture, task planning, and
|
|
645
|
+
"This query is outside Catalyst MCP scope. MCP handles: conversion tracking, debugging, config validation, build flow, architecture, task planning, doc sync, and GitHub issue creation.",
|
|
500
646
|
}),
|
|
501
647
|
},
|
|
502
648
|
],
|
package/mcp_v2/setup.js
CHANGED
|
@@ -8,38 +8,22 @@
|
|
|
8
8
|
* 2. Create context.db, run schema.sql
|
|
9
9
|
* 3. Seed framework_knowledge from knowledge-base.json (static rows)
|
|
10
10
|
* 4. Seed known_errors from knowledge-base.json known_errors section
|
|
11
|
-
* 5.
|
|
11
|
+
* 5. Build FTS index over static rows
|
|
12
|
+
* 6. Sync knowledge-base.json from tata1mg/catalyst-core@main (best-effort; warns but does not fail)
|
|
12
13
|
*/
|
|
13
14
|
|
|
14
15
|
const fs = require("fs")
|
|
15
16
|
const path = require("path")
|
|
16
17
|
const Database = require("better-sqlite3")
|
|
17
|
-
const
|
|
18
|
-
const
|
|
18
|
+
const sync = require("./tools/sync")
|
|
19
|
+
const knowledge = require("./tools/knowledge")
|
|
20
|
+
const { seedKnowledgeBase } = require("./lib/seed")
|
|
21
|
+
const { findCatalystRoot } = require("./lib/helpers")
|
|
19
22
|
|
|
20
23
|
const MCP_DIR = __dirname
|
|
21
24
|
const DB_PATH = path.join(MCP_DIR, "context.db")
|
|
22
25
|
const SCHEMA_PATH = path.join(MCP_DIR, "schema.sql")
|
|
23
26
|
const KB_PATH = path.join(MCP_DIR, "knowledge-base.json")
|
|
24
|
-
const SITEMAP_URL = "https://catalyst.1mg.com/public_docs/sitemap.xml"
|
|
25
|
-
|
|
26
|
-
// ── 1. Find & validate catalyst project ──────────────────────────────────────
|
|
27
|
-
|
|
28
|
-
function findCatalystRoot() {
|
|
29
|
-
let dir = process.cwd()
|
|
30
|
-
while (dir !== path.parse(dir).root) {
|
|
31
|
-
const pkgPath = path.join(dir, "package.json")
|
|
32
|
-
if (fs.existsSync(pkgPath)) {
|
|
33
|
-
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"))
|
|
34
|
-
const deps = { ...pkg.dependencies, ...pkg.devDependencies }
|
|
35
|
-
if (deps["catalyst-core"]) {
|
|
36
|
-
return { dir, pkg, catalystPackageName: "catalyst-core", version: deps["catalyst-core"] }
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
dir = path.dirname(dir)
|
|
40
|
-
}
|
|
41
|
-
return null
|
|
42
|
-
}
|
|
43
27
|
|
|
44
28
|
// ── 2. DB init ────────────────────────────────────────────────────────────────
|
|
45
29
|
|
|
@@ -52,180 +36,15 @@ function initDb() {
|
|
|
52
36
|
|
|
53
37
|
// ── 3 & 4. Seed from knowledge-base.json ─────────────────────────────────────
|
|
54
38
|
|
|
55
|
-
function
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
// DELETE existing static rows so re-runs reflect updated knowledge-base.json
|
|
59
|
-
db.prepare(`DELETE FROM framework_knowledge WHERE source = 'static'`).run()
|
|
60
|
-
db.prepare(`DELETE FROM known_errors`).run()
|
|
61
|
-
|
|
62
|
-
const insertKnowledge = db.prepare(`
|
|
63
|
-
INSERT INTO framework_knowledge (section, title, content, layer, source, tags, github_files)
|
|
64
|
-
VALUES (@section, @title, @content, @layer, @source, @tags, @github_files)
|
|
65
|
-
`)
|
|
66
|
-
|
|
67
|
-
const insertError = db.prepare(`
|
|
68
|
-
INSERT INTO known_errors (symptom, cause, fix, layer, tags)
|
|
69
|
-
VALUES (@symptom, @cause, @fix, @layer, @tags)
|
|
70
|
-
`)
|
|
71
|
-
|
|
72
|
-
let knowledgeCount = 0
|
|
73
|
-
let errorCount = 0
|
|
74
|
-
|
|
75
|
-
const seedAll = db.transaction(() => {
|
|
76
|
-
for (const entry of kb) {
|
|
77
|
-
if (entry.section === "known_errors") {
|
|
78
|
-
// known_errors entries encode symptom/cause/fix in content as:
|
|
79
|
-
// "Symptom: ... Cause: ... Fix: ..."
|
|
80
|
-
const content = entry.content || ""
|
|
81
|
-
const symptomMatch = content.match(/Symptom:\s*([^.]+\.?)/i)
|
|
82
|
-
const causeMatch = content.match(/Cause:\s*([^.]+\.?)/i)
|
|
83
|
-
const fixMatch = content.match(/Fix:\s*([\s\S]+)/i)
|
|
84
|
-
insertError.run({
|
|
85
|
-
symptom: symptomMatch ? symptomMatch[1].trim() : entry.title,
|
|
86
|
-
cause: causeMatch ? causeMatch[1].trim() : "",
|
|
87
|
-
fix: fixMatch ? fixMatch[1].trim() : "",
|
|
88
|
-
layer: entry.layer,
|
|
89
|
-
tags: JSON.stringify(entry.tags || []),
|
|
90
|
-
})
|
|
91
|
-
errorCount++
|
|
92
|
-
} else {
|
|
93
|
-
insertKnowledge.run({
|
|
94
|
-
section: entry.section,
|
|
95
|
-
title: entry.title,
|
|
96
|
-
content: entry.content,
|
|
97
|
-
layer: entry.layer,
|
|
98
|
-
source: "static",
|
|
99
|
-
tags: JSON.stringify(entry.tags || []),
|
|
100
|
-
github_files: entry.github_files ? JSON.stringify(entry.github_files) : null,
|
|
101
|
-
})
|
|
102
|
-
knowledgeCount++
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
})
|
|
106
|
-
|
|
107
|
-
seedAll()
|
|
39
|
+
function seedFromLocalKb(db, projectInfo) {
|
|
40
|
+
const { knowledgeCount, errorCount } = seedKnowledgeBase(db, KB_PATH, projectInfo)
|
|
108
41
|
console.log(` ✓ Seeded ${knowledgeCount} knowledge entries`)
|
|
109
42
|
console.log(` ✓ Seeded ${errorCount} known_errors entries`)
|
|
110
|
-
|
|
111
|
-
// Store project context
|
|
112
|
-
db.prepare(
|
|
113
|
-
`
|
|
114
|
-
INSERT OR REPLACE INTO project_context (id, repo_path, package_name, catalyst_version, detected_at)
|
|
115
|
-
VALUES (1, @repo_path, @package_name, @catalyst_version, datetime('now'))
|
|
116
|
-
`
|
|
117
|
-
).run({
|
|
118
|
-
repo_path: projectInfo.dir,
|
|
119
|
-
package_name: projectInfo.pkg.name || "unknown",
|
|
120
|
-
catalyst_version: projectInfo.version,
|
|
121
|
-
})
|
|
122
43
|
console.log(
|
|
123
44
|
` ✓ Project context stored (${projectInfo.pkg.name}, ${projectInfo.catalystPackageName}@${projectInfo.version})`
|
|
124
45
|
)
|
|
125
46
|
}
|
|
126
47
|
|
|
127
|
-
// ── 5. sync_catalyst_docs (initial run) ───────────────────────────────────────
|
|
128
|
-
|
|
129
|
-
function fetchUrl(url) {
|
|
130
|
-
return new Promise((resolve, reject) => {
|
|
131
|
-
const mod = url.startsWith("https") ? https : require("http")
|
|
132
|
-
mod.get(url, (res) => {
|
|
133
|
-
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
|
134
|
-
return fetchUrl(res.headers.location).then(resolve).catch(reject)
|
|
135
|
-
}
|
|
136
|
-
let data = ""
|
|
137
|
-
res.on("data", (chunk) => (data += chunk))
|
|
138
|
-
res.on("end", () => resolve(data))
|
|
139
|
-
}).on("error", reject)
|
|
140
|
-
})
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
function parseSitemapUrls(xml) {
|
|
144
|
-
const matches = xml.match(/<loc>(.*?)<\/loc>/g) || []
|
|
145
|
-
return matches.map((m) => m.replace(/<\/?loc>/g, "").trim())
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
function stripHtml(html) {
|
|
149
|
-
// Very simple strip — good enough for catalyst docs
|
|
150
|
-
return html
|
|
151
|
-
.replace(/<script[\s\S]*?<\/script>/gi, "")
|
|
152
|
-
.replace(/<style[\s\S]*?<\/style>/gi, "")
|
|
153
|
-
.replace(/<[^>]+>/g, " ")
|
|
154
|
-
.replace(/\s+/g, " ")
|
|
155
|
-
.trim()
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
function contentHash(text) {
|
|
159
|
-
return crypto.createHash("sha256").update(text).digest("hex").slice(0, 16)
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
// Kept for manual/live sync flows; setup does not invoke it by default.
|
|
163
|
-
// eslint-disable-next-line no-unused-vars
|
|
164
|
-
async function syncCatalystDocs(db) {
|
|
165
|
-
console.log("\n Fetching sitemap...")
|
|
166
|
-
let xml
|
|
167
|
-
try {
|
|
168
|
-
xml = await fetchUrl(SITEMAP_URL)
|
|
169
|
-
} catch (e) {
|
|
170
|
-
console.warn(` ⚠ Could not fetch sitemap (${e.message}). Skipping live docs sync.`)
|
|
171
|
-
console.warn(" You can run sync later via the sync_catalyst_docs MCP tool.")
|
|
172
|
-
return
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
const urls = parseSitemapUrls(xml)
|
|
176
|
-
console.log(` Found ${urls.length} URLs in sitemap`)
|
|
177
|
-
|
|
178
|
-
const insertKnowledge = db.prepare(`
|
|
179
|
-
INSERT INTO framework_knowledge (section, title, content, layer, source, tags, url)
|
|
180
|
-
VALUES (@section, @title, @content, @layer, 'sitemap', '[]', @url)
|
|
181
|
-
`)
|
|
182
|
-
|
|
183
|
-
const insertSnapshot = db.prepare(`
|
|
184
|
-
INSERT INTO doc_snapshots (url, content_hash, slot) VALUES (@url, @hash, 'curr')
|
|
185
|
-
`)
|
|
186
|
-
|
|
187
|
-
const insertLink = db.prepare(`
|
|
188
|
-
INSERT INTO linkage_map (url, knowledge_id) VALUES (@url, @knowledge_id)
|
|
189
|
-
`)
|
|
190
|
-
|
|
191
|
-
let synced = 0
|
|
192
|
-
let failed = 0
|
|
193
|
-
|
|
194
|
-
for (const url of urls) {
|
|
195
|
-
try {
|
|
196
|
-
const html = await fetchUrl(url)
|
|
197
|
-
const text = stripHtml(html)
|
|
198
|
-
const hash = contentHash(text)
|
|
199
|
-
|
|
200
|
-
// Extract a title from <title> tag if present
|
|
201
|
-
const titleMatch = html.match(/<title[^>]*>(.*?)<\/title>/i)
|
|
202
|
-
const title = titleMatch ? titleMatch[1].trim() : url.split("/").pop() || url
|
|
203
|
-
|
|
204
|
-
// Truncate content to 2000 chars to keep DB lean
|
|
205
|
-
const content = text.slice(0, 2000)
|
|
206
|
-
|
|
207
|
-
db.transaction(() => {
|
|
208
|
-
const row = insertKnowledge.run({
|
|
209
|
-
section: "sitemap",
|
|
210
|
-
title,
|
|
211
|
-
content,
|
|
212
|
-
layer: "Component",
|
|
213
|
-
url,
|
|
214
|
-
})
|
|
215
|
-
insertSnapshot.run({ url, hash })
|
|
216
|
-
insertLink.run({ url, knowledge_id: row.lastInsertRowid })
|
|
217
|
-
})()
|
|
218
|
-
|
|
219
|
-
synced++
|
|
220
|
-
process.stdout.write(`\r Synced ${synced}/${urls.length} pages...`)
|
|
221
|
-
} catch (e) {
|
|
222
|
-
failed++
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
console.log(`\n ✓ Synced ${synced} pages (${failed} failed)`)
|
|
227
|
-
}
|
|
228
|
-
|
|
229
48
|
// ── Main ──────────────────────────────────────────────────────────────────────
|
|
230
49
|
|
|
231
50
|
async function main() {
|
|
@@ -248,11 +67,29 @@ async function main() {
|
|
|
248
67
|
|
|
249
68
|
// 3 & 4. Seed static knowledge
|
|
250
69
|
console.log("\nSeeding knowledge-base.json...")
|
|
251
|
-
|
|
70
|
+
seedFromLocalKb(db, projectInfo)
|
|
252
71
|
|
|
253
|
-
// 5.
|
|
254
|
-
//
|
|
255
|
-
|
|
72
|
+
// 5. Build FTS index from the just-seeded static rows.
|
|
73
|
+
// DROP first so re-runs of setup don't leave orphan rowids pointing at deleted rows.
|
|
74
|
+
db.exec(`DROP TABLE IF EXISTS fk_fts`)
|
|
75
|
+
knowledge.init(db)
|
|
76
|
+
|
|
77
|
+
// 6. Initial sync — pulls knowledge-base.json from tata1mg/catalyst-core@main.
|
|
78
|
+
// Failures are warnings, not setup-blockers (network may be unavailable at install time).
|
|
79
|
+
console.log("\nSyncing knowledge-base.json from tata1mg/catalyst-core@main...")
|
|
80
|
+
sync.init(db)
|
|
81
|
+
try {
|
|
82
|
+
const result = await sync.handle_sync_knowledge_base({})
|
|
83
|
+
if (result.error) {
|
|
84
|
+
console.warn(` ⚠ ${result.error}`)
|
|
85
|
+
console.warn(" Run sync_knowledge_base later via your MCP client to retry.")
|
|
86
|
+
} else {
|
|
87
|
+
console.log(` ✓ ${result.message}`)
|
|
88
|
+
}
|
|
89
|
+
} catch (e) {
|
|
90
|
+
console.warn(` ⚠ Sync threw: ${e.message}`)
|
|
91
|
+
console.warn(" Run sync_knowledge_base later via your MCP client to retry.")
|
|
92
|
+
}
|
|
256
93
|
|
|
257
94
|
db.close()
|
|
258
95
|
console.log("\n✓ Setup complete. MCP is ready.\n")
|