cloud-pc-templates 1.2.2 → 1.3.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 +45 -1
- package/handlers/huggingface.js +169 -0
- package/handlers/ollamalocal.js +1 -1
- package/index.js +8 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -114,6 +114,36 @@ $ npx cloud-pc-templates ai login loginMode ollamalocal
|
|
|
114
114
|
- Runs proxy on port 3005
|
|
115
115
|
- Provides detailed status output
|
|
116
116
|
|
|
117
|
+
##### Hugging Face Login
|
|
118
|
+
|
|
119
|
+
Connect to Hugging Face services:
|
|
120
|
+
```bash
|
|
121
|
+
npx cloud-pc-templates ai login loginMode huggingface
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
**What it does:**
|
|
125
|
+
1. Prompts you to enter your Hugging Face API Key (masked input with asterisks)
|
|
126
|
+
2. Downloads the Hugging Face proxy script from GitHub
|
|
127
|
+
3. Runs the proxy on port 3006 with your API key
|
|
128
|
+
4. Validates the proxy health endpoint
|
|
129
|
+
5. Displays "Logged in" confirmation
|
|
130
|
+
|
|
131
|
+
**Example:**
|
|
132
|
+
```bash
|
|
133
|
+
$ npx cloud-pc-templates ai login loginMode huggingface
|
|
134
|
+
Enter Hugging Face API Key: ****************************
|
|
135
|
+
✓ Logged in
|
|
136
|
+
- Endpoint checked: http://localhost:3006/health
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
**Features:**
|
|
140
|
+
- Masked input for API key (shows `*` instead of actual characters)
|
|
141
|
+
- Supports pasting long API keys
|
|
142
|
+
- Backspace support for corrections
|
|
143
|
+
- Runs proxy on port 3006
|
|
144
|
+
- Real-time proxy output logging for debugging
|
|
145
|
+
- Get your API key from: https://huggingface.co/settings/tokens
|
|
146
|
+
|
|
117
147
|
### Command Discovery
|
|
118
148
|
|
|
119
149
|
The CLI features intelligent command discovery. If you don't provide all required arguments, it shows available options:
|
|
@@ -146,6 +176,7 @@ cloud-pc-templates/
|
|
|
146
176
|
├── handlers/
|
|
147
177
|
│ ├── ollamacloud.js # Ollama Cloud login functionality
|
|
148
178
|
│ ├── ollamalocal.js # Ollama Local login functionality
|
|
179
|
+
│ ├── huggingface.js # Hugging Face login functionality
|
|
149
180
|
│ └── launch.js # Website launcher
|
|
150
181
|
├── package.json # Project metadata and bin configuration
|
|
151
182
|
└── README.md # This file
|
|
@@ -170,6 +201,12 @@ cloud-pc-templates/
|
|
|
170
201
|
- `checkProxyHealth()`: Health check for the offline proxy
|
|
171
202
|
- `checkAndLoginOllamaLocal()`: Main login orchestrator with warning system
|
|
172
203
|
|
|
204
|
+
#### handlers/huggingface.js
|
|
205
|
+
- `promptForApiKey()`: Interactive masked API key input
|
|
206
|
+
- `checkHealthEndpoint()`: Health check for proxy server
|
|
207
|
+
- `downloadAndRunProxy()`: Downloads and executes proxy script with API key
|
|
208
|
+
- `checkAndLoginHuggingFace()`: Main login orchestrator
|
|
209
|
+
|
|
173
210
|
#### handlers/launch.js
|
|
174
211
|
- `openBrowser()`: Cross-platform browser launcher
|
|
175
212
|
- `launchWebsite()`: Opens cloud-pc-templates.com
|
|
@@ -288,10 +325,17 @@ When entering your API key:
|
|
|
288
325
|
- Start Ollama with: `ollama serve`
|
|
289
326
|
- Check if Ollama is running on port 11434:
|
|
290
327
|
```bash
|
|
291
|
-
curl http://localhost:11434/api/
|
|
328
|
+
curl http://localhost:11434/api/tags
|
|
292
329
|
```
|
|
293
330
|
- Ensure port 3005 is not in use by another application
|
|
294
331
|
|
|
332
|
+
### Hugging Face login fails
|
|
333
|
+
- Check that you have a valid Hugging Face API key
|
|
334
|
+
- Get your API key from: https://huggingface.co/settings/tokens
|
|
335
|
+
- Make sure your API key has the necessary permissions
|
|
336
|
+
- Ensure port 3006 is not in use by another application
|
|
337
|
+
- Check your internet connection for accessing Hugging Face services
|
|
338
|
+
|
|
295
339
|
### Browser won't open with `launch`
|
|
296
340
|
- Ensure you have a default browser configured
|
|
297
341
|
- On Linux, make sure `xdg-open` is installed: `sudo apt-get install xdg-utils`
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
const http = require('http');
|
|
2
|
+
const https = require('https');
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const { spawn } = require('child_process');
|
|
6
|
+
const os = require('os');
|
|
7
|
+
|
|
8
|
+
const PROXY_PORT = 3003;
|
|
9
|
+
|
|
10
|
+
// Function to get masked API key input
|
|
11
|
+
function promptForApiKey() {
|
|
12
|
+
return new Promise((resolve) => {
|
|
13
|
+
process.stdout.write('Enter Hugging Face API Key: ');
|
|
14
|
+
|
|
15
|
+
const stdin = process.stdin;
|
|
16
|
+
|
|
17
|
+
// Handle both TTY and non-TTY environments
|
|
18
|
+
if (stdin.isTTY) {
|
|
19
|
+
stdin.setRawMode(true);
|
|
20
|
+
}
|
|
21
|
+
stdin.resume();
|
|
22
|
+
|
|
23
|
+
let apiKey = '';
|
|
24
|
+
|
|
25
|
+
stdin.on('data', (buffer) => {
|
|
26
|
+
const chunk = buffer.toString();
|
|
27
|
+
|
|
28
|
+
// Process each character in the chunk (handles pasted text)
|
|
29
|
+
for (let i = 0; i < chunk.length; i++) {
|
|
30
|
+
const char = chunk[i];
|
|
31
|
+
|
|
32
|
+
if (char === '\n' || char === '\r' || char === '\u0004') {
|
|
33
|
+
// Enter or EOF
|
|
34
|
+
if (stdin.isTTY) {
|
|
35
|
+
stdin.setRawMode(false);
|
|
36
|
+
}
|
|
37
|
+
stdin.pause();
|
|
38
|
+
stdin.removeAllListeners('data');
|
|
39
|
+
console.log('');
|
|
40
|
+
resolve(apiKey);
|
|
41
|
+
return;
|
|
42
|
+
} else if (char === '\u0003') {
|
|
43
|
+
// Ctrl+C
|
|
44
|
+
if (stdin.isTTY) {
|
|
45
|
+
stdin.setRawMode(false);
|
|
46
|
+
}
|
|
47
|
+
process.exit();
|
|
48
|
+
} else if (char === '\x7f' || char === '\b') {
|
|
49
|
+
// Backspace
|
|
50
|
+
if (apiKey.length > 0) {
|
|
51
|
+
apiKey = apiKey.slice(0, -1);
|
|
52
|
+
process.stdout.write('\x1b[D\x1b[K');
|
|
53
|
+
}
|
|
54
|
+
} else if (char >= '\x20' && char <= '\x7e') {
|
|
55
|
+
// Printable character
|
|
56
|
+
apiKey += char;
|
|
57
|
+
process.stdout.write('*');
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Function to check health endpoint
|
|
65
|
+
function checkHealthEndpoint(endpoint) {
|
|
66
|
+
return new Promise((resolve) => {
|
|
67
|
+
const url = new URL(endpoint);
|
|
68
|
+
const protocol = url.protocol === 'https:' ? https : http;
|
|
69
|
+
|
|
70
|
+
const request = protocol.request(url, { method: 'GET' }, (res) => {
|
|
71
|
+
resolve(res.statusCode === 200);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
request.on('error', () => {
|
|
75
|
+
resolve(false);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
request.end();
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Function to download and run the proxy
|
|
83
|
+
async function downloadAndRunProxy(endpoint) {
|
|
84
|
+
const url = 'https://raw.githubusercontent.com/devashish234073/cloud-pc-templates-marketplace/refs/heads/main/JS-PROXIES/hf-proxy.js';
|
|
85
|
+
const tempFile = path.join(os.tmpdir(), 'hf-proxy.js');
|
|
86
|
+
|
|
87
|
+
// Download the file
|
|
88
|
+
await new Promise((resolve, reject) => {
|
|
89
|
+
const file = fs.createWriteStream(tempFile);
|
|
90
|
+
https.get(url, (res) => {
|
|
91
|
+
res.pipe(file);
|
|
92
|
+
file.on('finish', () => {
|
|
93
|
+
file.close();
|
|
94
|
+
resolve();
|
|
95
|
+
});
|
|
96
|
+
}).on('error', reject);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
// Get API key from user
|
|
100
|
+
const apiKey = await promptForApiKey();
|
|
101
|
+
|
|
102
|
+
// Run the proxy with API key passed as command-line argument
|
|
103
|
+
return new Promise((resolve, reject) => {
|
|
104
|
+
const child = spawn('node', [tempFile, apiKey]);
|
|
105
|
+
|
|
106
|
+
let serverReady = false;
|
|
107
|
+
|
|
108
|
+
// Capture stdout to detect when server is ready
|
|
109
|
+
child.stdout.on('data', (data) => {
|
|
110
|
+
const output = data.toString();
|
|
111
|
+
console.log(output);
|
|
112
|
+
|
|
113
|
+
// Check if server indicates it's ready
|
|
114
|
+
if (output.includes('listening') || output.includes('started') || output.includes('running')) {
|
|
115
|
+
serverReady = true;
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
// Capture stderr for error messages
|
|
120
|
+
child.stderr.on('data', (data) => {
|
|
121
|
+
console.error(data.toString());
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
// Wait a bit for server to start, then validate
|
|
125
|
+
setTimeout(async () => {
|
|
126
|
+
try {
|
|
127
|
+
const isHealthy = await checkHealthEndpoint(endpoint);
|
|
128
|
+
if (isHealthy) {
|
|
129
|
+
console.log('✓ Logged in');
|
|
130
|
+
console.log(` - Endpoint checked: ${endpoint}`);
|
|
131
|
+
} else {
|
|
132
|
+
console.log('✓ Proxy started');
|
|
133
|
+
console.log(` - Endpoint: ${endpoint}`);
|
|
134
|
+
}
|
|
135
|
+
resolve();
|
|
136
|
+
} catch (error) {
|
|
137
|
+
reject(error);
|
|
138
|
+
}
|
|
139
|
+
}, 2000);
|
|
140
|
+
|
|
141
|
+
child.on('error', reject);
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Function to check and login to Hugging Face
|
|
146
|
+
async function checkAndLoginHuggingFace() {
|
|
147
|
+
const endpoint = `http://localhost:${PROXY_PORT}/health`;
|
|
148
|
+
|
|
149
|
+
try {
|
|
150
|
+
const isHealthy = await checkHealthEndpoint(endpoint);
|
|
151
|
+
if (isHealthy) {
|
|
152
|
+
console.log('✓ Already logged in');
|
|
153
|
+
console.log(` - Endpoint checked: ${endpoint}`);
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Not healthy, download and run proxy
|
|
158
|
+
await downloadAndRunProxy(endpoint);
|
|
159
|
+
} catch (error) {
|
|
160
|
+
console.error('Error during login:', error.message);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
module.exports = {
|
|
165
|
+
checkAndLoginHuggingFace,
|
|
166
|
+
checkHealthEndpoint,
|
|
167
|
+
downloadAndRunProxy,
|
|
168
|
+
promptForApiKey
|
|
169
|
+
};
|
package/handlers/ollamalocal.js
CHANGED
package/index.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const { checkAndLoginOllamaCloud } = require('./handlers/ollamacloud');
|
|
4
4
|
const { checkAndLoginOllamaLocal } = require('./handlers/ollamalocal');
|
|
5
|
+
const { checkAndLoginHuggingFace } = require('./handlers/huggingface');
|
|
5
6
|
const { launchWebsite } = require('./handlers/launch');
|
|
6
7
|
|
|
7
8
|
// Command tree structure
|
|
@@ -27,6 +28,10 @@ const commandTree = {
|
|
|
27
28
|
ollamalocal: {
|
|
28
29
|
description: 'Connect to Ollama Local',
|
|
29
30
|
handler: () => aiLogin('ollamalocal')
|
|
31
|
+
},
|
|
32
|
+
huggingface: {
|
|
33
|
+
description: 'Connect to Hugging Face',
|
|
34
|
+
handler: () => aiLogin('huggingface')
|
|
30
35
|
}
|
|
31
36
|
}
|
|
32
37
|
}
|
|
@@ -54,6 +59,7 @@ function help() {
|
|
|
54
59
|
console.log('AI Commands:');
|
|
55
60
|
console.log(' npx cloud-pc-templates ai login loginMode ollamacloud');
|
|
56
61
|
console.log(' npx cloud-pc-templates ai login loginMode ollamalocal');
|
|
62
|
+
console.log(' npx cloud-pc-templates ai login loginMode huggingface');
|
|
57
63
|
}
|
|
58
64
|
|
|
59
65
|
// Default AI function
|
|
@@ -67,6 +73,8 @@ async function aiLogin(mode) {
|
|
|
67
73
|
await checkAndLoginOllamaCloud();
|
|
68
74
|
} else if (mode === 'ollamalocal') {
|
|
69
75
|
await checkAndLoginOllamaLocal();
|
|
76
|
+
} else if (mode === 'huggingface') {
|
|
77
|
+
await checkAndLoginHuggingFace();
|
|
70
78
|
}
|
|
71
79
|
}
|
|
72
80
|
|