didev 1.0.0
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 +378 -0
- package/dist/agents/analyst.d.ts +21 -0
- package/dist/agents/analyst.d.ts.map +1 -0
- package/dist/agents/analyst.js +69 -0
- package/dist/agents/analyst.js.map +1 -0
- package/dist/agents/architect.d.ts +21 -0
- package/dist/agents/architect.d.ts.map +1 -0
- package/dist/agents/architect.js +85 -0
- package/dist/agents/architect.js.map +1 -0
- package/dist/agents/base-agent.d.ts +56 -0
- package/dist/agents/base-agent.d.ts.map +1 -0
- package/dist/agents/base-agent.js +263 -0
- package/dist/agents/base-agent.js.map +1 -0
- package/dist/agents/developer.d.ts +21 -0
- package/dist/agents/developer.d.ts.map +1 -0
- package/dist/agents/developer.js +87 -0
- package/dist/agents/developer.js.map +1 -0
- package/dist/agents/orchestrator.d.ts +23 -0
- package/dist/agents/orchestrator.d.ts.map +1 -0
- package/dist/agents/orchestrator.js +287 -0
- package/dist/agents/orchestrator.js.map +1 -0
- package/dist/agents/reviewer.d.ts +15 -0
- package/dist/agents/reviewer.d.ts.map +1 -0
- package/dist/agents/reviewer.js +65 -0
- package/dist/agents/reviewer.js.map +1 -0
- package/dist/agents/tester.d.ts +15 -0
- package/dist/agents/tester.d.ts.map +1 -0
- package/dist/agents/tester.js +64 -0
- package/dist/agents/tester.js.map +1 -0
- package/dist/bmad/method.d.ts +6 -0
- package/dist/bmad/method.d.ts.map +1 -0
- package/dist/bmad/method.js +221 -0
- package/dist/bmad/method.js.map +1 -0
- package/dist/cli/commands/agent.d.ts +10 -0
- package/dist/cli/commands/agent.d.ts.map +1 -0
- package/dist/cli/commands/agent.js +28 -0
- package/dist/cli/commands/agent.js.map +1 -0
- package/dist/cli/commands/chat.d.ts +6 -0
- package/dist/cli/commands/chat.d.ts.map +1 -0
- package/dist/cli/commands/chat.js +556 -0
- package/dist/cli/commands/chat.js.map +1 -0
- package/dist/cli/commands/config.d.ts +3 -0
- package/dist/cli/commands/config.d.ts.map +1 -0
- package/dist/cli/commands/config.js +65 -0
- package/dist/cli/commands/config.js.map +1 -0
- package/dist/cli/commands/init.d.ts +8 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +204 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/mcp.d.ts +5 -0
- package/dist/cli/commands/mcp.d.ts.map +1 -0
- package/dist/cli/commands/mcp.js +836 -0
- package/dist/cli/commands/mcp.js.map +1 -0
- package/dist/cli/commands/refactor.d.ts +8 -0
- package/dist/cli/commands/refactor.d.ts.map +1 -0
- package/dist/cli/commands/refactor.js +161 -0
- package/dist/cli/commands/refactor.js.map +1 -0
- package/dist/cli/commands/review.d.ts +9 -0
- package/dist/cli/commands/review.d.ts.map +1 -0
- package/dist/cli/commands/review.js +138 -0
- package/dist/cli/commands/review.js.map +1 -0
- package/dist/core/api.d.ts +73 -0
- package/dist/core/api.d.ts.map +1 -0
- package/dist/core/api.js +206 -0
- package/dist/core/api.js.map +1 -0
- package/dist/core/config.d.ts +42 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +180 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/context.d.ts +33 -0
- package/dist/core/context.d.ts.map +1 -0
- package/dist/core/context.js +235 -0
- package/dist/core/context.js.map +1 -0
- package/dist/core/file-manager.d.ts +20 -0
- package/dist/core/file-manager.d.ts.map +1 -0
- package/dist/core/file-manager.js +133 -0
- package/dist/core/file-manager.js.map +1 -0
- package/dist/core/mcp.d.ts +31 -0
- package/dist/core/mcp.d.ts.map +1 -0
- package/dist/core/mcp.js +112 -0
- package/dist/core/mcp.js.map +1 -0
- package/dist/core/session.d.ts +16 -0
- package/dist/core/session.d.ts.map +1 -0
- package/dist/core/session.js +60 -0
- package/dist/core/session.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +237 -0
- package/dist/index.js.map +1 -0
- package/dist/utils/banner.d.ts +2 -0
- package/dist/utils/banner.d.ts.map +1 -0
- package/dist/utils/banner.js +50 -0
- package/dist/utils/banner.js.map +1 -0
- package/dist/utils/git.d.ts +9 -0
- package/dist/utils/git.d.ts.map +1 -0
- package/dist/utils/git.js +49 -0
- package/dist/utils/git.js.map +1 -0
- package/dist/utils/logger.d.ts +42 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +98 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/resilience.d.ts +17 -0
- package/dist/utils/resilience.d.ts.map +1 -0
- package/dist/utils/resilience.js +41 -0
- package/dist/utils/resilience.js.map +1 -0
- package/dist/utils/token-counter.d.ts +7 -0
- package/dist/utils/token-counter.d.ts.map +1 -0
- package/dist/utils/token-counter.js +20 -0
- package/dist/utils/token-counter.js.map +1 -0
- package/package.json +62 -0
- package/scripts/postinstall.mjs +54 -0
- package/scripts/setup-path.sh +42 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { logger } from './logger.js';
|
|
2
|
+
/**
|
|
3
|
+
* Race a promise against a timeout. Rejects with a descriptive error if ms elapses first.
|
|
4
|
+
* Clears the internal timer regardless of which side wins, preventing Node from staying alive.
|
|
5
|
+
*/
|
|
6
|
+
export function withTimeout(promise, ms, label = 'Operation') {
|
|
7
|
+
let timer;
|
|
8
|
+
const timeout = new Promise((_, reject) => {
|
|
9
|
+
timer = setTimeout(() => reject(new Error(`${label} timed out after ${ms}ms`)), ms);
|
|
10
|
+
});
|
|
11
|
+
return Promise.race([
|
|
12
|
+
promise.finally(() => clearTimeout(timer)),
|
|
13
|
+
timeout,
|
|
14
|
+
]);
|
|
15
|
+
}
|
|
16
|
+
const RETRIABLE = /timeout|ECONNREFUSED|ECONNRESET|ETIMEDOUT|fetch failed|network|50[234]|429/i;
|
|
17
|
+
/**
|
|
18
|
+
* Retry fn with exponential backoff + jitter on transient errors.
|
|
19
|
+
* Non-retriable errors (4xx except 429, logic errors) are re-thrown immediately.
|
|
20
|
+
*/
|
|
21
|
+
export async function retryWithBackoff(fn, options = {}) {
|
|
22
|
+
const { maxAttempts = 3, initialDelay = 500, maxDelay = 10_000, label = 'Operation' } = options;
|
|
23
|
+
let lastError;
|
|
24
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
25
|
+
try {
|
|
26
|
+
return await fn();
|
|
27
|
+
}
|
|
28
|
+
catch (e) {
|
|
29
|
+
lastError = e;
|
|
30
|
+
const isRetriable = RETRIABLE.test(lastError.message);
|
|
31
|
+
if (!isRetriable || attempt === maxAttempts - 1)
|
|
32
|
+
throw lastError;
|
|
33
|
+
const jitter = Math.random() * 200;
|
|
34
|
+
const delay = Math.min(initialDelay * Math.pow(2, attempt) + jitter, maxDelay);
|
|
35
|
+
logger.debug(`${label}: attempt ${attempt + 1} failed ("${lastError.message}"), retrying in ${Math.round(delay)}ms…`);
|
|
36
|
+
await new Promise(r => setTimeout(r, delay));
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
throw lastError;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=resilience.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resilience.js","sourceRoot":"","sources":["../../src/utils/resilience.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAI,OAAmB,EAAE,EAAU,EAAE,KAAK,GAAG,WAAW;IACjF,IAAI,KAAoC,CAAC;IACzC,MAAM,OAAO,GAAG,IAAI,OAAO,CAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE;QAC/C,KAAK,GAAG,UAAU,CAChB,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,GAAG,KAAK,oBAAoB,EAAE,IAAI,CAAC,CAAC,EAC3D,EAAE,CACH,CAAC;IACJ,CAAC,CAAC,CAAC;IACH,OAAO,OAAO,CAAC,IAAI,CAAC;QAClB,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC,KAAM,CAAC,CAAC;QAC3C,OAAO;KACR,CAAC,CAAC;AACL,CAAC;AASD,MAAM,SAAS,GAAG,6EAA6E,CAAC;AAEhG;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,EAAoB,EACpB,UAAwB,EAAE;IAE1B,MAAM,EAAE,WAAW,GAAG,CAAC,EAAE,YAAY,GAAG,GAAG,EAAE,QAAQ,GAAG,MAAM,EAAE,KAAK,GAAG,WAAW,EAAE,GAAG,OAAO,CAAC;IAChG,IAAI,SAAiB,CAAC;IAEtB,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,WAAW,EAAE,OAAO,EAAE,EAAE,CAAC;QACvD,IAAI,CAAC;YACH,OAAO,MAAM,EAAE,EAAE,CAAC;QACpB,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,SAAS,GAAG,CAAU,CAAC;YACvB,MAAM,WAAW,GAAG,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;YACtD,IAAI,CAAC,WAAW,IAAI,OAAO,KAAK,WAAW,GAAG,CAAC;gBAAE,MAAM,SAAS,CAAC;YACjE,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,GAAG,CAAC;YACnC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,GAAG,MAAM,EAAE,QAAQ,CAAC,CAAC;YAC/E,MAAM,CAAC,KAAK,CAAC,GAAG,KAAK,aAAa,OAAO,GAAG,CAAC,aAAa,SAAS,CAAC,OAAO,mBAAmB,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACtH,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC;IAED,MAAM,SAAS,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare function countTokens(text: string): number;
|
|
2
|
+
export declare function countMessagesTokens(messages: Array<{
|
|
3
|
+
content: string;
|
|
4
|
+
}>): number;
|
|
5
|
+
export declare function truncateToTokenLimit(text: string, maxTokens: number): string;
|
|
6
|
+
export declare function formatTokenCount(n: number): string;
|
|
7
|
+
//# sourceMappingURL=token-counter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-counter.d.ts","sourceRoot":"","sources":["../../src/utils/token-counter.ts"],"names":[],"mappings":"AAEA,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,KAAK,CAAC;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,GAAG,MAAM,CAEhF;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAI5E;AAED,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAGlD"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// Approximate token counting without external dependencies
|
|
2
|
+
// ~4 chars per token for English/code text
|
|
3
|
+
export function countTokens(text) {
|
|
4
|
+
return Math.ceil(text.length / 4);
|
|
5
|
+
}
|
|
6
|
+
export function countMessagesTokens(messages) {
|
|
7
|
+
return messages.reduce((sum, m) => sum + countTokens(m.content) + 4, 0);
|
|
8
|
+
}
|
|
9
|
+
export function truncateToTokenLimit(text, maxTokens) {
|
|
10
|
+
const maxChars = maxTokens * 4;
|
|
11
|
+
if (text.length <= maxChars)
|
|
12
|
+
return text;
|
|
13
|
+
return text.slice(0, maxChars - 100) + '\n... [truncated]';
|
|
14
|
+
}
|
|
15
|
+
export function formatTokenCount(n) {
|
|
16
|
+
if (n >= 1000)
|
|
17
|
+
return `${(n / 1000).toFixed(1)}k`;
|
|
18
|
+
return String(n);
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=token-counter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-counter.js","sourceRoot":"","sources":["../../src/utils/token-counter.ts"],"names":[],"mappings":"AAAA,2DAA2D;AAC3D,2CAA2C;AAC3C,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,QAAoC;IACtE,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;AAC1E,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,IAAY,EAAE,SAAiB;IAClE,MAAM,QAAQ,GAAG,SAAS,GAAG,CAAC,CAAC;IAC/B,IAAI,IAAI,CAAC,MAAM,IAAI,QAAQ;QAAE,OAAO,IAAI,CAAC;IACzC,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,GAAG,GAAG,CAAC,GAAG,mBAAmB,CAAC;AAC7D,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,CAAS;IACxC,IAAI,CAAC,IAAI,IAAI;QAAE,OAAO,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;IAClD,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC;AACnB,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "didev",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Professional AI-powered CLI for developers using DeepSeek API",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"didev": "./dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"scripts",
|
|
13
|
+
"templates",
|
|
14
|
+
"README.md"
|
|
15
|
+
],
|
|
16
|
+
"author": "neovaryag",
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsc",
|
|
19
|
+
"dev": "tsx src/index.ts",
|
|
20
|
+
"start": "node dist/index.js",
|
|
21
|
+
"test": "vitest",
|
|
22
|
+
"lint": "tsc --noEmit",
|
|
23
|
+
"postinstall": "node scripts/postinstall.mjs",
|
|
24
|
+
"setup-path": "bash scripts/setup-path.sh",
|
|
25
|
+
"prepublishOnly": "npm run build"
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
29
|
+
"boxen": "^7.1.1",
|
|
30
|
+
"chalk": "^5.3.0",
|
|
31
|
+
"chokidar": "^3.5.3",
|
|
32
|
+
"commander": "^12.0.0",
|
|
33
|
+
"diff": "^5.2.0",
|
|
34
|
+
"dotenv": "^16.4.5",
|
|
35
|
+
"glob": "^10.4.1",
|
|
36
|
+
"inquirer": "^9.2.20",
|
|
37
|
+
"js-yaml": "^4.1.0",
|
|
38
|
+
"ora": "^8.0.1",
|
|
39
|
+
"undici": "^6.13.0"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@types/diff": "^5.2.1",
|
|
43
|
+
"@types/inquirer": "^9.0.7",
|
|
44
|
+
"@types/js-yaml": "^4.0.9",
|
|
45
|
+
"@types/node": "^20.14.0",
|
|
46
|
+
"pptxgenjs": "^4.0.1",
|
|
47
|
+
"tsx": "^4.15.7",
|
|
48
|
+
"typescript": "^5.4.5",
|
|
49
|
+
"vitest": "^1.6.0"
|
|
50
|
+
},
|
|
51
|
+
"engines": {
|
|
52
|
+
"node": ">=18.0.0"
|
|
53
|
+
},
|
|
54
|
+
"keywords": [
|
|
55
|
+
"cli",
|
|
56
|
+
"ai",
|
|
57
|
+
"deepseek",
|
|
58
|
+
"developer-tools",
|
|
59
|
+
"code-review"
|
|
60
|
+
],
|
|
61
|
+
"license": "MIT"
|
|
62
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Runs after `npm install -g didev`. Shows PATH setup instructions for Git Bash.
|
|
3
|
+
import { execSync } from 'child_process';
|
|
4
|
+
import { existsSync, readFileSync } from 'fs';
|
|
5
|
+
import { join } from 'path';
|
|
6
|
+
import { homedir } from 'os';
|
|
7
|
+
|
|
8
|
+
// Skip for local (non-global) installs
|
|
9
|
+
if (!process.env.npm_config_global) process.exit(0);
|
|
10
|
+
|
|
11
|
+
let prefix = '';
|
|
12
|
+
try {
|
|
13
|
+
prefix = execSync('npm config get prefix', { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }).trim();
|
|
14
|
+
} catch {
|
|
15
|
+
process.exit(0);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Convert Windows path (C:\...) to Git Bash path (/c/...)
|
|
19
|
+
function toBashPath(winPath) {
|
|
20
|
+
const match = winPath.match(/^([A-Za-z]):[\\\/](.*)/);
|
|
21
|
+
if (match) {
|
|
22
|
+
const drive = match[1].toLowerCase();
|
|
23
|
+
const rest = match[2].replace(/\\/g, '/');
|
|
24
|
+
return `/${drive}/${rest}`;
|
|
25
|
+
}
|
|
26
|
+
return winPath.replace(/\\/g, '/');
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const bashPrefix = toBashPath(prefix);
|
|
30
|
+
const exportLine = `export PATH="${bashPrefix}:$PATH"`;
|
|
31
|
+
const bashrc = join(homedir(), '.bashrc');
|
|
32
|
+
|
|
33
|
+
let alreadyConfigured = false;
|
|
34
|
+
if (existsSync(bashrc)) {
|
|
35
|
+
const content = readFileSync(bashrc, 'utf-8');
|
|
36
|
+
alreadyConfigured = content.includes(bashPrefix) || content.includes('didev PATH');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
console.log('\n✅ didev installed globally!');
|
|
40
|
+
|
|
41
|
+
if (!alreadyConfigured) {
|
|
42
|
+
console.log('\n⚠️ To use didev in Git Bash, add npm global bin to your PATH.');
|
|
43
|
+
console.log('\n Run these commands in Git Bash:');
|
|
44
|
+
console.log(`\n echo '# didev PATH' >> ~/.bashrc`);
|
|
45
|
+
console.log(` echo '${exportLine}' >> ~/.bashrc`);
|
|
46
|
+
console.log(` source ~/.bashrc`);
|
|
47
|
+
console.log('\n Or run the helper script:');
|
|
48
|
+
console.log(' bash scripts/setup-path.sh');
|
|
49
|
+
} else {
|
|
50
|
+
console.log('✅ PATH is already configured.');
|
|
51
|
+
console.log(' Run: source ~/.bashrc (if in a new terminal)');
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
console.log('\n Then verify: didev --version\n');
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Adds npm global bin directory to PATH in ~/.bashrc for Git Bash on Windows.
|
|
3
|
+
# Usage: bash scripts/setup-path.sh
|
|
4
|
+
|
|
5
|
+
set -euo pipefail
|
|
6
|
+
|
|
7
|
+
PREFIX=$(npm config get prefix 2>/dev/null)
|
|
8
|
+
if [ -z "$PREFIX" ]; then
|
|
9
|
+
echo "Error: could not determine npm prefix. Make sure Node.js is installed."
|
|
10
|
+
exit 1
|
|
11
|
+
fi
|
|
12
|
+
|
|
13
|
+
# Convert Windows path (C:\...) to Git Bash format (/c/...)
|
|
14
|
+
if [[ "$PREFIX" =~ ^[A-Za-z]:\\ ]] || [[ "$PREFIX" =~ ^[A-Za-z]:/ ]]; then
|
|
15
|
+
DRIVE=$(echo "$PREFIX" | cut -c1 | tr '[:upper:]' '[:lower:]')
|
|
16
|
+
REST=$(echo "$PREFIX" | cut -c3- | tr '\\' '/')
|
|
17
|
+
BASH_PREFIX="/${DRIVE}/${REST}"
|
|
18
|
+
else
|
|
19
|
+
BASH_PREFIX="$PREFIX"
|
|
20
|
+
fi
|
|
21
|
+
|
|
22
|
+
EXPORT_LINE="export PATH=\"${BASH_PREFIX}:\$PATH\""
|
|
23
|
+
BASHRC="$HOME/.bashrc"
|
|
24
|
+
MARKER="# didev PATH"
|
|
25
|
+
|
|
26
|
+
if grep -qF "didev PATH" "$BASHRC" 2>/dev/null || grep -qF "$BASH_PREFIX" "$BASHRC" 2>/dev/null; then
|
|
27
|
+
echo "✅ PATH already configured in $BASHRC"
|
|
28
|
+
echo " Run: source ~/.bashrc"
|
|
29
|
+
exit 0
|
|
30
|
+
fi
|
|
31
|
+
|
|
32
|
+
{
|
|
33
|
+
echo ""
|
|
34
|
+
echo "$MARKER"
|
|
35
|
+
echo "$EXPORT_LINE"
|
|
36
|
+
} >> "$BASHRC"
|
|
37
|
+
|
|
38
|
+
echo "✅ Added to $BASHRC:"
|
|
39
|
+
echo " $EXPORT_LINE"
|
|
40
|
+
echo ""
|
|
41
|
+
echo " Now run: source ~/.bashrc"
|
|
42
|
+
echo " Then verify: didev --version"
|