@decohere/scaffold 0.0.1-dev.18 → 0.0.1-dev.81
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/commonjs/src/add-api.action.js +39 -0
- package/commonjs/src/add-api.command.js +41 -0
- package/commonjs/src/add.command.js +24 -0
- package/commonjs/src/add.module.js +26 -0
- package/commonjs/src/cli.js +9 -0
- package/commonjs/src/create.command.js +24 -0
- package/commonjs/src/create.module.js +26 -0
- package/commonjs/src/domain/prompt.js +64 -0
- package/commonjs/src/index.js +38 -0
- package/commonjs/src/models/compose.model.js +150 -0
- package/commonjs/src/models/config-yaml.model.js +88 -0
- package/commonjs/src/models/const.js +32 -0
- package/commonjs/src/models/dev-container.model.js +116 -0
- package/commonjs/src/models/docker-image.model.js +259 -0
- package/commonjs/src/models/env-file.model.js +50 -0
- package/commonjs/src/models/gitignore.model.js +43 -0
- package/commonjs/src/models/launch-json.model.js +74 -0
- package/commonjs/src/models/package-json.model.js +149 -0
- package/commonjs/src/models/project.model.js +134 -0
- package/commonjs/src/models/source-file.js +6 -0
- package/commonjs/src/models/tsconfig.model.js +34 -0
- package/commonjs/src/models/vitest-config.model.js +35 -0
- package/commonjs/src/models/vscode-settings.model.js +31 -0
- package/commonjs/src/program.js +57 -0
- package/commonjs/src/resolve-target-dir.js +19 -0
- package/commonjs/src/services/scaffold.service.js +62 -0
- package/commonjs/src/version.js +57 -0
- package/commonjs/src/webapi/api-name.js +95 -0
- package/commonjs/src/webapi/cli-options.js +101 -0
- package/commonjs/src/webapi/const.js +50 -0
- package/commonjs/src/webapi/create-api.js +237 -0
- package/commonjs/src/webapi/devcontainer/codebase-rag-mcp.js +166 -0
- package/commonjs/src/webapi/devcontainer/codebase-rag-mcp.ts +182 -0
- package/commonjs/src/webapi/devcontainer/host-scripts.js +52 -0
- package/commonjs/src/webapi/devcontainer/templates/codebase-rag.env.example +3 -0
- package/commonjs/src/webapi/devcontainer/templates/initialize.sh +169 -0
- package/commonjs/src/webapi/devcontainer/templates/post-create.sh +35 -0
- package/commonjs/src/webapi/devcontainer/templates/post-start.sh +65 -0
- package/commonjs/src/webapi/devcontainer/templates/tty-prompt.sh +38 -0
- package/commonjs/src/webapi/features/auth.feature.js +441 -0
- package/commonjs/src/webapi/features/auth0-cli.js +435 -0
- package/commonjs/src/webapi/features/biome-format.js +49 -0
- package/commonjs/src/webapi/features/database.feature.js +433 -0
- package/commonjs/src/webapi/features/finalize.feature.js +95 -0
- package/commonjs/src/webapi/features/postman.feature.js +324 -0
- package/commonjs/src/webapi/models/api-package-json.model.js +60 -0
- package/commonjs/src/webapi/models/auth-config.model.js +26 -0
- package/commonjs/src/webapi/models/controller-source-file.model.js +193 -0
- package/commonjs/src/webapi/models/github-ci.model.js +193 -0
- package/commonjs/src/webapi/models/main-source-file.model.js +167 -0
- package/commonjs/src/webapi/models/production-dockerfile.model.js +157 -0
- package/commonjs/src/webapi/models/sample-files.model.js +60 -0
- package/commonjs/src/webapi/models/webapi-image.model.js +27 -0
- package/commonjs/src/webapi/postman/hello-openapi.js +175 -0
- package/commonjs/src/webapi/postman/local-view.js +184 -0
- package/commonjs/src/webapi/postman/openapi-to-postman.js +202 -0
- package/commonjs/src/webapi/workspace-readme.js +110 -0
- package/commonjs/src/webapi.action.js +30 -0
- package/commonjs/src/webapi.command.js +45 -0
- package/es6/src/add-api.action.js +29 -0
- package/es6/src/add-api.command.js +31 -0
- package/es6/src/add.command.js +14 -0
- package/es6/src/add.module.js +16 -0
- package/es6/src/cli.js +5 -0
- package/es6/src/create.command.js +14 -0
- package/es6/src/create.module.js +16 -0
- package/es6/src/domain/prompt.js +43 -0
- package/es6/src/index.js +8 -0
- package/es6/src/models/compose.model.js +144 -0
- package/es6/src/models/config-yaml.model.js +76 -0
- package/es6/src/models/const.js +22 -0
- package/es6/src/models/dev-container.model.js +106 -0
- package/es6/src/models/docker-image.model.js +217 -0
- package/es6/src/models/env-file.model.js +46 -0
- package/es6/src/models/gitignore.model.js +33 -0
- package/es6/src/models/launch-json.model.js +64 -0
- package/es6/src/models/package-json.model.js +137 -0
- package/es6/src/models/project.model.js +119 -0
- package/es6/src/models/source-file.js +3 -0
- package/es6/src/models/tsconfig.model.js +24 -0
- package/es6/src/models/vitest-config.model.js +25 -0
- package/es6/src/models/vscode-settings.model.js +21 -0
- package/es6/src/program.js +39 -0
- package/es6/src/resolve-target-dir.js +9 -0
- package/es6/src/services/scaffold.service.js +52 -0
- package/es6/src/version.js +36 -0
- package/es6/src/webapi/api-name.js +59 -0
- package/es6/src/webapi/cli-options.js +36 -0
- package/es6/src/webapi/const.js +20 -0
- package/es6/src/webapi/create-api.js +217 -0
- package/es6/src/webapi/devcontainer/codebase-rag-mcp.js +156 -0
- package/es6/src/webapi/devcontainer/codebase-rag-mcp.ts +182 -0
- package/es6/src/webapi/devcontainer/host-scripts.js +31 -0
- package/es6/src/webapi/devcontainer/templates/codebase-rag.env.example +3 -0
- package/es6/src/webapi/devcontainer/templates/initialize.sh +169 -0
- package/es6/src/webapi/devcontainer/templates/post-create.sh +35 -0
- package/es6/src/webapi/devcontainer/templates/post-start.sh +65 -0
- package/es6/src/webapi/devcontainer/templates/tty-prompt.sh +38 -0
- package/es6/src/webapi/features/auth.feature.js +390 -0
- package/es6/src/webapi/features/auth0-cli.js +375 -0
- package/es6/src/webapi/features/biome-format.js +42 -0
- package/es6/src/webapi/features/database.feature.js +423 -0
- package/es6/src/webapi/features/finalize.feature.js +85 -0
- package/es6/src/webapi/features/postman.feature.js +258 -0
- package/es6/src/webapi/models/api-package-json.model.js +55 -0
- package/es6/src/webapi/models/auth-config.model.js +22 -0
- package/es6/src/webapi/models/controller-source-file.model.js +184 -0
- package/es6/src/webapi/models/github-ci.model.js +186 -0
- package/es6/src/webapi/models/main-source-file.model.js +163 -0
- package/es6/src/webapi/models/production-dockerfile.model.js +148 -0
- package/es6/src/webapi/models/sample-files.model.js +42 -0
- package/es6/src/webapi/models/webapi-image.model.js +20 -0
- package/es6/src/webapi/postman/hello-openapi.js +168 -0
- package/es6/src/webapi/postman/local-view.js +169 -0
- package/es6/src/webapi/postman/openapi-to-postman.js +179 -0
- package/es6/src/webapi/workspace-readme.js +89 -0
- package/es6/src/webapi.action.js +20 -0
- package/es6/src/webapi.command.js +35 -0
- package/package.json +8 -8
- package/types/src/add-api.action.d.ts +13 -0
- package/types/src/add-api.command.d.ts +7 -0
- package/types/src/add.command.d.ts +6 -0
- package/types/src/add.module.d.ts +14 -0
- package/types/src/cli.d.ts +2 -0
- package/types/src/create.command.d.ts +6 -0
- package/types/src/create.module.d.ts +14 -0
- package/types/src/domain/prompt.d.ts +4 -0
- package/types/src/models/compose.model.d.ts +64 -0
- package/types/src/models/config-yaml.model.d.ts +27 -0
- package/types/src/models/const.d.ts +20 -0
- package/types/src/models/dev-container.model.d.ts +37 -0
- package/types/src/models/docker-image.model.d.ts +84 -0
- package/types/src/models/env-file.model.d.ts +16 -0
- package/types/src/models/gitignore.model.d.ts +7 -0
- package/types/src/models/launch-json.model.d.ts +7 -0
- package/types/src/models/package-json.model.d.ts +35 -0
- package/types/src/models/project.model.d.ts +60 -0
- package/{src/models/source-file.ts → types/src/models/source-file.d.ts} +4 -6
- package/types/src/models/tsconfig.model.d.ts +5 -0
- package/types/src/models/vitest-config.model.d.ts +5 -0
- package/types/src/models/vscode-settings.model.d.ts +7 -0
- package/types/src/program.d.ts +3 -0
- package/{src/resolve-target-dir.ts → types/src/resolve-target-dir.d.ts} +1 -4
- package/types/src/services/scaffold.service.d.ts +22 -0
- package/types/src/version.d.ts +6 -0
- package/types/src/webapi/api-name.d.ts +14 -0
- package/types/src/webapi/cli-options.d.ts +6 -0
- package/{src/webapi/const.ts → types/src/webapi/const.d.ts} +7 -21
- package/types/src/webapi/create-api.d.ts +15 -0
- package/types/src/webapi/devcontainer/codebase-rag-mcp.d.ts +32 -0
- package/types/src/webapi/devcontainer/codebase-rag-mcp.ts +182 -0
- package/types/src/webapi/devcontainer/host-scripts.d.ts +7 -0
- package/types/src/webapi/devcontainer/templates/codebase-rag.env.example +3 -0
- package/types/src/webapi/devcontainer/templates/initialize.sh +169 -0
- package/types/src/webapi/devcontainer/templates/post-create.sh +35 -0
- package/types/src/webapi/devcontainer/templates/post-start.sh +65 -0
- package/types/src/webapi/devcontainer/templates/tty-prompt.sh +38 -0
- package/types/src/webapi/features/auth.feature.d.ts +10 -0
- package/types/src/webapi/features/auth0-cli.d.ts +80 -0
- package/types/src/webapi/features/biome-format.d.ts +5 -0
- package/types/src/webapi/features/database.feature.d.ts +7 -0
- package/types/src/webapi/features/finalize.feature.d.ts +2 -0
- package/types/src/webapi/features/postman.feature.d.ts +16 -0
- package/types/src/webapi/models/api-package-json.model.d.ts +18 -0
- package/types/src/webapi/models/auth-config.model.d.ts +26 -0
- package/types/src/webapi/models/controller-source-file.model.d.ts +46 -0
- package/types/src/webapi/models/github-ci.model.d.ts +9 -0
- package/types/src/webapi/models/main-source-file.model.d.ts +54 -0
- package/types/src/webapi/models/production-dockerfile.model.d.ts +23 -0
- package/types/src/webapi/models/sample-files.model.d.ts +7 -0
- package/types/src/webapi/models/webapi-image.model.d.ts +12 -0
- package/types/src/webapi/postman/hello-openapi.d.ts +19 -0
- package/types/src/webapi/postman/local-view.d.ts +17 -0
- package/types/src/webapi/postman/openapi-to-postman.d.ts +62 -0
- package/types/src/webapi/workspace-readme.d.ts +18 -0
- package/types/src/webapi.action.d.ts +14 -0
- package/types/src/webapi.command.d.ts +11 -0
- package/src/add-api.action.ts +0 -25
- package/src/add-api.command.ts +0 -31
- package/src/add.command.ts +0 -20
- package/src/add.module.ts +0 -11
- package/src/cli.ts +0 -4
- package/src/create.command.ts +0 -20
- package/src/create.module.ts +0 -11
- package/src/domain/prompt.ts +0 -50
- package/src/models/compose.model.ts +0 -205
- package/src/models/config-yaml.model.ts +0 -83
- package/src/models/const.ts +0 -20
- package/src/models/dev-container.model.ts +0 -136
- package/src/models/docker-image.model.ts +0 -343
- package/src/models/env-file.model.ts +0 -45
- package/src/models/gitignore.model.ts +0 -35
- package/src/models/launch-json.model.ts +0 -60
- package/src/models/package-json.model.ts +0 -169
- package/src/models/project.model.ts +0 -141
- package/src/models/tsconfig.model.ts +0 -29
- package/src/models/vitest-config.model.ts +0 -26
- package/src/models/vscode-settings.model.ts +0 -24
- package/src/program.ts +0 -63
- package/src/services/scaffold.service.ts +0 -89
- package/src/version.ts +0 -56
- package/src/webapi/api-name.ts +0 -73
- package/src/webapi/cli-options.ts +0 -56
- package/src/webapi/create-api.ts +0 -275
- package/src/webapi/devcontainer/host-scripts.ts +0 -35
- package/src/webapi/features/auth.feature.ts +0 -454
- package/src/webapi/features/auth0-cli.ts +0 -421
- package/src/webapi/features/biome-format.ts +0 -34
- package/src/webapi/features/database.feature.ts +0 -522
- package/src/webapi/features/finalize.feature.ts +0 -112
- package/src/webapi/features/postman.feature.ts +0 -287
- package/src/webapi/models/api-package-json.model.ts +0 -60
- package/src/webapi/models/auth-config.model.ts +0 -36
- package/src/webapi/models/controller-source-file.model.ts +0 -232
- package/src/webapi/models/github-ci.model.ts +0 -188
- package/src/webapi/models/main-source-file.model.ts +0 -208
- package/src/webapi/models/production-dockerfile.model.ts +0 -162
- package/src/webapi/models/sample-files.model.ts +0 -45
- package/src/webapi/models/webapi-image.model.ts +0 -21
- package/src/webapi/postman/hello-openapi.ts +0 -92
- package/src/webapi/postman/local-view.ts +0 -195
- package/src/webapi/postman/openapi-to-postman.ts +0 -208
- package/src/webapi/workspace-readme.ts +0 -192
- package/src/webapi.action.ts +0 -22
- package/src/webapi.command.ts +0 -41
- package/tests/auth-postman.wiring.spec.ts +0 -263
- package/tests/auth0-cli.spec.ts +0 -232
- package/tests/biome-format.spec.ts +0 -49
- package/tests/cli.integration.spec.ts +0 -658
- package/tests/compose.model.spec.ts +0 -51
- package/tests/container-image.model.spec.ts +0 -162
- package/tests/dev-container.model.spec.ts +0 -29
- package/tests/devcontainer-base-image.spec.ts +0 -32
- package/tests/hello-di-inject.scaffold.spec.ts +0 -18
- package/tests/hello-route.contract.spec.ts +0 -94
- package/tests/package-json.order.spec.ts +0 -59
- package/tests/postman-from-openapi.spec.ts +0 -197
- package/tests/seed-devcontainer-templates.ts +0 -40
- package/tests/webapi/devcontainer/codebase-rag-mcp.spec.ts +0 -96
- /package/{src/index.ts → types/src/index.d.ts} +0 -0
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "codebaseRagMcp", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: function() {
|
|
8
|
+
return codebaseRagMcp;
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
const _nodefs = require("node:fs");
|
|
12
|
+
const _nodepath = require("node:path");
|
|
13
|
+
const _nodeurl = require("node:url");
|
|
14
|
+
function isRecord(value) {
|
|
15
|
+
return value != null && typeof value === "object" && !Array.isArray(value);
|
|
16
|
+
}
|
|
17
|
+
function loadDotenv(path, env) {
|
|
18
|
+
let raw;
|
|
19
|
+
try {
|
|
20
|
+
raw = (0, _nodefs.readFileSync)(path, "utf8");
|
|
21
|
+
} catch {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
for (const line of raw.split(/\r?\n/)){
|
|
25
|
+
const trimmed = line.trim();
|
|
26
|
+
if (!trimmed || trimmed.startsWith("#") || !trimmed.includes("=")) continue;
|
|
27
|
+
const eq = trimmed.indexOf("=");
|
|
28
|
+
const key = trimmed.slice(0, eq).trim();
|
|
29
|
+
const value = trimmed.slice(eq + 1).trim().replace(/^["']|["']$/g, "");
|
|
30
|
+
if (key && env[key] === undefined) env[key] = value;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function seedFromMcpJson(raw) {
|
|
34
|
+
let data;
|
|
35
|
+
try {
|
|
36
|
+
data = JSON.parse(raw);
|
|
37
|
+
} catch {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
if (!isRecord(data)) return null;
|
|
41
|
+
const servers = data.mcpServers;
|
|
42
|
+
if (!isRecord(servers)) return null;
|
|
43
|
+
const server = servers["codebase-rag"];
|
|
44
|
+
if (!isRecord(server)) return null;
|
|
45
|
+
const url = typeof server.url === "string" ? server.url.trim() : "";
|
|
46
|
+
const headers = isRecord(server.headers) ? server.headers : {};
|
|
47
|
+
const auth = typeof headers.Authorization === "string" ? headers.Authorization.trim() : "";
|
|
48
|
+
const token = auth.toLowerCase().startsWith("bearer ") ? auth.slice(7).trim() : "";
|
|
49
|
+
if (!url.startsWith("http") || token.length === 0) return null;
|
|
50
|
+
return {
|
|
51
|
+
url,
|
|
52
|
+
token
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
function mergeIntoMcpJson(input) {
|
|
56
|
+
const { mcpPath, url, token, hostRoot } = input;
|
|
57
|
+
if (!url || !token) {
|
|
58
|
+
return {
|
|
59
|
+
skipped: "no URL/token"
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
const xRoot = hostRoot || "${workspaceFolder}";
|
|
63
|
+
(0, _nodefs.mkdirSync)((0, _nodepath.dirname)(mcpPath), {
|
|
64
|
+
recursive: true
|
|
65
|
+
});
|
|
66
|
+
let data = {
|
|
67
|
+
mcpServers: {}
|
|
68
|
+
};
|
|
69
|
+
try {
|
|
70
|
+
if ((0, _nodefs.statSync)(mcpPath).size > 0) {
|
|
71
|
+
const loaded = JSON.parse((0, _nodefs.readFileSync)(mcpPath, "utf8"));
|
|
72
|
+
if (isRecord(loaded)) data = loaded;
|
|
73
|
+
}
|
|
74
|
+
} catch (err) {
|
|
75
|
+
const code = isRecord(err) && typeof err.code === "string" ? err.code : "";
|
|
76
|
+
if (code !== "ENOENT") {
|
|
77
|
+
console.log("codebase-rag MCP: existing mcp.json is invalid JSON; replacing rag entry only after backup");
|
|
78
|
+
(0, _nodefs.renameSync)(mcpPath, `${mcpPath}.bak`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
const servers = isRecord(data.mcpServers) ? data.mcpServers : {};
|
|
82
|
+
data.mcpServers = servers;
|
|
83
|
+
servers["codebase-rag"] = {
|
|
84
|
+
url,
|
|
85
|
+
headers: {
|
|
86
|
+
Authorization: `Bearer ${token}`,
|
|
87
|
+
"X-Codebase-Root": xRoot
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
(0, _nodefs.writeFileSync)(mcpPath, `${JSON.stringify(data, null, 2)}\n`, "utf8");
|
|
91
|
+
try {
|
|
92
|
+
(0, _nodefs.chmodSync)(mcpPath, 0o600);
|
|
93
|
+
} catch {
|
|
94
|
+
// memfs and some hosts omit chmod
|
|
95
|
+
}
|
|
96
|
+
return {
|
|
97
|
+
path: mcpPath,
|
|
98
|
+
root: xRoot
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
function workspaceRoot(env = process.env) {
|
|
102
|
+
const fromEnv = env.CODEBASE_RAG_WORKSPACE?.trim();
|
|
103
|
+
if (fromEnv) return fromEnv;
|
|
104
|
+
// Scaffolded copy lives at <repo>/.devcontainer/codebase-rag-mcp.ts
|
|
105
|
+
return (0, _nodepath.dirname)((0, _nodepath.dirname)((0, _nodeurl.fileURLToPath)(require("url").pathToFileURL(__filename).toString())));
|
|
106
|
+
}
|
|
107
|
+
function mergeFromEnv(env = process.env) {
|
|
108
|
+
const root = workspaceRoot(env);
|
|
109
|
+
const cursorDir = (0, _nodepath.join)(root, ".cursor");
|
|
110
|
+
loadDotenv((0, _nodepath.join)(cursorDir, "codebase-rag.env"), env);
|
|
111
|
+
const url = (env.CODEBASE_RAG_MCP_URL ?? "").trim();
|
|
112
|
+
const token = (env.CODEBASE_RAG_MCP_TOKEN ?? "").trim();
|
|
113
|
+
const hostRoot = (env.CODEBASE_RAG_MCP_ROOT ?? "").trim() || root;
|
|
114
|
+
const result = mergeIntoMcpJson({
|
|
115
|
+
mcpPath: (0, _nodepath.join)(cursorDir, "mcp.json"),
|
|
116
|
+
url,
|
|
117
|
+
token,
|
|
118
|
+
hostRoot
|
|
119
|
+
});
|
|
120
|
+
if (result.skipped != null) {
|
|
121
|
+
console.log(`codebase-rag MCP: skipped (${result.skipped})`);
|
|
122
|
+
return 0;
|
|
123
|
+
}
|
|
124
|
+
console.log(`codebase-rag MCP: wrote ${result.path} url=${url} root=${result.root}`);
|
|
125
|
+
return 0;
|
|
126
|
+
}
|
|
127
|
+
function seedPrint(mcpPath) {
|
|
128
|
+
let raw;
|
|
129
|
+
try {
|
|
130
|
+
raw = (0, _nodefs.readFileSync)(mcpPath, "utf8");
|
|
131
|
+
} catch {
|
|
132
|
+
return 1;
|
|
133
|
+
}
|
|
134
|
+
const creds = seedFromMcpJson(raw);
|
|
135
|
+
if (creds == null) return 1;
|
|
136
|
+
console.log(creds.url);
|
|
137
|
+
console.log(creds.token);
|
|
138
|
+
return 0;
|
|
139
|
+
}
|
|
140
|
+
function main(argv = process.argv.slice(2)) {
|
|
141
|
+
const command = argv[0] ?? "merge";
|
|
142
|
+
if (command === "seed-print") {
|
|
143
|
+
const mcpPath = argv[1];
|
|
144
|
+
if (mcpPath == null || mcpPath.length === 0) return 1;
|
|
145
|
+
return seedPrint(mcpPath);
|
|
146
|
+
}
|
|
147
|
+
if (command === "merge") {
|
|
148
|
+
return mergeFromEnv();
|
|
149
|
+
}
|
|
150
|
+
console.error(`codebase-rag MCP: unknown command ${command}`);
|
|
151
|
+
return 1;
|
|
152
|
+
}
|
|
153
|
+
const invoked = (process.argv[1] ?? "").replaceAll("\\", "/");
|
|
154
|
+
if (invoked.endsWith("/codebase-rag-mcp.ts") || invoked.endsWith("/codebase-rag-mcp.js")) {
|
|
155
|
+
process.exit(main());
|
|
156
|
+
}
|
|
157
|
+
const codebaseRagMcp = {
|
|
158
|
+
loadDotenv,
|
|
159
|
+
seedFromMcpJson,
|
|
160
|
+
mergeIntoMcpJson,
|
|
161
|
+
mergeFromEnv,
|
|
162
|
+
seedPrint,
|
|
163
|
+
main
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL3NjYWZmb2xkL3NyYy93ZWJhcGkvZGV2Y29udGFpbmVyL2NvZGViYXNlLXJhZy1tY3AudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcblx0Y2htb2RTeW5jLFxuXHRta2RpclN5bmMsXG5cdHJlYWRGaWxlU3luYyxcblx0cmVuYW1lU3luYyxcblx0c3RhdFN5bmMsXG5cdHdyaXRlRmlsZVN5bmMsXG59IGZyb20gXCJub2RlOmZzXCI7XG5pbXBvcnQgeyBkaXJuYW1lLCBqb2luIH0gZnJvbSBcIm5vZGU6cGF0aFwiO1xuaW1wb3J0IHsgZmlsZVVSTFRvUGF0aCB9IGZyb20gXCJub2RlOnVybFwiO1xuXG5leHBvcnQgdHlwZSBDb2RlYmFzZVJhZ0NyZWRlbnRpYWxzID0ge1xuXHR1cmw6IHN0cmluZztcblx0dG9rZW46IHN0cmluZztcbn07XG5cbmV4cG9ydCB0eXBlIE1jcEpzb24gPSB7XG5cdG1jcFNlcnZlcnM/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcblx0W2tleTogc3RyaW5nXTogdW5rbm93bjtcbn07XG5cbmZ1bmN0aW9uIGlzUmVjb3JkKHZhbHVlOiB1bmtub3duKTogdmFsdWUgaXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4ge1xuXHRyZXR1cm4gdmFsdWUgIT0gbnVsbCAmJiB0eXBlb2YgdmFsdWUgPT09IFwib2JqZWN0XCIgJiYgIUFycmF5LmlzQXJyYXkodmFsdWUpO1xufVxuXG5mdW5jdGlvbiBsb2FkRG90ZW52KHBhdGg6IHN0cmluZywgZW52OiBOb2RlSlMuUHJvY2Vzc0Vudik6IHZvaWQge1xuXHRsZXQgcmF3OiBzdHJpbmc7XG5cdHRyeSB7XG5cdFx0cmF3ID0gcmVhZEZpbGVTeW5jKHBhdGgsIFwidXRmOFwiKTtcblx0fSBjYXRjaCB7XG5cdFx0cmV0dXJuO1xuXHR9XG5cdGZvciAoY29uc3QgbGluZSBvZiByYXcuc3BsaXQoL1xccj9cXG4vKSkge1xuXHRcdGNvbnN0IHRyaW1tZWQgPSBsaW5lLnRyaW0oKTtcblx0XHRpZiAoIXRyaW1tZWQgfHwgdHJpbW1lZC5zdGFydHNXaXRoKFwiI1wiKSB8fCAhdHJpbW1lZC5pbmNsdWRlcyhcIj1cIikpIGNvbnRpbnVlO1xuXHRcdGNvbnN0IGVxID0gdHJpbW1lZC5pbmRleE9mKFwiPVwiKTtcblx0XHRjb25zdCBrZXkgPSB0cmltbWVkLnNsaWNlKDAsIGVxKS50cmltKCk7XG5cdFx0Y29uc3QgdmFsdWUgPSB0cmltbWVkXG5cdFx0XHQuc2xpY2UoZXEgKyAxKVxuXHRcdFx0LnRyaW0oKVxuXHRcdFx0LnJlcGxhY2UoL15bXCInXXxbXCInXSQvZywgXCJcIik7XG5cdFx0aWYgKGtleSAmJiBlbnZba2V5XSA9PT0gdW5kZWZpbmVkKSBlbnZba2V5XSA9IHZhbHVlO1xuXHR9XG59XG5cbmZ1bmN0aW9uIHNlZWRGcm9tTWNwSnNvbihyYXc6IHN0cmluZyk6IENvZGViYXNlUmFnQ3JlZGVudGlhbHMgfCBudWxsIHtcblx0bGV0IGRhdGE6IHVua25vd247XG5cdHRyeSB7XG5cdFx0ZGF0YSA9IEpTT04ucGFyc2UocmF3KTtcblx0fSBjYXRjaCB7XG5cdFx0cmV0dXJuIG51bGw7XG5cdH1cblx0aWYgKCFpc1JlY29yZChkYXRhKSkgcmV0dXJuIG51bGw7XG5cdGNvbnN0IHNlcnZlcnMgPSBkYXRhLm1jcFNlcnZlcnM7XG5cdGlmICghaXNSZWNvcmQoc2VydmVycykpIHJldHVybiBudWxsO1xuXHRjb25zdCBzZXJ2ZXIgPSBzZXJ2ZXJzW1wiY29kZWJhc2UtcmFnXCJdO1xuXHRpZiAoIWlzUmVjb3JkKHNlcnZlcikpIHJldHVybiBudWxsO1xuXHRjb25zdCB1cmwgPSB0eXBlb2Ygc2VydmVyLnVybCA9PT0gXCJzdHJpbmdcIiA/IHNlcnZlci51cmwudHJpbSgpIDogXCJcIjtcblx0Y29uc3QgaGVhZGVycyA9IGlzUmVjb3JkKHNlcnZlci5oZWFkZXJzKSA/IHNlcnZlci5oZWFkZXJzIDoge307XG5cdGNvbnN0IGF1dGggPSB0eXBlb2YgaGVhZGVycy5BdXRob3JpemF0aW9uID09PSBcInN0cmluZ1wiID8gaGVhZGVycy5BdXRob3JpemF0aW9uLnRyaW0oKSA6IFwiXCI7XG5cdGNvbnN0IHRva2VuID0gYXV0aC50b0xvd2VyQ2FzZSgpLnN0YXJ0c1dpdGgoXCJiZWFyZXIgXCIpID8gYXV0aC5zbGljZSg3KS50cmltKCkgOiBcIlwiO1xuXHRpZiAoIXVybC5zdGFydHNXaXRoKFwiaHR0cFwiKSB8fCB0b2tlbi5sZW5ndGggPT09IDApIHJldHVybiBudWxsO1xuXHRyZXR1cm4geyB1cmwsIHRva2VuIH07XG59XG5cbmZ1bmN0aW9uIG1lcmdlSW50b01jcEpzb24oaW5wdXQ6IHtcblx0bWNwUGF0aDogc3RyaW5nO1xuXHR1cmw6IHN0cmluZztcblx0dG9rZW46IHN0cmluZztcblx0aG9zdFJvb3Q6IHN0cmluZztcbn0pOiB7IHNraXBwZWQ/OiBzdHJpbmc7IHBhdGg/OiBzdHJpbmc7IHJvb3Q/OiBzdHJpbmcgfSB7XG5cdGNvbnN0IHsgbWNwUGF0aCwgdXJsLCB0b2tlbiwgaG9zdFJvb3QgfSA9IGlucHV0O1xuXHRpZiAoIXVybCB8fCAhdG9rZW4pIHtcblx0XHRyZXR1cm4geyBza2lwcGVkOiBcIm5vIFVSTC90b2tlblwiIH07XG5cdH1cblxuXHRjb25zdCB4Um9vdCA9IGhvc3RSb290IHx8IFwiJHt3b3Jrc3BhY2VGb2xkZXJ9XCI7XG5cdG1rZGlyU3luYyhkaXJuYW1lKG1jcFBhdGgpLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcblxuXHRsZXQgZGF0YTogTWNwSnNvbiA9IHsgbWNwU2VydmVyczoge30gfTtcblx0dHJ5IHtcblx0XHRpZiAoc3RhdFN5bmMobWNwUGF0aCkuc2l6ZSA+IDApIHtcblx0XHRcdGNvbnN0IGxvYWRlZDogdW5rbm93biA9IEpTT04ucGFyc2UocmVhZEZpbGVTeW5jKG1jcFBhdGgsIFwidXRmOFwiKSk7XG5cdFx0XHRpZiAoaXNSZWNvcmQobG9hZGVkKSkgZGF0YSA9IGxvYWRlZCBhcyBNY3BKc29uO1xuXHRcdH1cblx0fSBjYXRjaCAoZXJyKSB7XG5cdFx0Y29uc3QgY29kZSA9IGlzUmVjb3JkKGVycikgJiYgdHlwZW9mIGVyci5jb2RlID09PSBcInN0cmluZ1wiID8gZXJyLmNvZGUgOiBcIlwiO1xuXHRcdGlmIChjb2RlICE9PSBcIkVOT0VOVFwiKSB7XG5cdFx0XHRjb25zb2xlLmxvZyhcblx0XHRcdFx0XCJjb2RlYmFzZS1yYWcgTUNQOiBleGlzdGluZyBtY3AuanNvbiBpcyBpbnZhbGlkIEpTT047IHJlcGxhY2luZyByYWcgZW50cnkgb25seSBhZnRlciBiYWNrdXBcIixcblx0XHRcdCk7XG5cdFx0XHRyZW5hbWVTeW5jKG1jcFBhdGgsIGAke21jcFBhdGh9LmJha2ApO1xuXHRcdH1cblx0fVxuXG5cdGNvbnN0IHNlcnZlcnMgPSBpc1JlY29yZChkYXRhLm1jcFNlcnZlcnMpID8gZGF0YS5tY3BTZXJ2ZXJzIDoge307XG5cdGRhdGEubWNwU2VydmVycyA9IHNlcnZlcnM7XG5cdHNlcnZlcnNbXCJjb2RlYmFzZS1yYWdcIl0gPSB7XG5cdFx0dXJsLFxuXHRcdGhlYWRlcnM6IHtcblx0XHRcdEF1dGhvcml6YXRpb246IGBCZWFyZXIgJHt0b2tlbn1gLFxuXHRcdFx0XCJYLUNvZGViYXNlLVJvb3RcIjogeFJvb3QsXG5cdFx0fSxcblx0fTtcblx0d3JpdGVGaWxlU3luYyhtY3BQYXRoLCBgJHtKU09OLnN0cmluZ2lmeShkYXRhLCBudWxsLCAyKX1cXG5gLCBcInV0ZjhcIik7XG5cdHRyeSB7XG5cdFx0Y2htb2RTeW5jKG1jcFBhdGgsIDBvNjAwKTtcblx0fSBjYXRjaCB7XG5cdFx0Ly8gbWVtZnMgYW5kIHNvbWUgaG9zdHMgb21pdCBjaG1vZFxuXHR9XG5cdHJldHVybiB7IHBhdGg6IG1jcFBhdGgsIHJvb3Q6IHhSb290IH07XG59XG5cbmZ1bmN0aW9uIHdvcmtzcGFjZVJvb3QoZW52OiBOb2RlSlMuUHJvY2Vzc0VudiA9IHByb2Nlc3MuZW52KTogc3RyaW5nIHtcblx0Y29uc3QgZnJvbUVudiA9IGVudi5DT0RFQkFTRV9SQUdfV09SS1NQQUNFPy50cmltKCk7XG5cdGlmIChmcm9tRW52KSByZXR1cm4gZnJvbUVudjtcblx0Ly8gU2NhZmZvbGRlZCBjb3B5IGxpdmVzIGF0IDxyZXBvPi8uZGV2Y29udGFpbmVyL2NvZGViYXNlLXJhZy1tY3AudHNcblx0cmV0dXJuIGRpcm5hbWUoZGlybmFtZShmaWxlVVJMVG9QYXRoKGltcG9ydC5tZXRhLnVybCkpKTtcbn1cblxuZnVuY3Rpb24gbWVyZ2VGcm9tRW52KGVudjogTm9kZUpTLlByb2Nlc3NFbnYgPSBwcm9jZXNzLmVudik6IG51bWJlciB7XG5cdGNvbnN0IHJvb3QgPSB3b3Jrc3BhY2VSb290KGVudik7XG5cdGNvbnN0IGN1cnNvckRpciA9IGpvaW4ocm9vdCwgXCIuY3Vyc29yXCIpO1xuXHRsb2FkRG90ZW52KGpvaW4oY3Vyc29yRGlyLCBcImNvZGViYXNlLXJhZy5lbnZcIiksIGVudik7XG5cdGNvbnN0IHVybCA9IChlbnYuQ09ERUJBU0VfUkFHX01DUF9VUkwgPz8gXCJcIikudHJpbSgpO1xuXHRjb25zdCB0b2tlbiA9IChlbnYuQ09ERUJBU0VfUkFHX01DUF9UT0tFTiA/PyBcIlwiKS50cmltKCk7XG5cdGNvbnN0IGhvc3RSb290ID0gKGVudi5DT0RFQkFTRV9SQUdfTUNQX1JPT1QgPz8gXCJcIikudHJpbSgpIHx8IHJvb3Q7XG5cdGNvbnN0IHJlc3VsdCA9IG1lcmdlSW50b01jcEpzb24oe1xuXHRcdG1jcFBhdGg6IGpvaW4oY3Vyc29yRGlyLCBcIm1jcC5qc29uXCIpLFxuXHRcdHVybCxcblx0XHR0b2tlbixcblx0XHRob3N0Um9vdCxcblx0fSk7XG5cdGlmIChyZXN1bHQuc2tpcHBlZCAhPSBudWxsKSB7XG5cdFx0Y29uc29sZS5sb2coYGNvZGViYXNlLXJhZyBNQ1A6IHNraXBwZWQgKCR7cmVzdWx0LnNraXBwZWR9KWApO1xuXHRcdHJldHVybiAwO1xuXHR9XG5cdGNvbnNvbGUubG9nKGBjb2RlYmFzZS1yYWcgTUNQOiB3cm90ZSAke3Jlc3VsdC5wYXRofSB1cmw9JHt1cmx9IHJvb3Q9JHtyZXN1bHQucm9vdH1gKTtcblx0cmV0dXJuIDA7XG59XG5cbmZ1bmN0aW9uIHNlZWRQcmludChtY3BQYXRoOiBzdHJpbmcpOiBudW1iZXIge1xuXHRsZXQgcmF3OiBzdHJpbmc7XG5cdHRyeSB7XG5cdFx0cmF3ID0gcmVhZEZpbGVTeW5jKG1jcFBhdGgsIFwidXRmOFwiKTtcblx0fSBjYXRjaCB7XG5cdFx0cmV0dXJuIDE7XG5cdH1cblx0Y29uc3QgY3JlZHMgPSBzZWVkRnJvbU1jcEpzb24ocmF3KTtcblx0aWYgKGNyZWRzID09IG51bGwpIHJldHVybiAxO1xuXHRjb25zb2xlLmxvZyhjcmVkcy51cmwpO1xuXHRjb25zb2xlLmxvZyhjcmVkcy50b2tlbik7XG5cdHJldHVybiAwO1xufVxuXG5mdW5jdGlvbiBtYWluKGFyZ3YgPSBwcm9jZXNzLmFyZ3Yuc2xpY2UoMikpOiBudW1iZXIge1xuXHRjb25zdCBjb21tYW5kID0gYXJndlswXSA/PyBcIm1lcmdlXCI7XG5cdGlmIChjb21tYW5kID09PSBcInNlZWQtcHJpbnRcIikge1xuXHRcdGNvbnN0IG1jcFBhdGggPSBhcmd2WzFdO1xuXHRcdGlmIChtY3BQYXRoID09IG51bGwgfHwgbWNwUGF0aC5sZW5ndGggPT09IDApIHJldHVybiAxO1xuXHRcdHJldHVybiBzZWVkUHJpbnQobWNwUGF0aCk7XG5cdH1cblx0aWYgKGNvbW1hbmQgPT09IFwibWVyZ2VcIikge1xuXHRcdHJldHVybiBtZXJnZUZyb21FbnYoKTtcblx0fVxuXHRjb25zb2xlLmVycm9yKGBjb2RlYmFzZS1yYWcgTUNQOiB1bmtub3duIGNvbW1hbmQgJHtjb21tYW5kfWApO1xuXHRyZXR1cm4gMTtcbn1cblxuY29uc3QgaW52b2tlZCA9IChwcm9jZXNzLmFyZ3ZbMV0gPz8gXCJcIikucmVwbGFjZUFsbChcIlxcXFxcIiwgXCIvXCIpO1xuaWYgKGludm9rZWQuZW5kc1dpdGgoXCIvY29kZWJhc2UtcmFnLW1jcC50c1wiKSB8fCBpbnZva2VkLmVuZHNXaXRoKFwiL2NvZGViYXNlLXJhZy1tY3AuanNcIikpIHtcblx0cHJvY2Vzcy5leGl0KG1haW4oKSk7XG59XG5cbmV4cG9ydCBjb25zdCBjb2RlYmFzZVJhZ01jcCA9IHtcblx0bG9hZERvdGVudixcblx0c2VlZEZyb21NY3BKc29uLFxuXHRtZXJnZUludG9NY3BKc29uLFxuXHRtZXJnZUZyb21FbnYsXG5cdHNlZWRQcmludCxcblx0bWFpbixcbn07XG4iXSwibmFtZXMiOlsiY29kZWJhc2VSYWdNY3AiLCJpc1JlY29yZCIsInZhbHVlIiwiQXJyYXkiLCJpc0FycmF5IiwibG9hZERvdGVudiIsInBhdGgiLCJlbnYiLCJyYXciLCJyZWFkRmlsZVN5bmMiLCJsaW5lIiwic3BsaXQiLCJ0cmltbWVkIiwidHJpbSIsInN0YXJ0c1dpdGgiLCJpbmNsdWRlcyIsImVxIiwiaW5kZXhPZiIsImtleSIsInNsaWNlIiwicmVwbGFjZSIsInVuZGVmaW5lZCIsInNlZWRGcm9tTWNwSnNvbiIsImRhdGEiLCJKU09OIiwicGFyc2UiLCJzZXJ2ZXJzIiwibWNwU2VydmVycyIsInNlcnZlciIsInVybCIsImhlYWRlcnMiLCJhdXRoIiwiQXV0aG9yaXphdGlvbiIsInRva2VuIiwidG9Mb3dlckNhc2UiLCJsZW5ndGgiLCJtZXJnZUludG9NY3BKc29uIiwiaW5wdXQiLCJtY3BQYXRoIiwiaG9zdFJvb3QiLCJza2lwcGVkIiwieFJvb3QiLCJta2RpclN5bmMiLCJkaXJuYW1lIiwicmVjdXJzaXZlIiwic3RhdFN5bmMiLCJzaXplIiwibG9hZGVkIiwiZXJyIiwiY29kZSIsImNvbnNvbGUiLCJsb2ciLCJyZW5hbWVTeW5jIiwid3JpdGVGaWxlU3luYyIsInN0cmluZ2lmeSIsImNobW9kU3luYyIsInJvb3QiLCJ3b3Jrc3BhY2VSb290IiwicHJvY2VzcyIsImZyb21FbnYiLCJDT0RFQkFTRV9SQUdfV09SS1NQQUNFIiwiZmlsZVVSTFRvUGF0aCIsIm1lcmdlRnJvbUVudiIsImN1cnNvckRpciIsImpvaW4iLCJDT0RFQkFTRV9SQUdfTUNQX1VSTCIsIkNPREVCQVNFX1JBR19NQ1BfVE9LRU4iLCJDT0RFQkFTRV9SQUdfTUNQX1JPT1QiLCJyZXN1bHQiLCJzZWVkUHJpbnQiLCJjcmVkcyIsIm1haW4iLCJhcmd2IiwiY29tbWFuZCIsImVycm9yIiwiaW52b2tlZCIsInJlcGxhY2VBbGwiLCJlbmRzV2l0aCIsImV4aXQiXSwibWFwcGluZ3MiOiI7Ozs7K0JBOEthQTs7O2VBQUFBOzs7d0JBdktOOzBCQUN1Qjt5QkFDQTtBQVk5QixTQUFTQyxTQUFTQyxLQUFjO0lBQy9CLE9BQU9BLFNBQVMsUUFBUSxPQUFPQSxVQUFVLFlBQVksQ0FBQ0MsTUFBTUMsT0FBTyxDQUFDRjtBQUNyRTtBQUVBLFNBQVNHLFdBQVdDLElBQVksRUFBRUMsR0FBc0I7SUFDdkQsSUFBSUM7SUFDSixJQUFJO1FBQ0hBLE1BQU1DLElBQUFBLG9CQUFZLEVBQUNILE1BQU07SUFDMUIsRUFBRSxPQUFNO1FBQ1A7SUFDRDtJQUNBLEtBQUssTUFBTUksUUFBUUYsSUFBSUcsS0FBSyxDQUFDLFNBQVU7UUFDdEMsTUFBTUMsVUFBVUYsS0FBS0csSUFBSTtRQUN6QixJQUFJLENBQUNELFdBQVdBLFFBQVFFLFVBQVUsQ0FBQyxRQUFRLENBQUNGLFFBQVFHLFFBQVEsQ0FBQyxNQUFNO1FBQ25FLE1BQU1DLEtBQUtKLFFBQVFLLE9BQU8sQ0FBQztRQUMzQixNQUFNQyxNQUFNTixRQUFRTyxLQUFLLENBQUMsR0FBR0gsSUFBSUgsSUFBSTtRQUNyQyxNQUFNWCxRQUFRVSxRQUNaTyxLQUFLLENBQUNILEtBQUssR0FDWEgsSUFBSSxHQUNKTyxPQUFPLENBQUMsZ0JBQWdCO1FBQzFCLElBQUlGLE9BQU9YLEdBQUcsQ0FBQ1csSUFBSSxLQUFLRyxXQUFXZCxHQUFHLENBQUNXLElBQUksR0FBR2hCO0lBQy9DO0FBQ0Q7QUFFQSxTQUFTb0IsZ0JBQWdCZCxHQUFXO0lBQ25DLElBQUllO0lBQ0osSUFBSTtRQUNIQSxPQUFPQyxLQUFLQyxLQUFLLENBQUNqQjtJQUNu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
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import {
|
|
2
|
+
chmodSync,
|
|
3
|
+
mkdirSync,
|
|
4
|
+
readFileSync,
|
|
5
|
+
renameSync,
|
|
6
|
+
statSync,
|
|
7
|
+
writeFileSync,
|
|
8
|
+
} from "node:fs";
|
|
9
|
+
import { dirname, join } from "node:path";
|
|
10
|
+
import { fileURLToPath } from "node:url";
|
|
11
|
+
|
|
12
|
+
export type CodebaseRagCredentials = {
|
|
13
|
+
url: string;
|
|
14
|
+
token: string;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export type McpJson = {
|
|
18
|
+
mcpServers?: Record<string, unknown>;
|
|
19
|
+
[key: string]: unknown;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
23
|
+
return value != null && typeof value === "object" && !Array.isArray(value);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function loadDotenv(path: string, env: NodeJS.ProcessEnv): void {
|
|
27
|
+
let raw: string;
|
|
28
|
+
try {
|
|
29
|
+
raw = readFileSync(path, "utf8");
|
|
30
|
+
} catch {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
for (const line of raw.split(/\r?\n/)) {
|
|
34
|
+
const trimmed = line.trim();
|
|
35
|
+
if (!trimmed || trimmed.startsWith("#") || !trimmed.includes("=")) continue;
|
|
36
|
+
const eq = trimmed.indexOf("=");
|
|
37
|
+
const key = trimmed.slice(0, eq).trim();
|
|
38
|
+
const value = trimmed
|
|
39
|
+
.slice(eq + 1)
|
|
40
|
+
.trim()
|
|
41
|
+
.replace(/^["']|["']$/g, "");
|
|
42
|
+
if (key && env[key] === undefined) env[key] = value;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function seedFromMcpJson(raw: string): CodebaseRagCredentials | null {
|
|
47
|
+
let data: unknown;
|
|
48
|
+
try {
|
|
49
|
+
data = JSON.parse(raw);
|
|
50
|
+
} catch {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
if (!isRecord(data)) return null;
|
|
54
|
+
const servers = data.mcpServers;
|
|
55
|
+
if (!isRecord(servers)) return null;
|
|
56
|
+
const server = servers["codebase-rag"];
|
|
57
|
+
if (!isRecord(server)) return null;
|
|
58
|
+
const url = typeof server.url === "string" ? server.url.trim() : "";
|
|
59
|
+
const headers = isRecord(server.headers) ? server.headers : {};
|
|
60
|
+
const auth = typeof headers.Authorization === "string" ? headers.Authorization.trim() : "";
|
|
61
|
+
const token = auth.toLowerCase().startsWith("bearer ") ? auth.slice(7).trim() : "";
|
|
62
|
+
if (!url.startsWith("http") || token.length === 0) return null;
|
|
63
|
+
return { url, token };
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function mergeIntoMcpJson(input: {
|
|
67
|
+
mcpPath: string;
|
|
68
|
+
url: string;
|
|
69
|
+
token: string;
|
|
70
|
+
hostRoot: string;
|
|
71
|
+
}): { skipped?: string; path?: string; root?: string } {
|
|
72
|
+
const { mcpPath, url, token, hostRoot } = input;
|
|
73
|
+
if (!url || !token) {
|
|
74
|
+
return { skipped: "no URL/token" };
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const xRoot = hostRoot || "${workspaceFolder}";
|
|
78
|
+
mkdirSync(dirname(mcpPath), { recursive: true });
|
|
79
|
+
|
|
80
|
+
let data: McpJson = { mcpServers: {} };
|
|
81
|
+
try {
|
|
82
|
+
if (statSync(mcpPath).size > 0) {
|
|
83
|
+
const loaded: unknown = JSON.parse(readFileSync(mcpPath, "utf8"));
|
|
84
|
+
if (isRecord(loaded)) data = loaded as McpJson;
|
|
85
|
+
}
|
|
86
|
+
} catch (err) {
|
|
87
|
+
const code = isRecord(err) && typeof err.code === "string" ? err.code : "";
|
|
88
|
+
if (code !== "ENOENT") {
|
|
89
|
+
console.log(
|
|
90
|
+
"codebase-rag MCP: existing mcp.json is invalid JSON; replacing rag entry only after backup",
|
|
91
|
+
);
|
|
92
|
+
renameSync(mcpPath, `${mcpPath}.bak`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const servers = isRecord(data.mcpServers) ? data.mcpServers : {};
|
|
97
|
+
data.mcpServers = servers;
|
|
98
|
+
servers["codebase-rag"] = {
|
|
99
|
+
url,
|
|
100
|
+
headers: {
|
|
101
|
+
Authorization: `Bearer ${token}`,
|
|
102
|
+
"X-Codebase-Root": xRoot,
|
|
103
|
+
},
|
|
104
|
+
};
|
|
105
|
+
writeFileSync(mcpPath, `${JSON.stringify(data, null, 2)}\n`, "utf8");
|
|
106
|
+
try {
|
|
107
|
+
chmodSync(mcpPath, 0o600);
|
|
108
|
+
} catch {
|
|
109
|
+
// memfs and some hosts omit chmod
|
|
110
|
+
}
|
|
111
|
+
return { path: mcpPath, root: xRoot };
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function workspaceRoot(env: NodeJS.ProcessEnv = process.env): string {
|
|
115
|
+
const fromEnv = env.CODEBASE_RAG_WORKSPACE?.trim();
|
|
116
|
+
if (fromEnv) return fromEnv;
|
|
117
|
+
// Scaffolded copy lives at <repo>/.devcontainer/codebase-rag-mcp.ts
|
|
118
|
+
return dirname(dirname(fileURLToPath(import.meta.url)));
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function mergeFromEnv(env: NodeJS.ProcessEnv = process.env): number {
|
|
122
|
+
const root = workspaceRoot(env);
|
|
123
|
+
const cursorDir = join(root, ".cursor");
|
|
124
|
+
loadDotenv(join(cursorDir, "codebase-rag.env"), env);
|
|
125
|
+
const url = (env.CODEBASE_RAG_MCP_URL ?? "").trim();
|
|
126
|
+
const token = (env.CODEBASE_RAG_MCP_TOKEN ?? "").trim();
|
|
127
|
+
const hostRoot = (env.CODEBASE_RAG_MCP_ROOT ?? "").trim() || root;
|
|
128
|
+
const result = mergeIntoMcpJson({
|
|
129
|
+
mcpPath: join(cursorDir, "mcp.json"),
|
|
130
|
+
url,
|
|
131
|
+
token,
|
|
132
|
+
hostRoot,
|
|
133
|
+
});
|
|
134
|
+
if (result.skipped != null) {
|
|
135
|
+
console.log(`codebase-rag MCP: skipped (${result.skipped})`);
|
|
136
|
+
return 0;
|
|
137
|
+
}
|
|
138
|
+
console.log(`codebase-rag MCP: wrote ${result.path} url=${url} root=${result.root}`);
|
|
139
|
+
return 0;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function seedPrint(mcpPath: string): number {
|
|
143
|
+
let raw: string;
|
|
144
|
+
try {
|
|
145
|
+
raw = readFileSync(mcpPath, "utf8");
|
|
146
|
+
} catch {
|
|
147
|
+
return 1;
|
|
148
|
+
}
|
|
149
|
+
const creds = seedFromMcpJson(raw);
|
|
150
|
+
if (creds == null) return 1;
|
|
151
|
+
console.log(creds.url);
|
|
152
|
+
console.log(creds.token);
|
|
153
|
+
return 0;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function main(argv = process.argv.slice(2)): number {
|
|
157
|
+
const command = argv[0] ?? "merge";
|
|
158
|
+
if (command === "seed-print") {
|
|
159
|
+
const mcpPath = argv[1];
|
|
160
|
+
if (mcpPath == null || mcpPath.length === 0) return 1;
|
|
161
|
+
return seedPrint(mcpPath);
|
|
162
|
+
}
|
|
163
|
+
if (command === "merge") {
|
|
164
|
+
return mergeFromEnv();
|
|
165
|
+
}
|
|
166
|
+
console.error(`codebase-rag MCP: unknown command ${command}`);
|
|
167
|
+
return 1;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const invoked = (process.argv[1] ?? "").replaceAll("\\", "/");
|
|
171
|
+
if (invoked.endsWith("/codebase-rag-mcp.ts") || invoked.endsWith("/codebase-rag-mcp.js")) {
|
|
172
|
+
process.exit(main());
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export const codebaseRagMcp = {
|
|
176
|
+
loadDotenv,
|
|
177
|
+
seedFromMcpJson,
|
|
178
|
+
mergeIntoMcpJson,
|
|
179
|
+
mergeFromEnv,
|
|
180
|
+
seedPrint,
|
|
181
|
+
main,
|
|
182
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
function _export(target, all) {
|
|
6
|
+
for(var name in all)Object.defineProperty(target, name, {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: Object.getOwnPropertyDescriptor(all, name).get
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
_export(exports, {
|
|
12
|
+
get DevContainerHostScripts () {
|
|
13
|
+
return DevContainerHostScripts;
|
|
14
|
+
},
|
|
15
|
+
get codebaseRagMcpSourcePath () {
|
|
16
|
+
return codebaseRagMcpSourcePath;
|
|
17
|
+
},
|
|
18
|
+
get devcontainerTemplatePath () {
|
|
19
|
+
return devcontainerTemplatePath;
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
const _nodefs = require("node:fs");
|
|
23
|
+
const _nodeurl = require("node:url");
|
|
24
|
+
const TEMPLATE_FILES = [
|
|
25
|
+
"initialize.sh",
|
|
26
|
+
"post-create.sh",
|
|
27
|
+
"post-start.sh",
|
|
28
|
+
"tty-prompt.sh",
|
|
29
|
+
"codebase-rag.env.example"
|
|
30
|
+
];
|
|
31
|
+
function devcontainerTemplatePath(name) {
|
|
32
|
+
return (0, _nodeurl.fileURLToPath)(new URL(`./templates/${name}`, require("url").pathToFileURL(__filename).toString()));
|
|
33
|
+
}
|
|
34
|
+
function codebaseRagMcpSourcePath() {
|
|
35
|
+
return (0, _nodeurl.fileURLToPath)(new URL("./codebase-rag-mcp.ts", require("url").pathToFileURL(__filename).toString()));
|
|
36
|
+
}
|
|
37
|
+
class DevContainerHostScripts {
|
|
38
|
+
files() {
|
|
39
|
+
return [
|
|
40
|
+
...TEMPLATE_FILES.map((name)=>({
|
|
41
|
+
filePath: `.devcontainer/${name}`,
|
|
42
|
+
content: (0, _nodefs.readFileSync)(devcontainerTemplatePath(name), "utf8")
|
|
43
|
+
})),
|
|
44
|
+
{
|
|
45
|
+
filePath: ".devcontainer/codebase-rag-mcp.ts",
|
|
46
|
+
content: (0, _nodefs.readFileSync)(codebaseRagMcpSourcePath(), "utf8")
|
|
47
|
+
}
|
|
48
|
+
];
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL3J1bm5lci93b3JrL2RlY29oZXJlL2RlY29oZXJlL3Byb2plY3RzL3NjYWZmb2xkL3NyYy93ZWJhcGkvZGV2Y29udGFpbmVyL2hvc3Qtc2NyaXB0cy50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyByZWFkRmlsZVN5bmMgfSBmcm9tIFwibm9kZTpmc1wiO1xuaW1wb3J0IHsgZmlsZVVSTFRvUGF0aCB9IGZyb20gXCJub2RlOnVybFwiO1xuaW1wb3J0IHR5cGUgeyBTb3VyY2VGaWxlLCBTb3VyY2VGaWxlUHJvdmlkZXIgfSBmcm9tIFwiLi4vLi4vbW9kZWxzL3NvdXJjZS1maWxlLmpzXCI7XG5cbmNvbnN0IFRFTVBMQVRFX0ZJTEVTID0gW1xuXHRcImluaXRpYWxpemUuc2hcIixcblx0XCJwb3N0LWNyZWF0ZS5zaFwiLFxuXHRcInBvc3Qtc3RhcnQuc2hcIixcblx0XCJ0dHktcHJvbXB0LnNoXCIsXG5cdFwiY29kZWJhc2UtcmFnLmVudi5leGFtcGxlXCIsXG5dIGFzIGNvbnN0O1xuXG5leHBvcnQgZnVuY3Rpb24gZGV2Y29udGFpbmVyVGVtcGxhdGVQYXRoKG5hbWU6IHN0cmluZyk6IHN0cmluZyB7XG5cdHJldHVybiBmaWxlVVJMVG9QYXRoKG5ldyBVUkwoYC4vdGVtcGxhdGVzLyR7bmFtZX1gLCBpbXBvcnQubWV0YS51cmwpKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNvZGViYXNlUmFnTWNwU291cmNlUGF0aCgpOiBzdHJpbmcge1xuXHRyZXR1cm4gZmlsZVVSTFRvUGF0aChuZXcgVVJMKFwiLi9jb2RlYmFzZS1yYWctbWNwLnRzXCIsIGltcG9ydC5tZXRhLnVybCkpO1xufVxuXG4vKiogSG9zdCArIGNvbnRhaW5lciBzY3JpcHRzIGZvciB0aGUgc2NhZmZvbGRlZCBEZXYgQ29udGFpbmVyLiAqL1xuZXhwb3J0IGNsYXNzIERldkNvbnRhaW5lckhvc3RTY3JpcHRzIGltcGxlbWVudHMgU291cmNlRmlsZVByb3ZpZGVyIHtcblx0cHVibGljIGZpbGVzKCk6IFNvdXJjZUZpbGVbXSB7XG5cdFx0cmV0dXJuIFtcblx0XHRcdC4uLlRFTVBMQVRFX0ZJTEVTLm1hcCgobmFtZSkgPT4gKHtcblx0XHRcdFx0ZmlsZVBhdGg6IGAuZGV2Y29udGFpbmVyLyR7bmFtZX1gLFxuXHRcdFx0XHRjb250ZW50OiByZWFkRmlsZVN5bmMoZGV2Y29udGFpbmVyVGVtcGxhdGVQYXRoKG5hbWUpLCBcInV0ZjhcIiksXG5cdFx0XHR9KSksXG5cdFx0XHR7XG5cdFx0XHRcdGZpbGVQYXRoOiBcIi5kZXZjb250YWluZXIvY29kZWJhc2UtcmFnLW1jcC50c1wiLFxuXHRcdFx0XHRjb250ZW50OiByZWFkRmlsZVN5bmMoY29kZWJhc2VSYWdNY3BTb3VyY2VQYXRoKCksIFwidXRmOFwiKSxcblx0XHRcdH0sXG5cdFx0XTtcblx0fVxufVxuIl0sIm5hbWVzIjpbIkRldkNvbnRhaW5lckhvc3RTY3JpcHRzIiwiY29kZWJhc2VSYWdNY3BTb3VyY2VQYXRoIiwiZGV2Y29udGFpbmVyVGVtcGxhdGVQYXRoIiwiVEVNUExBVEVfRklMRVMiLCJuYW1lIiwiZmlsZVVSTFRvUGF0aCIsIlVSTCIsImZpbGVzIiwibWFwIiwiZmlsZVBhdGgiLCJjb250ZW50IiwicmVhZEZpbGVTeW5jIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7OztRQXFCYUE7ZUFBQUE7O1FBTEdDO2VBQUFBOztRQUpBQztlQUFBQTs7O3dCQVphO3lCQUNDO0FBRzlCLE1BQU1DLGlCQUFpQjtJQUN0QjtJQUNBO0lBQ0E7SUFDQTtJQUNBO0NBQ0E7QUFFTSxTQUFTRCx5QkFBeUJFLElBQVk7SUFDcEQsT0FBT0MsSUFBQUEsc0JBQWEsRUFBQyxJQUFJQyxJQUFJLENBQUMsWUFBWSxFQUFFRixNQUFNLEVBQUU7QUFDckQ7QUFFTyxTQUFTSDtJQUNmLE9BQU9JLElBQUFBLHNCQUFhLEVBQUMsSUFBSUMsSUFBSSx5QkFBeUI7QUFDdkQ7QUFHTyxNQUFNTjtJQUNMTyxRQUFzQjtRQUM1QixPQUFPO2VBQ0hKLGVBQWVLLEdBQUcsQ0FBQyxDQUFDSixPQUFVLENBQUE7b0JBQ2hDSyxVQUFVLENBQUMsY0FBYyxFQUFFTCxNQUFNO29CQUNqQ00sU0FBU0MsSUFBQUEsb0JBQVksRUFBQ1QseUJBQXlCRSxPQUFPO2dCQUN2RCxDQUFBO1lBQ0E7Z0JBQ0NLLFVBQVU7Z0JBQ1ZDLFNBQVNDLElBQUFBLG9CQUFZLEVBQUNWLDRCQUE0QjtZQUNuRDtTQUNBO0lBQ0Y7QUFDRCJ9
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Runs on the host before the container is created (devcontainer initializeCommand).
|
|
3
|
+
# Creates bind-mount sources as the host user so Docker does not create them as root.
|
|
4
|
+
# Optional npm / gh / MCP setup is y/N on a TTY; no TTY skips.
|
|
5
|
+
set -euo pipefail
|
|
6
|
+
|
|
7
|
+
root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
8
|
+
here="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
9
|
+
# shellcheck source=tty-prompt.sh
|
|
10
|
+
source "$here/tty-prompt.sh"
|
|
11
|
+
|
|
12
|
+
npm_dir="$root/.devcontainer/npm-auth"
|
|
13
|
+
gh_dir="$root/.devcontainer/gh-auth"
|
|
14
|
+
gh_env="$root/.devcontainer/gh.env"
|
|
15
|
+
cursor_dir="$root/.cursor"
|
|
16
|
+
RAG_ENV="$cursor_dir/codebase-rag.env"
|
|
17
|
+
|
|
18
|
+
run_codebase_rag_mcp() {
|
|
19
|
+
local script="$here/codebase-rag-mcp.ts"
|
|
20
|
+
CODEBASE_RAG_WORKSPACE="$root" node --experimental-strip-types "$script" "$@"
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
load_rag_env() {
|
|
24
|
+
RAG_URL=""
|
|
25
|
+
RAG_TOKEN=""
|
|
26
|
+
[[ -f "$RAG_ENV" ]] || return 0
|
|
27
|
+
# shellcheck disable=SC1090
|
|
28
|
+
set -a
|
|
29
|
+
# shellcheck disable=SC1090
|
|
30
|
+
source "$RAG_ENV"
|
|
31
|
+
set +a
|
|
32
|
+
RAG_URL="${CODEBASE_RAG_MCP_URL:-}"
|
|
33
|
+
RAG_TOKEN="${CODEBASE_RAG_MCP_TOKEN:-}"
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
write_rag_env() {
|
|
37
|
+
mkdir -p "$(dirname "$RAG_ENV")"
|
|
38
|
+
umask 077
|
|
39
|
+
cat >"$RAG_ENV" <<EOF
|
|
40
|
+
# Written by .devcontainer/initialize.sh. Not in git.
|
|
41
|
+
CODEBASE_RAG_MCP_URL=${RAG_URL}
|
|
42
|
+
CODEBASE_RAG_MCP_TOKEN=${RAG_TOKEN}
|
|
43
|
+
CODEBASE_RAG_MCP_ROOT=${root}
|
|
44
|
+
EOF
|
|
45
|
+
chmod 600 "$RAG_ENV"
|
|
46
|
+
if [[ -n "$RAG_URL" && -n "$RAG_TOKEN" ]]; then
|
|
47
|
+
run_codebase_rag_mcp merge || true
|
|
48
|
+
fi
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
seed_rag_from_host_mcp() {
|
|
52
|
+
local mcp="${HOME}/.cursor/mcp.json"
|
|
53
|
+
[[ -f "$mcp" ]] || return 1
|
|
54
|
+
command -v node >/dev/null 2>&1 || return 1
|
|
55
|
+
run_codebase_rag_mcp seed-print "$mcp"
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
ensure_cursor_dir() {
|
|
59
|
+
mkdir -p "$cursor_dir"
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
ensure_auth_dir() {
|
|
63
|
+
local dir="$1"
|
|
64
|
+
if ! mkdir -p "$dir" 2>/dev/null; then
|
|
65
|
+
echo "Cannot create $dir (permission denied)." >&2
|
|
66
|
+
echo "The scaffold container likely left .devcontainer root-owned. Fix with:" >&2
|
|
67
|
+
echo " sudo chown -R \"$USER:$USER\" \"$root\"" >&2
|
|
68
|
+
exit 1
|
|
69
|
+
fi
|
|
70
|
+
{
|
|
71
|
+
echo "*"
|
|
72
|
+
echo "!.gitignore"
|
|
73
|
+
} >"$dir/.gitignore"
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
ensure_gh_env() {
|
|
77
|
+
if [[ -d "$gh_env" ]]; then
|
|
78
|
+
echo "Refusing to start: $gh_env is a directory (left by a prior bind mount). Remove it and rebuild." >&2
|
|
79
|
+
exit 1
|
|
80
|
+
fi
|
|
81
|
+
touch "$gh_env"
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
setup_npm_auth() {
|
|
85
|
+
if [[ -f "$npm_dir/.npmrc" ]]; then
|
|
86
|
+
echo "npm auth: using $npm_dir/.npmrc"
|
|
87
|
+
return 0
|
|
88
|
+
fi
|
|
89
|
+
if ! prompt_yn "Configure npm auth for this workspace?"; then
|
|
90
|
+
echo "npm auth: skipped"
|
|
91
|
+
return 0
|
|
92
|
+
fi
|
|
93
|
+
if [[ -f "${HOME}/.npmrc" ]]; then
|
|
94
|
+
cp -a "${HOME}/.npmrc" "$npm_dir/.npmrc"
|
|
95
|
+
echo "npm auth: copied ~/.npmrc → $npm_dir/.npmrc"
|
|
96
|
+
return 0
|
|
97
|
+
fi
|
|
98
|
+
echo "npm auth: no ~/.npmrc — log in inside the container if prompted"
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
setup_gh_auth() {
|
|
102
|
+
if [[ -f "$gh_dir/hosts.yml" ]]; then
|
|
103
|
+
echo "gh auth: using $gh_dir/hosts.yml"
|
|
104
|
+
return 0
|
|
105
|
+
fi
|
|
106
|
+
if ! prompt_yn "Configure GitHub CLI auth for this workspace?"; then
|
|
107
|
+
echo "gh auth: skipped"
|
|
108
|
+
return 0
|
|
109
|
+
fi
|
|
110
|
+
if [[ -f "${HOME}/.config/gh/hosts.yml" ]]; then
|
|
111
|
+
cp -a "${HOME}/.config/gh/hosts.yml" "$gh_dir/hosts.yml"
|
|
112
|
+
[[ -f "${HOME}/.config/gh/config.yml" ]] &&
|
|
113
|
+
cp -a "${HOME}/.config/gh/config.yml" "$gh_dir/config.yml"
|
|
114
|
+
echo "gh auth: copied ~/.config/gh → $gh_dir"
|
|
115
|
+
return 0
|
|
116
|
+
fi
|
|
117
|
+
echo "gh auth: no ~/.config/gh/hosts.yml — log in inside the container if prompted"
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
setup_codebase_rag_env() {
|
|
121
|
+
load_rag_env
|
|
122
|
+
if [[ -n "$RAG_URL" && -n "$RAG_TOKEN" ]]; then
|
|
123
|
+
write_rag_env
|
|
124
|
+
echo "codebase-rag MCP: using $RAG_ENV"
|
|
125
|
+
return 0
|
|
126
|
+
fi
|
|
127
|
+
|
|
128
|
+
local seeded
|
|
129
|
+
if seeded="$(seed_rag_from_host_mcp 2>/dev/null)"; then
|
|
130
|
+
if prompt_yn "Found codebase-rag in ~/.cursor/mcp.json. Use it for this workspace?" y; then
|
|
131
|
+
RAG_URL="$(printf '%s\n' "$seeded" | sed -n '1p')"
|
|
132
|
+
RAG_TOKEN="$(printf '%s\n' "$seeded" | sed -n '2p')"
|
|
133
|
+
write_rag_env
|
|
134
|
+
echo "codebase-rag MCP: imported HTTP server from ~/.cursor/mcp.json → $RAG_ENV"
|
|
135
|
+
return 0
|
|
136
|
+
fi
|
|
137
|
+
fi
|
|
138
|
+
|
|
139
|
+
if ! prompt_yn "Configure codebase RAG MCP (semantic search)?"; then
|
|
140
|
+
RAG_URL=""
|
|
141
|
+
RAG_TOKEN=""
|
|
142
|
+
write_rag_env
|
|
143
|
+
echo "codebase-rag MCP: skipped"
|
|
144
|
+
return 0
|
|
145
|
+
fi
|
|
146
|
+
|
|
147
|
+
printf '%s\n' "Empty URL skips. Example: https://rag.example.com/mcp" >/dev/tty
|
|
148
|
+
printf '%s' "MCP URL: " >/dev/tty
|
|
149
|
+
read_tty RAG_URL
|
|
150
|
+
RAG_URL="$(printf '%s' "$RAG_URL" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')"
|
|
151
|
+
if [[ -z "$RAG_URL" ]]; then
|
|
152
|
+
RAG_TOKEN=""
|
|
153
|
+
write_rag_env
|
|
154
|
+
echo "codebase-rag MCP: skipped"
|
|
155
|
+
return 0
|
|
156
|
+
fi
|
|
157
|
+
printf '%s' "Bearer token (hidden): " >/dev/tty
|
|
158
|
+
read_tty RAG_TOKEN hidden
|
|
159
|
+
write_rag_env
|
|
160
|
+
echo "codebase-rag MCP: saved $RAG_ENV"
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
ensure_auth_dir "$npm_dir"
|
|
164
|
+
ensure_auth_dir "$gh_dir"
|
|
165
|
+
ensure_gh_env
|
|
166
|
+
ensure_cursor_dir
|
|
167
|
+
setup_npm_auth
|
|
168
|
+
setup_gh_auth
|
|
169
|
+
setup_codebase_rag_env
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Runs after container create and when workspace content updates
|
|
3
|
+
# (devcontainer postCreateCommand / updateContentCommand).
|
|
4
|
+
# Installs deps when missing or when the lockfile changed; skips otherwise.
|
|
5
|
+
set -euo pipefail
|
|
6
|
+
|
|
7
|
+
root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
8
|
+
cd "$root"
|
|
9
|
+
|
|
10
|
+
lockfile="pnpm-lock.yaml"
|
|
11
|
+
stamp="node_modules/.decohere-pnpm-lock.sha"
|
|
12
|
+
|
|
13
|
+
current_hash=""
|
|
14
|
+
if [[ -f "$lockfile" ]]; then
|
|
15
|
+
current_hash="$(sha256sum "$lockfile" | awk '{print $1}')"
|
|
16
|
+
elif [[ -f package.json ]]; then
|
|
17
|
+
current_hash="$(sha256sum package.json | awk '{print $1}')"
|
|
18
|
+
fi
|
|
19
|
+
|
|
20
|
+
if [[ -d node_modules/.bin ]] && [[ -n "$current_hash" ]] && [[ -f "$stamp" ]] && [[ "$(cat "$stamp")" == "$current_hash" ]]; then
|
|
21
|
+
echo "node_modules: up to date, skipping pnpm install"
|
|
22
|
+
exit 0
|
|
23
|
+
fi
|
|
24
|
+
|
|
25
|
+
echo "node_modules: installing dependencies (first create may take a while)..."
|
|
26
|
+
if [[ -f "$lockfile" ]]; then
|
|
27
|
+
pnpm install --frozen-lockfile
|
|
28
|
+
else
|
|
29
|
+
pnpm install
|
|
30
|
+
fi
|
|
31
|
+
|
|
32
|
+
if [[ -n "$current_hash" ]]; then
|
|
33
|
+
mkdir -p node_modules
|
|
34
|
+
printf '%s\n' "$current_hash" >"$stamp"
|
|
35
|
+
fi
|