@ngocsangairvds/vsaf 3.2.10 → 3.2.12
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/package.json
CHANGED
package/src/global.js
CHANGED
|
@@ -17,7 +17,10 @@ async function installGlobal() {
|
|
|
17
17
|
installSkills();
|
|
18
18
|
installBinary('gitnexus', () => exec('npm install -g gitnexus@1.6.4-rc.79'));
|
|
19
19
|
setupGitnexusMcp();
|
|
20
|
-
|
|
20
|
+
const isWin = process.platform === 'win32';
|
|
21
|
+
installBinary('uv', () => isWin
|
|
22
|
+
? exec('powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"')
|
|
23
|
+
: exec('curl -LsSf https://astral.sh/uv/install.sh | sh'));
|
|
21
24
|
await setupVdsScriptsMcp();
|
|
22
25
|
|
|
23
26
|
console.log('\n\x1b[32m\x1b[1m✓ Global infra ready.\x1b[0m\n');
|
|
@@ -74,6 +77,47 @@ function setupGitnexusMcp() {
|
|
|
74
77
|
|
|
75
78
|
|
|
76
79
|
|
|
80
|
+
function installVdsCliwrapper(vdsRoot) {
|
|
81
|
+
const os = require('os');
|
|
82
|
+
const isWin = process.platform === 'win32';
|
|
83
|
+
|
|
84
|
+
if (isWin) {
|
|
85
|
+
const wrapperDir = path.join(os.homedir(), '.local', 'bin');
|
|
86
|
+
const wrapperPath = path.join(wrapperDir, 'vds-cli.cmd');
|
|
87
|
+
fs.mkdirSync(wrapperDir, { recursive: true });
|
|
88
|
+
fs.writeFileSync(wrapperPath, [
|
|
89
|
+
'@echo off',
|
|
90
|
+
`set "ROOT=${vdsRoot}"`,
|
|
91
|
+
`set "VENV=%ROOT%\\.venv"`,
|
|
92
|
+
`if exist "%USERPROFILE%\\.vds\\.env" (`,
|
|
93
|
+
` for /f "usebackq tokens=*" %%a in ("%USERPROFILE%\\.vds\\.env") do set "%%a"`,
|
|
94
|
+
`)`,
|
|
95
|
+
`"%VENV%\\Scripts\\vds-cli.exe" %*`,
|
|
96
|
+
].join('\r\n'));
|
|
97
|
+
ok(`vds-cli wrapper → ${wrapperPath}`);
|
|
98
|
+
const inPath = (process.env.PATH || '').split(';').some(p => p.toLowerCase() === wrapperDir.toLowerCase());
|
|
99
|
+
if (!inPath) warn(`Thêm vào PATH: ${wrapperDir}`);
|
|
100
|
+
} else {
|
|
101
|
+
const wrapperDir = path.join(os.homedir(), '.local', 'bin');
|
|
102
|
+
const wrapperPath = path.join(wrapperDir, 'vds-cli');
|
|
103
|
+
fs.mkdirSync(wrapperDir, { recursive: true });
|
|
104
|
+
fs.writeFileSync(wrapperPath, [
|
|
105
|
+
'#!/usr/bin/env bash',
|
|
106
|
+
'set -euo pipefail',
|
|
107
|
+
`ROOT="${vdsRoot}"`,
|
|
108
|
+
'VENV="$ROOT/.venv"',
|
|
109
|
+
'if [[ -n "${VIRTUAL_ENV:-}" && "${VIRTUAL_ENV}" != "$VENV" ]]; then unset VIRTUAL_ENV; fi',
|
|
110
|
+
'unset UV_PROJECT_ENVIRONMENT CONDA_PREFIX 2>/dev/null || true',
|
|
111
|
+
'if [[ -f "$HOME/.vds/.env" ]]; then set -a; source "$HOME/.vds/.env"; set +a; fi',
|
|
112
|
+
'exec "$VENV/bin/vds-cli" "$@"',
|
|
113
|
+
].join('\n') + '\n');
|
|
114
|
+
fs.chmodSync(wrapperPath, 0o755);
|
|
115
|
+
ok(`vds-cli wrapper → ${wrapperPath}`);
|
|
116
|
+
const inPath = (process.env.PATH || '').split(':').includes(wrapperDir);
|
|
117
|
+
if (!inPath) warn(`Thêm vào ~/.bashrc hoặc ~/.zshrc: export PATH="$HOME/.local/bin:$PATH"`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
77
121
|
async function setupVdsScriptsMcp() {
|
|
78
122
|
step('VDS Scripts MCP');
|
|
79
123
|
|
|
@@ -93,7 +137,18 @@ async function setupVdsScriptsMcp() {
|
|
|
93
137
|
|
|
94
138
|
fs.mkdirSync(path.dirname(destDir), { recursive: true });
|
|
95
139
|
copyDir(srcDir, destDir);
|
|
96
|
-
ok('
|
|
140
|
+
ok('Đã sao chép vds-scripts.');
|
|
141
|
+
|
|
142
|
+
info('Đang khởi tạo môi trường Python (uv sync)...');
|
|
143
|
+
const syncOk = exec(`uv sync --frozen --package vds-cli --project "${destDir}"`, { silent: true })
|
|
144
|
+
|| exec(`uv sync --package vds-cli --project "${destDir}"`, { silent: true });
|
|
145
|
+
if (syncOk) {
|
|
146
|
+
ok('Môi trường Python đã sẵn sàng.');
|
|
147
|
+
} else {
|
|
148
|
+
warn('uv sync thất bại — vds-cli có thể chưa sẵn sàng');
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
installVdsCliwrapper(destDir);
|
|
97
152
|
|
|
98
153
|
step('Cấu hình VDS CLI và Credentials');
|
|
99
154
|
const envDir = path.join(require('os').homedir(), '.vds');
|
|
@@ -131,7 +186,8 @@ async function setupVdsScriptsMcp() {
|
|
|
131
186
|
ok('Đã tìm thấy file cấu hình ~/.vds/.env');
|
|
132
187
|
}
|
|
133
188
|
|
|
134
|
-
|
|
189
|
+
exec('claude mcp remove vds-orchestrator', { silent: true });
|
|
190
|
+
const cmd = `claude mcp add vds-orchestrator --scope user -e VDS_SCRIPTS_ROOT="${destDir}" -- uv run --project "${mcpDir}" vds-mcp-server`;
|
|
135
191
|
|
|
136
192
|
if (exec(cmd)) {
|
|
137
193
|
ok('VDS Scripts MCP đã được cấu hình thành công');
|
package/src/utils.js
CHANGED
|
@@ -18,7 +18,10 @@ function hasCommand(cmd) {
|
|
|
18
18
|
if (versionCheck.status === 0) return true;
|
|
19
19
|
|
|
20
20
|
// Fallback: check if command exists on PATH
|
|
21
|
-
const
|
|
21
|
+
const isWin = process.platform === 'win32';
|
|
22
|
+
const pathCheck = isWin
|
|
23
|
+
? spawnSync('where', [cmd], { stdio: 'ignore', shell: false })
|
|
24
|
+
: spawnSync('sh', ['-c', `command -v "${cmd}"`], { stdio: 'ignore', shell: false });
|
|
22
25
|
return pathCheck.status === 0;
|
|
23
26
|
}
|
|
24
27
|
|
|
@@ -73,6 +76,7 @@ function cleanStaleWal() {
|
|
|
73
76
|
|
|
74
77
|
function getPlatform() {
|
|
75
78
|
if (process.platform === 'darwin') return 'macos';
|
|
79
|
+
if (process.platform === 'win32') return 'windows';
|
|
76
80
|
return 'linux';
|
|
77
81
|
}
|
|
78
82
|
|
|
@@ -222,29 +222,31 @@ class ConfluenceClient:
|
|
|
222
222
|
client_cls = AtlassianConfluenceCloud if self._is_cloud else AtlassianConfluenceServer
|
|
223
223
|
|
|
224
224
|
# Configure authentication based on available credentials
|
|
225
|
+
# Token (Bearer/PAT) takes priority over username+password to avoid 401s
|
|
226
|
+
# when Basic auth is disabled on the server.
|
|
225
227
|
auth_kwargs: dict[str, Any] = {"url": base_url, "timeout": self._timeout}
|
|
226
228
|
if self._is_cloud:
|
|
227
|
-
if
|
|
229
|
+
if token:
|
|
230
|
+
auth_kwargs["token"] = token
|
|
231
|
+
elif settings.username and settings.password:
|
|
228
232
|
auth_kwargs["username"] = settings.username
|
|
229
233
|
auth_kwargs["password"] = resolve_secret(settings.password)
|
|
230
|
-
elif token:
|
|
231
|
-
auth_kwargs["token"] = token
|
|
232
234
|
else:
|
|
233
235
|
raise AuthError(
|
|
234
236
|
f"No credentials available for cloud server '{self._server}'. "
|
|
235
|
-
"Provide
|
|
237
|
+
"Provide an API token or VDS_USERNAME+VDS_PASSWORD.",
|
|
236
238
|
context={"server": self._server},
|
|
237
239
|
)
|
|
240
|
+
elif token:
|
|
241
|
+
# PATs supported on Confluence Server/Data Center
|
|
242
|
+
auth_kwargs["token"] = token
|
|
238
243
|
elif settings.username and settings.password:
|
|
239
244
|
auth_kwargs["username"] = settings.username
|
|
240
245
|
auth_kwargs["password"] = resolve_secret(settings.password)
|
|
241
|
-
elif token:
|
|
242
|
-
# Recent ConfluenceServer class also supports PATs
|
|
243
|
-
auth_kwargs["token"] = token
|
|
244
246
|
else:
|
|
245
247
|
raise AuthError(
|
|
246
248
|
f"No credentials available for server '{self._server}'. "
|
|
247
|
-
"Provide
|
|
249
|
+
"Provide a CONFLUENCE token or VDS_USERNAME+VDS_PASSWORD.",
|
|
248
250
|
context={"server": self._server},
|
|
249
251
|
)
|
|
250
252
|
client_params = set(self._safe_signature_params(client_cls))
|