@kaitranntt/ccs 4.4.0 → 5.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 +14 -7
- package/VERSION +1 -1
- package/config/base-agy.settings.json +10 -0
- package/config/base-codex.settings.json +10 -0
- package/config/base-gemini.settings.json +10 -0
- package/dist/auth/auth-commands.d.ts +52 -0
- package/dist/auth/auth-commands.d.ts.map +1 -0
- package/dist/auth/auth-commands.js +479 -0
- package/dist/auth/auth-commands.js.map +1 -0
- package/dist/auth/profile-detector.d.ts +68 -0
- package/dist/auth/profile-detector.d.ts.map +1 -0
- package/dist/auth/profile-detector.js +209 -0
- package/dist/auth/profile-detector.js.map +1 -0
- package/dist/auth/profile-registry.d.ts +60 -0
- package/dist/auth/profile-registry.d.ts.map +1 -0
- package/dist/auth/profile-registry.js +188 -0
- package/dist/auth/profile-registry.js.map +1 -0
- package/dist/ccs.d.ts +10 -0
- package/dist/ccs.d.ts.map +1 -0
- package/dist/ccs.js +320 -0
- package/dist/ccs.js.map +1 -0
- package/dist/cliproxy/auth-handler.d.ts +93 -0
- package/dist/cliproxy/auth-handler.d.ts.map +1 -0
- package/dist/cliproxy/auth-handler.js +402 -0
- package/dist/cliproxy/auth-handler.js.map +1 -0
- package/dist/cliproxy/base-config-loader.d.ts +42 -0
- package/dist/cliproxy/base-config-loader.d.ts.map +1 -0
- package/dist/cliproxy/base-config-loader.js +123 -0
- package/dist/cliproxy/base-config-loader.js.map +1 -0
- package/dist/cliproxy/binary-manager.d.ts +104 -0
- package/dist/cliproxy/binary-manager.d.ts.map +1 -0
- package/dist/cliproxy/binary-manager.js +567 -0
- package/dist/cliproxy/binary-manager.js.map +1 -0
- package/dist/cliproxy/cliproxy-executor.d.ts +33 -0
- package/dist/cliproxy/cliproxy-executor.d.ts.map +1 -0
- package/dist/cliproxy/cliproxy-executor.js +297 -0
- package/dist/cliproxy/cliproxy-executor.js.map +1 -0
- package/dist/cliproxy/config-generator.d.ts +89 -0
- package/dist/cliproxy/config-generator.d.ts.map +1 -0
- package/dist/cliproxy/config-generator.js +263 -0
- package/dist/cliproxy/config-generator.js.map +1 -0
- package/dist/cliproxy/index.d.ts +13 -0
- package/dist/cliproxy/index.d.ts.map +1 -0
- package/dist/cliproxy/index.js +62 -0
- package/dist/cliproxy/index.js.map +1 -0
- package/dist/cliproxy/platform-detector.d.ts +48 -0
- package/dist/cliproxy/platform-detector.d.ts.map +1 -0
- package/dist/cliproxy/platform-detector.js +118 -0
- package/dist/cliproxy/platform-detector.js.map +1 -0
- package/dist/cliproxy/types.d.ts +169 -0
- package/dist/cliproxy/types.d.ts.map +1 -0
- package/dist/cliproxy/types.js +7 -0
- package/dist/cliproxy/types.js.map +1 -0
- package/dist/commands/doctor-command.d.ts +10 -0
- package/dist/commands/doctor-command.d.ts.map +1 -0
- package/dist/commands/doctor-command.js +44 -0
- package/dist/commands/doctor-command.js.map +1 -0
- package/dist/commands/help-command.d.ts +5 -0
- package/dist/commands/help-command.d.ts.map +1 -0
- package/dist/commands/help-command.js +104 -0
- package/dist/commands/help-command.js.map +1 -0
- package/dist/commands/install-command.d.ts +14 -0
- package/dist/commands/install-command.d.ts.map +1 -0
- package/dist/commands/install-command.js +39 -0
- package/dist/commands/install-command.js.map +1 -0
- package/dist/commands/shell-completion-command.d.ts +10 -0
- package/dist/commands/shell-completion-command.d.ts.map +1 -0
- package/dist/commands/shell-completion-command.js +85 -0
- package/dist/commands/shell-completion-command.js.map +1 -0
- package/dist/commands/sync-command.d.ts +10 -0
- package/dist/commands/sync-command.d.ts.map +1 -0
- package/dist/commands/sync-command.js +59 -0
- package/dist/commands/sync-command.js.map +1 -0
- package/dist/commands/update-command.d.ts +12 -0
- package/dist/commands/update-command.d.ts.map +1 -0
- package/dist/commands/update-command.js +295 -0
- package/dist/commands/update-command.js.map +1 -0
- package/dist/commands/version-command.d.ts +10 -0
- package/dist/commands/version-command.d.ts.map +1 -0
- package/dist/commands/version-command.js +100 -0
- package/dist/commands/version-command.js.map +1 -0
- package/dist/delegation/delegation-handler.d.ts +60 -0
- package/dist/delegation/delegation-handler.d.ts.map +1 -0
- package/dist/delegation/delegation-handler.js +174 -0
- package/dist/delegation/delegation-handler.js.map +1 -0
- package/dist/delegation/headless-executor.d.ts +114 -0
- package/dist/delegation/headless-executor.d.ts.map +1 -0
- package/dist/delegation/headless-executor.js +562 -0
- package/dist/delegation/headless-executor.js.map +1 -0
- package/dist/delegation/result-formatter.d.ts +108 -0
- package/dist/delegation/result-formatter.d.ts.map +1 -0
- package/dist/delegation/result-formatter.js +391 -0
- package/dist/delegation/result-formatter.js.map +1 -0
- package/dist/delegation/session-manager.d.ts +58 -0
- package/dist/delegation/session-manager.d.ts.map +1 -0
- package/dist/delegation/session-manager.js +153 -0
- package/dist/delegation/session-manager.js.map +1 -0
- package/dist/delegation/settings-parser.d.ts +31 -0
- package/dist/delegation/settings-parser.d.ts.map +1 -0
- package/dist/delegation/settings-parser.js +107 -0
- package/dist/delegation/settings-parser.js.map +1 -0
- package/dist/glmt/delta-accumulator.d.ts +210 -0
- package/dist/glmt/delta-accumulator.d.ts.map +1 -0
- package/dist/glmt/delta-accumulator.js +351 -0
- package/dist/glmt/delta-accumulator.js.map +1 -0
- package/dist/glmt/glmt-proxy.d.ts +72 -0
- package/dist/glmt/glmt-proxy.d.ts.map +1 -0
- package/dist/glmt/glmt-proxy.js +427 -0
- package/dist/glmt/glmt-proxy.js.map +1 -0
- package/dist/glmt/glmt-transformer.d.ts +265 -0
- package/dist/glmt/glmt-transformer.d.ts.map +1 -0
- package/dist/glmt/glmt-transformer.js +832 -0
- package/dist/glmt/glmt-transformer.js.map +1 -0
- package/dist/glmt/locale-enforcer.d.ts +38 -0
- package/dist/glmt/locale-enforcer.d.ts.map +1 -0
- package/dist/glmt/locale-enforcer.js +69 -0
- package/dist/glmt/locale-enforcer.js.map +1 -0
- package/dist/glmt/reasoning-enforcer.d.ts +52 -0
- package/dist/glmt/reasoning-enforcer.d.ts.map +1 -0
- package/dist/glmt/reasoning-enforcer.js +151 -0
- package/dist/glmt/reasoning-enforcer.js.map +1 -0
- package/dist/glmt/sse-parser.d.ts +47 -0
- package/dist/glmt/sse-parser.d.ts.map +1 -0
- package/dist/glmt/sse-parser.js +93 -0
- package/dist/glmt/sse-parser.js.map +1 -0
- package/dist/management/doctor.d.ts +104 -0
- package/dist/management/doctor.d.ts.map +1 -0
- package/dist/management/doctor.js +673 -0
- package/dist/management/doctor.js.map +1 -0
- package/dist/management/instance-manager.d.ts +57 -0
- package/dist/management/instance-manager.d.ts.map +1 -0
- package/dist/management/instance-manager.js +195 -0
- package/dist/management/instance-manager.js.map +1 -0
- package/dist/management/recovery-manager.d.ts +39 -0
- package/dist/management/recovery-manager.d.ts.map +1 -0
- package/dist/management/recovery-manager.js +141 -0
- package/dist/management/recovery-manager.js.map +1 -0
- package/dist/management/shared-manager.d.ts +47 -0
- package/dist/management/shared-manager.d.ts.map +1 -0
- package/dist/management/shared-manager.js +388 -0
- package/dist/management/shared-manager.js.map +1 -0
- package/dist/types/cli.d.ts +50 -0
- package/dist/types/cli.d.ts.map +1 -0
- package/dist/types/cli.js +16 -0
- package/dist/types/cli.js.map +1 -0
- package/dist/types/config.d.ts +51 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +26 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/delegation.d.ts +61 -0
- package/dist/types/delegation.d.ts.map +1 -0
- package/dist/types/delegation.js +6 -0
- package/dist/types/delegation.js.map +1 -0
- package/dist/types/glmt.d.ts +95 -0
- package/dist/types/glmt.d.ts.map +1 -0
- package/dist/types/glmt.js +7 -0
- package/dist/types/glmt.js.map +1 -0
- package/dist/types/index.d.ts +13 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +16 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/utils.d.ts +36 -0
- package/dist/types/utils.d.ts.map +1 -0
- package/dist/types/utils.js +22 -0
- package/dist/types/utils.js.map +1 -0
- package/dist/utils/claude-detector.d.ts +14 -0
- package/dist/utils/claude-detector.d.ts.map +1 -0
- package/dist/utils/claude-detector.js +112 -0
- package/dist/utils/claude-detector.js.map +1 -0
- package/dist/utils/claude-dir-installer.d.ts +46 -0
- package/dist/utils/claude-dir-installer.d.ts.map +1 -0
- package/dist/utils/claude-dir-installer.js +289 -0
- package/dist/utils/claude-dir-installer.js.map +1 -0
- package/dist/utils/claude-symlink-manager.d.ts +61 -0
- package/dist/utils/claude-symlink-manager.d.ts.map +1 -0
- package/dist/utils/claude-symlink-manager.js +291 -0
- package/dist/utils/claude-symlink-manager.js.map +1 -0
- package/dist/utils/config-manager.d.ts +32 -0
- package/dist/utils/config-manager.d.ts.map +1 -0
- package/dist/utils/config-manager.js +143 -0
- package/dist/utils/config-manager.js.map +1 -0
- package/dist/utils/delegation-validator.d.ts +39 -0
- package/dist/utils/delegation-validator.d.ts.map +1 -0
- package/dist/utils/delegation-validator.js +161 -0
- package/dist/utils/delegation-validator.js.map +1 -0
- package/dist/utils/error-codes.d.ts +36 -0
- package/dist/utils/error-codes.d.ts.map +1 -0
- package/dist/utils/error-codes.js +63 -0
- package/dist/utils/error-codes.js.map +1 -0
- package/dist/utils/error-manager.d.ts +59 -0
- package/dist/utils/error-manager.d.ts.map +1 -0
- package/dist/utils/error-manager.js +228 -0
- package/dist/utils/error-manager.js.map +1 -0
- package/dist/utils/helpers.d.ts +27 -0
- package/dist/utils/helpers.d.ts.map +1 -0
- package/dist/utils/helpers.js +150 -0
- package/dist/utils/helpers.js.map +1 -0
- package/dist/utils/package-manager-detector.d.ts +14 -0
- package/dist/utils/package-manager-detector.d.ts.map +1 -0
- package/dist/utils/package-manager-detector.js +162 -0
- package/dist/utils/package-manager-detector.js.map +1 -0
- package/dist/utils/progress-indicator.d.ts +52 -0
- package/dist/utils/progress-indicator.d.ts.map +1 -0
- package/dist/utils/progress-indicator.js +102 -0
- package/dist/utils/progress-indicator.js.map +1 -0
- package/dist/utils/prompt.d.ts +29 -0
- package/dist/utils/prompt.d.ts.map +1 -0
- package/dist/utils/prompt.js +116 -0
- package/dist/utils/prompt.js.map +1 -0
- package/dist/utils/shell-completion.d.ts +52 -0
- package/dist/utils/shell-completion.d.ts.map +1 -0
- package/dist/utils/shell-completion.js +231 -0
- package/dist/utils/shell-completion.js.map +1 -0
- package/dist/utils/shell-executor.d.ts +15 -0
- package/dist/utils/shell-executor.d.ts.map +1 -0
- package/dist/utils/shell-executor.js +57 -0
- package/dist/utils/shell-executor.js.map +1 -0
- package/dist/utils/update-checker.d.ts +48 -0
- package/dist/utils/update-checker.d.ts.map +1 -0
- package/dist/utils/update-checker.js +241 -0
- package/dist/utils/update-checker.js.map +1 -0
- package/lib/ccs +21 -1907
- package/lib/ccs.ps1 +26 -1800
- package/lib/error-codes.ps1 +2 -1
- package/lib/prompt.ps1 +2 -2
- package/package.json +31 -11
- package/scripts/add-shebang.js +39 -0
- package/scripts/bump-version.sh +25 -37
- package/scripts/dev-install.sh +32 -11
- package/scripts/postinstall.js +29 -29
- package/bin/auth/auth-commands.js +0 -499
- package/bin/auth/profile-detector.js +0 -204
- package/bin/auth/profile-registry.js +0 -225
- package/bin/ccs.js +0 -1034
- package/bin/delegation/README.md +0 -191
- package/bin/delegation/delegation-handler.js +0 -212
- package/bin/delegation/headless-executor.js +0 -618
- package/bin/delegation/result-formatter.js +0 -485
- package/bin/delegation/session-manager.js +0 -157
- package/bin/delegation/settings-parser.js +0 -109
- package/bin/glmt/delta-accumulator.js +0 -276
- package/bin/glmt/glmt-proxy.js +0 -495
- package/bin/glmt/glmt-transformer.js +0 -999
- package/bin/glmt/locale-enforcer.js +0 -72
- package/bin/glmt/reasoning-enforcer.js +0 -173
- package/bin/glmt/sse-parser.js +0 -96
- package/bin/management/doctor.js +0 -721
- package/bin/management/instance-manager.js +0 -202
- package/bin/management/recovery-manager.js +0 -135
- package/bin/management/shared-manager.js +0 -402
- package/bin/utils/claude-detector.js +0 -73
- package/bin/utils/claude-dir-installer.js +0 -283
- package/bin/utils/claude-symlink-manager.js +0 -289
- package/bin/utils/config-manager.js +0 -103
- package/bin/utils/delegation-validator.js +0 -154
- package/bin/utils/error-codes.js +0 -59
- package/bin/utils/error-manager.js +0 -165
- package/bin/utils/helpers.js +0 -136
- package/bin/utils/progress-indicator.js +0 -111
- package/bin/utils/prompt.js +0 -134
- package/bin/utils/shell-completion.js +0 -256
- package/bin/utils/update-checker.js +0 -243
package/bin/utils/prompt.js
DELETED
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const readline = require('readline');
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Interactive Prompt Utilities (NO external dependencies)
|
|
7
|
-
*
|
|
8
|
-
* Features:
|
|
9
|
-
* - TTY detection (auto-confirm in non-TTY)
|
|
10
|
-
* - --yes flag support for automation
|
|
11
|
-
* - --no-input flag support for CI
|
|
12
|
-
* - Safe defaults (N for destructive actions)
|
|
13
|
-
* - Input validation with retry
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
class InteractivePrompt {
|
|
17
|
-
/**
|
|
18
|
-
* Ask for confirmation
|
|
19
|
-
* @param {string} message - Confirmation message
|
|
20
|
-
* @param {Object} options - Options
|
|
21
|
-
* @param {boolean} options.default - Default value (true=Yes, false=No)
|
|
22
|
-
* @returns {Promise<boolean>} User confirmation
|
|
23
|
-
*/
|
|
24
|
-
static async confirm(message, options = {}) {
|
|
25
|
-
const { default: defaultValue = false } = options;
|
|
26
|
-
|
|
27
|
-
// Check for --yes flag (automation) - always returns true
|
|
28
|
-
if (process.env.CCS_YES === '1' || process.argv.includes('--yes') || process.argv.includes('-y')) {
|
|
29
|
-
return true;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// Check for --no-input flag (CI)
|
|
33
|
-
if (process.env.CCS_NO_INPUT === '1' || process.argv.includes('--no-input')) {
|
|
34
|
-
throw new Error('Interactive input required but --no-input specified');
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// Non-TTY: use default
|
|
38
|
-
if (!process.stdin.isTTY) {
|
|
39
|
-
return defaultValue;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// Interactive prompt
|
|
43
|
-
const rl = readline.createInterface({
|
|
44
|
-
input: process.stdin,
|
|
45
|
-
output: process.stderr,
|
|
46
|
-
terminal: true
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
const promptText = defaultValue
|
|
50
|
-
? `${message} [Y/n]: `
|
|
51
|
-
: `${message} [y/N]: `;
|
|
52
|
-
|
|
53
|
-
return new Promise((resolve) => {
|
|
54
|
-
rl.question(promptText, (answer) => {
|
|
55
|
-
rl.close();
|
|
56
|
-
|
|
57
|
-
const normalized = answer.trim().toLowerCase();
|
|
58
|
-
|
|
59
|
-
// Empty answer: use default
|
|
60
|
-
if (normalized === '') {
|
|
61
|
-
resolve(defaultValue);
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// Valid answers
|
|
66
|
-
if (normalized === 'y' || normalized === 'yes') {
|
|
67
|
-
resolve(true);
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
if (normalized === 'n' || normalized === 'no') {
|
|
72
|
-
resolve(false);
|
|
73
|
-
return;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// Invalid input: retry
|
|
77
|
-
console.error('[!] Please answer y or n');
|
|
78
|
-
resolve(InteractivePrompt.confirm(message, options));
|
|
79
|
-
});
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Get text input from user
|
|
85
|
-
* @param {string} message - Prompt message
|
|
86
|
-
* @param {Object} options - Options
|
|
87
|
-
* @param {string} options.default - Default value
|
|
88
|
-
* @param {Function} options.validate - Validation function
|
|
89
|
-
* @returns {Promise<string>} User input
|
|
90
|
-
*/
|
|
91
|
-
static async input(message, options = {}) {
|
|
92
|
-
const { default: defaultValue = '', validate = null } = options;
|
|
93
|
-
|
|
94
|
-
// Non-TTY: use default or error
|
|
95
|
-
if (!process.stdin.isTTY) {
|
|
96
|
-
if (defaultValue) {
|
|
97
|
-
return defaultValue;
|
|
98
|
-
}
|
|
99
|
-
throw new Error('Interactive input required but stdin is not a TTY');
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
const rl = readline.createInterface({
|
|
103
|
-
input: process.stdin,
|
|
104
|
-
output: process.stderr,
|
|
105
|
-
terminal: true
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
const promptText = defaultValue
|
|
109
|
-
? `${message} [${defaultValue}]: `
|
|
110
|
-
: `${message}: `;
|
|
111
|
-
|
|
112
|
-
return new Promise((resolve) => {
|
|
113
|
-
rl.question(promptText, (answer) => {
|
|
114
|
-
rl.close();
|
|
115
|
-
|
|
116
|
-
const value = answer.trim() || defaultValue;
|
|
117
|
-
|
|
118
|
-
// Validate input if validator provided
|
|
119
|
-
if (validate) {
|
|
120
|
-
const error = validate(value);
|
|
121
|
-
if (error) {
|
|
122
|
-
console.error(`[!] ${error}`);
|
|
123
|
-
resolve(InteractivePrompt.input(message, options));
|
|
124
|
-
return;
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
resolve(value);
|
|
129
|
-
});
|
|
130
|
-
});
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
module.exports = { InteractivePrompt };
|
|
@@ -1,256 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const fs = require('fs');
|
|
4
|
-
const path = require('path');
|
|
5
|
-
const os = require('os');
|
|
6
|
-
const { execSync } = require('child_process');
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Shell Completion Installer
|
|
10
|
-
* Auto-configures shell completion for bash, zsh, fish, PowerShell
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
class ShellCompletionInstaller {
|
|
14
|
-
constructor() {
|
|
15
|
-
this.homeDir = os.homedir();
|
|
16
|
-
this.ccsDir = path.join(this.homeDir, '.ccs');
|
|
17
|
-
this.completionDir = path.join(this.ccsDir, 'completions');
|
|
18
|
-
this.scriptsDir = path.join(__dirname, '../../scripts/completion');
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Detect current shell
|
|
23
|
-
*/
|
|
24
|
-
detectShell() {
|
|
25
|
-
const shell = process.env.SHELL || '';
|
|
26
|
-
|
|
27
|
-
if (shell.includes('bash')) return 'bash';
|
|
28
|
-
if (shell.includes('zsh')) return 'zsh';
|
|
29
|
-
if (shell.includes('fish')) return 'fish';
|
|
30
|
-
if (process.platform === 'win32') return 'powershell';
|
|
31
|
-
|
|
32
|
-
return null;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Ensure completion files are in ~/.ccs/completions/
|
|
37
|
-
*/
|
|
38
|
-
ensureCompletionFiles() {
|
|
39
|
-
if (!fs.existsSync(this.completionDir)) {
|
|
40
|
-
fs.mkdirSync(this.completionDir, { recursive: true });
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// Copy completion scripts
|
|
44
|
-
const files = ['ccs.bash', 'ccs.zsh', 'ccs.fish', 'ccs.ps1'];
|
|
45
|
-
files.forEach(file => {
|
|
46
|
-
const src = path.join(this.scriptsDir, file);
|
|
47
|
-
const dest = path.join(this.completionDir, file);
|
|
48
|
-
|
|
49
|
-
if (fs.existsSync(src)) {
|
|
50
|
-
fs.copyFileSync(src, dest);
|
|
51
|
-
}
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Safely create directory, checking for file conflicts
|
|
57
|
-
* @param {string} dirPath - Path to create
|
|
58
|
-
* @throws {Error} If path exists but is a file
|
|
59
|
-
*/
|
|
60
|
-
ensureDirectory(dirPath) {
|
|
61
|
-
if (fs.existsSync(dirPath)) {
|
|
62
|
-
const stat = fs.statSync(dirPath);
|
|
63
|
-
if (!stat.isDirectory()) {
|
|
64
|
-
throw new Error(
|
|
65
|
-
`Cannot create directory: ${dirPath} exists but is a file.\n` +
|
|
66
|
-
`Please remove or rename this file and try again.`
|
|
67
|
-
);
|
|
68
|
-
}
|
|
69
|
-
// Directory exists, nothing to do
|
|
70
|
-
return;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// Check parent directories recursively
|
|
74
|
-
const parentDir = path.dirname(dirPath);
|
|
75
|
-
if (parentDir !== dirPath) {
|
|
76
|
-
this.ensureDirectory(parentDir);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// Create the directory
|
|
80
|
-
fs.mkdirSync(dirPath);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Install bash completion
|
|
85
|
-
*/
|
|
86
|
-
installBash() {
|
|
87
|
-
const rcFile = path.join(this.homeDir, '.bashrc');
|
|
88
|
-
const completionPath = path.join(this.completionDir, 'ccs.bash');
|
|
89
|
-
|
|
90
|
-
if (!fs.existsSync(completionPath)) {
|
|
91
|
-
throw new Error('Completion file not found. Please reinstall CCS.');
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
const marker = '# CCS shell completion';
|
|
95
|
-
const sourceCmd = `source "${completionPath}"`;
|
|
96
|
-
const block = `\n${marker}\n${sourceCmd}\n`;
|
|
97
|
-
|
|
98
|
-
// Check if already installed
|
|
99
|
-
if (fs.existsSync(rcFile)) {
|
|
100
|
-
const content = fs.readFileSync(rcFile, 'utf8');
|
|
101
|
-
if (content.includes(marker)) {
|
|
102
|
-
return { success: true, alreadyInstalled: true };
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// Append to .bashrc
|
|
107
|
-
fs.appendFileSync(rcFile, block);
|
|
108
|
-
|
|
109
|
-
return {
|
|
110
|
-
success: true,
|
|
111
|
-
message: `Added to ${rcFile}`,
|
|
112
|
-
reload: 'source ~/.bashrc'
|
|
113
|
-
};
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* Install zsh completion
|
|
118
|
-
*/
|
|
119
|
-
installZsh() {
|
|
120
|
-
const rcFile = path.join(this.homeDir, '.zshrc');
|
|
121
|
-
const completionPath = path.join(this.completionDir, 'ccs.zsh');
|
|
122
|
-
const zshCompDir = path.join(this.homeDir, '.zsh', 'completion');
|
|
123
|
-
|
|
124
|
-
if (!fs.existsSync(completionPath)) {
|
|
125
|
-
throw new Error('Completion file not found. Please reinstall CCS.');
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
// Create zsh completion directory (with file conflict checking)
|
|
129
|
-
this.ensureDirectory(zshCompDir);
|
|
130
|
-
|
|
131
|
-
// Copy to zsh completion directory
|
|
132
|
-
const destFile = path.join(zshCompDir, '_ccs');
|
|
133
|
-
fs.copyFileSync(completionPath, destFile);
|
|
134
|
-
|
|
135
|
-
const marker = '# CCS shell completion';
|
|
136
|
-
const setupCmds = [
|
|
137
|
-
'fpath=(~/.zsh/completion $fpath)',
|
|
138
|
-
'autoload -Uz compinit && compinit'
|
|
139
|
-
];
|
|
140
|
-
const block = `\n${marker}\n${setupCmds.join('\n')}\n`;
|
|
141
|
-
|
|
142
|
-
// Check if already installed
|
|
143
|
-
if (fs.existsSync(rcFile)) {
|
|
144
|
-
const content = fs.readFileSync(rcFile, 'utf8');
|
|
145
|
-
if (content.includes(marker)) {
|
|
146
|
-
return { success: true, alreadyInstalled: true };
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
// Append to .zshrc
|
|
151
|
-
fs.appendFileSync(rcFile, block);
|
|
152
|
-
|
|
153
|
-
return {
|
|
154
|
-
success: true,
|
|
155
|
-
message: `Added to ${rcFile}`,
|
|
156
|
-
reload: 'source ~/.zshrc'
|
|
157
|
-
};
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
/**
|
|
161
|
-
* Install fish completion
|
|
162
|
-
*/
|
|
163
|
-
installFish() {
|
|
164
|
-
const completionPath = path.join(this.completionDir, 'ccs.fish');
|
|
165
|
-
const fishCompDir = path.join(this.homeDir, '.config', 'fish', 'completions');
|
|
166
|
-
|
|
167
|
-
if (!fs.existsSync(completionPath)) {
|
|
168
|
-
throw new Error('Completion file not found. Please reinstall CCS.');
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
// Create fish completion directory (with file conflict checking)
|
|
172
|
-
this.ensureDirectory(fishCompDir);
|
|
173
|
-
|
|
174
|
-
// Copy to fish completion directory (fish auto-loads from here)
|
|
175
|
-
const destFile = path.join(fishCompDir, 'ccs.fish');
|
|
176
|
-
fs.copyFileSync(completionPath, destFile);
|
|
177
|
-
|
|
178
|
-
return {
|
|
179
|
-
success: true,
|
|
180
|
-
message: `Installed to ${destFile}`,
|
|
181
|
-
reload: 'Fish auto-loads completions (no reload needed)'
|
|
182
|
-
};
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
/**
|
|
186
|
-
* Install PowerShell completion
|
|
187
|
-
*/
|
|
188
|
-
installPowerShell() {
|
|
189
|
-
const profilePath = process.env.PROFILE || path.join(
|
|
190
|
-
this.homeDir,
|
|
191
|
-
'Documents',
|
|
192
|
-
'PowerShell',
|
|
193
|
-
'Microsoft.PowerShell_profile.ps1'
|
|
194
|
-
);
|
|
195
|
-
const completionPath = path.join(this.completionDir, 'ccs.ps1');
|
|
196
|
-
|
|
197
|
-
if (!fs.existsSync(completionPath)) {
|
|
198
|
-
throw new Error('Completion file not found. Please reinstall CCS.');
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
const marker = '# CCS shell completion';
|
|
202
|
-
const sourceCmd = `. "${completionPath.replace(/\\/g, '\\\\')}"`;
|
|
203
|
-
const block = `\n${marker}\n${sourceCmd}\n`;
|
|
204
|
-
|
|
205
|
-
// Create profile directory if needed (with file conflict checking)
|
|
206
|
-
const profileDir = path.dirname(profilePath);
|
|
207
|
-
this.ensureDirectory(profileDir);
|
|
208
|
-
|
|
209
|
-
// Check if already installed
|
|
210
|
-
if (fs.existsSync(profilePath)) {
|
|
211
|
-
const content = fs.readFileSync(profilePath, 'utf8');
|
|
212
|
-
if (content.includes(marker)) {
|
|
213
|
-
return { success: true, alreadyInstalled: true };
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
// Append to PowerShell profile
|
|
218
|
-
fs.appendFileSync(profilePath, block);
|
|
219
|
-
|
|
220
|
-
return {
|
|
221
|
-
success: true,
|
|
222
|
-
message: `Added to ${profilePath}`,
|
|
223
|
-
reload: '. $PROFILE'
|
|
224
|
-
};
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
/**
|
|
228
|
-
* Install for detected or specified shell
|
|
229
|
-
*/
|
|
230
|
-
install(shell = null) {
|
|
231
|
-
const targetShell = shell || this.detectShell();
|
|
232
|
-
|
|
233
|
-
if (!targetShell) {
|
|
234
|
-
throw new Error('Could not detect shell. Please specify: --bash, --zsh, --fish, or --powershell');
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
// Ensure completion files exist
|
|
238
|
-
this.ensureCompletionFiles();
|
|
239
|
-
|
|
240
|
-
// Install for target shell
|
|
241
|
-
switch (targetShell) {
|
|
242
|
-
case 'bash':
|
|
243
|
-
return this.installBash();
|
|
244
|
-
case 'zsh':
|
|
245
|
-
return this.installZsh();
|
|
246
|
-
case 'fish':
|
|
247
|
-
return this.installFish();
|
|
248
|
-
case 'powershell':
|
|
249
|
-
return this.installPowerShell();
|
|
250
|
-
default:
|
|
251
|
-
throw new Error(`Unsupported shell: ${targetShell}`);
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
module.exports = { ShellCompletionInstaller };
|
|
@@ -1,243 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const fs = require('fs');
|
|
4
|
-
const path = require('path');
|
|
5
|
-
const os = require('os');
|
|
6
|
-
const https = require('https');
|
|
7
|
-
const { colored } = require('./helpers');
|
|
8
|
-
|
|
9
|
-
const UPDATE_CHECK_FILE = path.join(os.homedir(), '.ccs', 'update-check.json');
|
|
10
|
-
const CHECK_INTERVAL = 24 * 60 * 60 * 1000; // 24 hours
|
|
11
|
-
const GITHUB_API_URL = 'https://api.github.com/repos/kaitranntt/ccs/releases/latest';
|
|
12
|
-
const NPM_REGISTRY_URL = 'https://registry.npmjs.org/@kaitranntt/ccs/latest';
|
|
13
|
-
const REQUEST_TIMEOUT = 5000; // 5 seconds
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Compare semantic versions
|
|
17
|
-
* @param {string} v1 - First version (e.g., "4.1.6")
|
|
18
|
-
* @param {string} v2 - Second version
|
|
19
|
-
* @returns {number} - 1 if v1 > v2, -1 if v1 < v2, 0 if equal
|
|
20
|
-
*/
|
|
21
|
-
function compareVersions(v1, v2) {
|
|
22
|
-
const parts1 = v1.replace(/^v/, '').split('.').map(Number);
|
|
23
|
-
const parts2 = v2.replace(/^v/, '').split('.').map(Number);
|
|
24
|
-
|
|
25
|
-
for (let i = 0; i < 3; i++) {
|
|
26
|
-
const p1 = parts1[i] || 0;
|
|
27
|
-
const p2 = parts2[i] || 0;
|
|
28
|
-
if (p1 > p2) return 1;
|
|
29
|
-
if (p1 < p2) return -1;
|
|
30
|
-
}
|
|
31
|
-
return 0;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Fetch latest version from GitHub releases
|
|
36
|
-
* @returns {Promise<string|null>} - Latest version or null on error
|
|
37
|
-
*/
|
|
38
|
-
function fetchLatestVersionFromGitHub() {
|
|
39
|
-
return new Promise((resolve) => {
|
|
40
|
-
const req = https.get(GITHUB_API_URL, {
|
|
41
|
-
headers: { 'User-Agent': 'CCS-Update-Checker' },
|
|
42
|
-
timeout: REQUEST_TIMEOUT
|
|
43
|
-
}, (res) => {
|
|
44
|
-
let data = '';
|
|
45
|
-
|
|
46
|
-
res.on('data', (chunk) => {
|
|
47
|
-
data += chunk;
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
res.on('end', () => {
|
|
51
|
-
try {
|
|
52
|
-
if (res.statusCode !== 200) {
|
|
53
|
-
resolve(null);
|
|
54
|
-
return;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const release = JSON.parse(data);
|
|
58
|
-
const version = release.tag_name?.replace(/^v/, '') || null;
|
|
59
|
-
resolve(version);
|
|
60
|
-
} catch (err) {
|
|
61
|
-
resolve(null);
|
|
62
|
-
}
|
|
63
|
-
});
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
req.on('error', () => resolve(null));
|
|
67
|
-
req.on('timeout', () => {
|
|
68
|
-
req.destroy();
|
|
69
|
-
resolve(null);
|
|
70
|
-
});
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Fetch latest version from npm registry
|
|
76
|
-
* @returns {Promise<string|null>} - Latest version or null on error
|
|
77
|
-
*/
|
|
78
|
-
function fetchLatestVersionFromNpm() {
|
|
79
|
-
return new Promise((resolve) => {
|
|
80
|
-
const req = https.get(NPM_REGISTRY_URL, {
|
|
81
|
-
headers: { 'User-Agent': 'CCS-Update-Checker' },
|
|
82
|
-
timeout: REQUEST_TIMEOUT
|
|
83
|
-
}, (res) => {
|
|
84
|
-
let data = '';
|
|
85
|
-
|
|
86
|
-
res.on('data', (chunk) => {
|
|
87
|
-
data += chunk;
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
res.on('end', () => {
|
|
91
|
-
try {
|
|
92
|
-
if (res.statusCode !== 200) {
|
|
93
|
-
resolve(null);
|
|
94
|
-
return;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
const packageData = JSON.parse(data);
|
|
98
|
-
const version = packageData.version || null;
|
|
99
|
-
resolve(version);
|
|
100
|
-
} catch (err) {
|
|
101
|
-
resolve(null);
|
|
102
|
-
}
|
|
103
|
-
});
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
req.on('error', () => resolve(null));
|
|
107
|
-
req.on('timeout', () => {
|
|
108
|
-
req.destroy();
|
|
109
|
-
resolve(null);
|
|
110
|
-
});
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* Read update check cache
|
|
116
|
-
* @returns {Object} - Cache object
|
|
117
|
-
*/
|
|
118
|
-
function readCache() {
|
|
119
|
-
try {
|
|
120
|
-
if (!fs.existsSync(UPDATE_CHECK_FILE)) {
|
|
121
|
-
return { last_check: 0, latest_version: null, dismissed_version: null };
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
const data = fs.readFileSync(UPDATE_CHECK_FILE, 'utf8');
|
|
125
|
-
return JSON.parse(data);
|
|
126
|
-
} catch (err) {
|
|
127
|
-
return { last_check: 0, latest_version: null, dismissed_version: null };
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
/**
|
|
132
|
-
* Write update check cache
|
|
133
|
-
* @param {Object} cache - Cache object to write
|
|
134
|
-
*/
|
|
135
|
-
function writeCache(cache) {
|
|
136
|
-
try {
|
|
137
|
-
const ccsDir = path.join(os.homedir(), '.ccs');
|
|
138
|
-
if (!fs.existsSync(ccsDir)) {
|
|
139
|
-
fs.mkdirSync(ccsDir, { recursive: true, mode: 0o700 });
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
fs.writeFileSync(UPDATE_CHECK_FILE, JSON.stringify(cache, null, 2), 'utf8');
|
|
143
|
-
} catch (err) {
|
|
144
|
-
// Silently fail - not critical
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* Check for updates (async, non-blocking)
|
|
150
|
-
* @param {string} currentVersion - Current CCS version
|
|
151
|
-
* @param {boolean} force - Force check even if within interval
|
|
152
|
-
* @param {string} installMethod - Installation method ('npm' or 'direct')
|
|
153
|
-
* @returns {Promise<Object>} - Update result object with status and data
|
|
154
|
-
*/
|
|
155
|
-
async function checkForUpdates(currentVersion, force = false, installMethod = 'direct') {
|
|
156
|
-
const cache = readCache();
|
|
157
|
-
const now = Date.now();
|
|
158
|
-
|
|
159
|
-
// Check if we should check for updates
|
|
160
|
-
if (!force && (now - cache.last_check < CHECK_INTERVAL)) {
|
|
161
|
-
// Use cached result if available
|
|
162
|
-
if (cache.latest_version && compareVersions(cache.latest_version, currentVersion) > 0) {
|
|
163
|
-
// Don't show if user dismissed this version
|
|
164
|
-
if (cache.dismissed_version === cache.latest_version) {
|
|
165
|
-
return { status: 'no_update', reason: 'dismissed' };
|
|
166
|
-
}
|
|
167
|
-
return { status: 'update_available', latest: cache.latest_version, current: currentVersion };
|
|
168
|
-
}
|
|
169
|
-
return { status: 'no_update', reason: 'cached' };
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
// Fetch latest version from appropriate source
|
|
173
|
-
let latestVersion;
|
|
174
|
-
let fetchError = null;
|
|
175
|
-
|
|
176
|
-
if (installMethod === 'npm') {
|
|
177
|
-
latestVersion = await fetchLatestVersionFromNpm();
|
|
178
|
-
if (!latestVersion) fetchError = 'npm_registry_error';
|
|
179
|
-
} else {
|
|
180
|
-
latestVersion = await fetchLatestVersionFromGitHub();
|
|
181
|
-
if (!latestVersion) fetchError = 'github_api_error';
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
// Update cache
|
|
185
|
-
cache.last_check = now;
|
|
186
|
-
if (latestVersion) {
|
|
187
|
-
cache.latest_version = latestVersion;
|
|
188
|
-
}
|
|
189
|
-
writeCache(cache);
|
|
190
|
-
|
|
191
|
-
// Handle fetch errors
|
|
192
|
-
if (fetchError) {
|
|
193
|
-
return {
|
|
194
|
-
status: 'check_failed',
|
|
195
|
-
reason: fetchError,
|
|
196
|
-
message: `Failed to check for updates: ${fetchError.replace(/_/g, ' ')}`
|
|
197
|
-
};
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
// Check if update available
|
|
201
|
-
if (latestVersion && compareVersions(latestVersion, currentVersion) > 0) {
|
|
202
|
-
// Don't show if user dismissed this version
|
|
203
|
-
if (cache.dismissed_version === latestVersion) {
|
|
204
|
-
return { status: 'no_update', reason: 'dismissed' };
|
|
205
|
-
}
|
|
206
|
-
return { status: 'update_available', latest: latestVersion, current: currentVersion };
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
return { status: 'no_update', reason: 'latest' };
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
/**
|
|
213
|
-
* Show update notification
|
|
214
|
-
* @param {Object} updateInfo - Update information
|
|
215
|
-
*/
|
|
216
|
-
function showUpdateNotification(updateInfo) {
|
|
217
|
-
console.log('');
|
|
218
|
-
console.log(colored('═══════════════════════════════════════════════════════', 'cyan'));
|
|
219
|
-
console.log(colored(` Update available: ${updateInfo.current} → ${updateInfo.latest}`, 'yellow'));
|
|
220
|
-
console.log(colored('═══════════════════════════════════════════════════════', 'cyan'));
|
|
221
|
-
console.log('');
|
|
222
|
-
console.log(` Run ${colored('ccs update', 'yellow')} to update`);
|
|
223
|
-
console.log('');
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
/**
|
|
227
|
-
* Dismiss update notification for a specific version
|
|
228
|
-
* @param {string} version - Version to dismiss
|
|
229
|
-
*/
|
|
230
|
-
function dismissUpdate(version) {
|
|
231
|
-
const cache = readCache();
|
|
232
|
-
cache.dismissed_version = version;
|
|
233
|
-
writeCache(cache);
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
module.exports = {
|
|
237
|
-
compareVersions,
|
|
238
|
-
checkForUpdates,
|
|
239
|
-
showUpdateNotification,
|
|
240
|
-
dismissUpdate,
|
|
241
|
-
readCache,
|
|
242
|
-
writeCache
|
|
243
|
-
};
|