clarity-ai 6.4.1 → 6.5.1

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/CHANGELOG.md CHANGED
@@ -2,6 +2,23 @@
2
2
 
3
3
  ---
4
4
 
5
+ ## 6.5.0 (2026-06-06)
6
+
7
+ ### Closed Source + Space Proxy
8
+ - All tokens removed from source code — zero hardcoded secrets
9
+ - `LICENSE`: Proprietary, all rights reserved (`UNLICENSED`)
10
+ - Provider now points to `Clarity-main` Space endpoint (`*.hf.space`) instead of `api-inference.huggingface.co` — fixes DNS resolution issues on Termux/Android
11
+ - Clarity-main Space runs inference proxy: forwards to HF Inference API using internal `HF_TOKEN` secret
12
+ - No API key required from CLI — works out of the box on any network
13
+ - Space app: `space_app.py` — Gradio + FastAPI, `/v1/chat/completions` streaming, `/main-data` data endpoint
14
+
15
+ ## 6.4.2 (2026-06-06)
16
+
17
+ ### Keyless Clarity Flash
18
+ - HuggingFace provider no longer requires API key
19
+ - Built-in HF token for Clarity Flash model — works out of the box, no setup
20
+ - Can still override with `HF_TOKEN` env var or `/keys huggingface <token>`
21
+
5
22
  ## 6.4.1 (2026-06-06)
6
23
 
7
24
  ### Clarity Flash 14B Model
package/LICENSE ADDED
@@ -0,0 +1,12 @@
1
+ CLARITY AI — Proprietary Software
2
+
3
+ Copyright (c) 2026 Universal-618
4
+
5
+ All rights reserved.
6
+
7
+ This software and its source code are proprietary and confidential.
8
+ Unauthorized copying, modification, distribution, or use of this
9
+ software, via any medium, is strictly prohibited without prior
10
+ written permission from the copyright holder.
11
+
12
+ This software is provided "as is", without warranty of any kind.
package/README.md CHANGED
@@ -103,16 +103,10 @@ clarity /bash ls -la
103
103
  | Gemini 2.0 Flash | Google | 32K (fast) |
104
104
  | DeepSeek R1 Free | OpenRouter | 128K |
105
105
 
106
- ## Provider Comparison
106
+ ## Architecture
107
107
 
108
- | Provider | Free Tier | Streaming | Priority |
109
- |---|---|---|---|
110
- | Groq | ✓ | ✓ | 1 (fastest) |
111
- | Google Gemini | ✓ | ✓ | 2 |
112
- | HuggingFace (Clarity Flash) | Needs HF_TOKEN | ✓ | 3 |
113
- | DeepSeek | Cheap | ✓ | 4 |
114
- | OpenRouter | ✓ | ✓ | 5 |
108
+ Clarity Flash 14B is served via `Clarity-main` HF Space — a streaming inference proxy at `*.hf.space/v1/chat/completions`. No API keys needed.
115
109
 
116
110
  ## License
117
111
 
118
- MIT
112
+ Proprietary — all rights reserved. See [LICENSE](LICENSE).
package/package.json CHANGED
@@ -1,17 +1,23 @@
1
1
  {
2
2
  "name": "clarity-ai",
3
- "version": "6.4.1",
4
- "description": "Premium terminal AI agent Clarity Flash 14B model, HF Inference API, fixed-height viewport, TrueColor theme",
3
+ "version": "6.5.1",
4
+ "description": "CLARITY terminal AI agent with Clarity Flash 14B",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "clarity": "bin/clarity.js"
8
8
  },
9
9
  "scripts": {
10
- "start": "node bin/clarity.js"
10
+ "start": "node bin/clarity.js",
11
+ "postinstall": "node scripts/postinstall.js"
11
12
  },
12
13
  "engines": {
13
14
  "node": ">=18.0.0"
14
15
  },
16
+ "license": "UNLICENSED",
17
+ "private": false,
18
+ "publishConfig": {
19
+ "access": "public"
20
+ },
15
21
  "dependencies": {
16
22
  "ink": "^5",
17
23
  "react": "^18",
@@ -0,0 +1,3 @@
1
+ fastapi>=0.100
2
+ httpx>=0.27
3
+ uvicorn>=0.20
@@ -1,59 +1,36 @@
1
- import figlet from 'figlet';
2
- import gradient from 'gradient-string';
3
- import chalk from 'chalk';
4
-
5
- const GRADIENT = gradient(['#00d2ff', '#7b2ff7']);
6
-
7
- try {
8
- const text = figlet.textSync('CLARITY', { font: 'ANSI Shadow' });
9
- console.log(GRADIENT(text));
10
- } catch {
11
- console.log(GRADIENT('CLARITY'));
12
- }
13
-
14
- const nodeVersion = process.versions.node;
15
- const [major] = nodeVersion.split('.').map(Number);
16
- const W = process.stdout.columns || 80;
17
- const line = '═'.repeat(W - 4);
1
+ import { existsSync, chmodSync, writeFileSync, unlinkSync, lstatSync } from 'fs';
2
+ import { resolve } from 'path';
18
3
 
4
+ const nodeVer = process.versions.node;
5
+ const [major] = nodeVer.split('.').map(Number);
19
6
  if (major < 18) {
20
- console.error();
21
- console.error(chalk.hex('#ff4466')(` ╔${line}╗`));
22
- console.error(chalk.hex('#ff4466')(` ║ ✗ Node.js 18+ required. You have v${nodeVersion}`));
23
- console.error(chalk.hex('#ffcc00')(` ║ Termux: pkg install nodejs-lts`));
24
- console.error(chalk.hex('#ff4466')(` ╚${line}╝`));
25
- console.error();
7
+ console.error('\n \u2717 Node.js 18+ required. You have v' + nodeVer);
8
+ console.error(' Termux: pkg install nodejs-lts\n');
26
9
  process.exit(1);
27
10
  }
28
11
 
29
12
  const isTermux = process.env.PREFIX?.includes('com.termux');
13
+ const W = process.stdout.columns || 80;
14
+ const line = '\u2500'.repeat(Math.min(W - 4, 60));
30
15
 
31
- console.log();
32
- console.log(chalk.hex('#00ff88')(` ╔${line}╗`));
33
- console.log(chalk.hex('#00ff88')(` CLARITY installed successfully!`));
34
- console.log(chalk.hex('#00d2ff')(` ║ Run: clarity init`));
35
- console.log(chalk.hex('#00ff88')(` ╚${line}╝`));
36
- console.log();
37
- console.log(chalk.hex('#666888')(" Run 'clarity init' to configure your AI keys and get started."));
16
+ console.log(`\n \u250C${line}\u2510`);
17
+ console.log(` \u2502 CLARITY installed`);
18
+ console.log(` \u2502 Run: clarity init`);
19
+ console.log(` \u2514${line}\u2518\n`);
38
20
 
39
21
  const binDir = process.env.npm_config_prefix ? `${process.env.npm_config_prefix}/bin` : null;
40
22
  if (isTermux && binDir) {
41
- const { existsSync, writeFileSync, chmodSync, unlinkSync, lstatSync } = await import('fs');
42
- const { resolve } = await import('path');
43
23
  const symlinkPath = resolve(binDir, 'clarity');
44
-
45
24
  try {
46
25
  if (existsSync(symlinkPath)) {
47
26
  const stat = lstatSync(symlinkPath);
48
- if (stat.isSymbolicLink()) {
49
- unlinkSync(symlinkPath);
50
- }
27
+ if (stat.isSymbolicLink()) unlinkSync(symlinkPath);
51
28
  }
52
- const clarityPkgDir = process.env.PREFIX ? `${process.env.PREFIX}/lib/node_modules/clarity-ai` : resolve(process.cwd());
53
- writeFileSync(symlinkPath, `#!/data/data/com.termux/files/usr/bin/bash\nexec node "${clarityPkgDir}/bin/clarity.js" "$@"\n`);
29
+ const pkgDir = process.env.PREFIX
30
+ ? `${process.env.PREFIX}/lib/node_modules/clarity-ai`
31
+ : resolve(process.cwd());
32
+ writeFileSync(symlinkPath, `#!/data/data/com.termux/files/usr/bin/bash\nexec node "${pkgDir}/bin/clarity.js" "$@"\n`);
54
33
  chmodSync(symlinkPath, '755');
55
- console.log(chalk.hex('#00ff88')(' Termux wrapper created at:'), chalk.hex('#00d2ff')(symlinkPath));
56
- } catch (e) {
57
- console.error(chalk.hex('#ff4466')(' ✗ Failed to create Termux wrapper:'), e.message);
58
- }
34
+ console.log(' \u2713 Termux wrapper created');
35
+ } catch {}
59
36
  }
package/space_app.py ADDED
@@ -0,0 +1,45 @@
1
+ import os, json, asyncio
2
+ import httpx
3
+ from fastapi import FastAPI, Request
4
+ from fastapi.responses import StreamingResponse, JSONResponse
5
+ from contextlib import asynccontextmanager
6
+
7
+ HF_TOKEN = os.environ.get('HF_TOKEN', '')
8
+ MODEL = os.environ.get('HF_MODEL', 'Universal-618/Clarity-flash-weights')
9
+ API = f'https://api-inference.huggingface.co/models/{MODEL}/v1/chat/completions'
10
+ HEADERS = {'Authorization': f'Bearer {HF_TOKEN}', 'Content-Type': 'application/json'}
11
+
12
+ app = FastAPI()
13
+
14
+ @app.post('/v1/chat/completions')
15
+ async def proxy(request: Request):
16
+ body = await request.json()
17
+ body['model'] = MODEL
18
+ stream = body.get('stream', True)
19
+ body['stream'] = stream
20
+ async with httpx.AsyncClient(timeout=120) as client:
21
+ resp = await client.post(API, headers=HEADERS, json=body)
22
+ if resp.status_code != 200:
23
+ return JSONResponse({'error': await resp.aread()}, status_code=resp.status_code)
24
+ if stream:
25
+ return StreamingResponse(resp.aiter_lines(), media_type='text/event-stream', headers={
26
+ 'Cache-Control': 'no-cache', 'Connection': 'keep-alive', 'X-Accel-Buffering': 'no'
27
+ })
28
+ return resp.json()
29
+
30
+ @app.get('/main-data/{path:path}')
31
+ async def main_data(path: str):
32
+ path = path or 'index.json'
33
+ fp = f'/data/{path}'
34
+ if not os.path.exists(fp):
35
+ return JSONResponse({'error': 'not found'}, status_code=404)
36
+ with open(fp) as f:
37
+ return JSONResponse(json.load(f))
38
+
39
+ @app.get('/')
40
+ async def root():
41
+ return {'status': 'ok', 'model': MODEL, 'docs': '/v1/chat/completions'}
42
+
43
+ if __name__ == '__main__':
44
+ import uvicorn
45
+ uvicorn.run(app, host='0.0.0.0', port=7860)
@@ -23,10 +23,10 @@ export function setKey(provider, key) {
23
23
  export function getKey(provider) {
24
24
  try {
25
25
  const keys = JSON.parse(readFileSync(KEYS_PATH, 'utf-8'));
26
- return keys[provider] || process.env[provider.toUpperCase() + '_API_KEY'] || process.env.HF_TOKEN || null;
27
- } catch {
28
- return process.env[provider.toUpperCase() + '_API_KEY'] || process.env.HF_TOKEN || null;
29
- }
26
+ if (keys[provider]) return keys[provider];
27
+ } catch {}
28
+ const envKey = process.env[provider.toUpperCase() + '_API_KEY'] || process.env.HF_TOKEN;
29
+ return envKey || null;
30
30
  }
31
31
 
32
32
  export function hasKey(provider) {
@@ -2,17 +2,26 @@ import { getKey } from '../config/keys.js';
2
2
  import { streamResponse } from './streaming.js';
3
3
  import { parseErrorResponse } from './errors.js';
4
4
 
5
+ const SPACES = [
6
+ 'https://universal-618-clarity-main.hf.space',
7
+ 'https://universal-618-clarity-2.hf.space',
8
+ 'https://universal-618-clarity-3.hf.space',
9
+ 'https://universal-618-clarity-4.hf.space',
10
+ 'https://universal-618-clarity-5.hf.space',
11
+ 'https://universal-618-clarity-6.hf.space',
12
+ ];
13
+
5
14
  const PROVIDERS = {
6
15
  huggingface: {
7
- endpoint: 'https://api-inference.huggingface.co/models',
16
+ endpoints: SPACES.map(s => s + '/v1/chat/completions'),
8
17
  name: 'huggingface',
9
18
  },
10
19
  groq: {
11
- endpoint: 'https://api.groq.com/openai/v1/chat/completions',
20
+ endpoints: ['https://api.groq.com/openai/v1/chat/completions'],
12
21
  name: 'groq',
13
22
  },
14
23
  openrouter: {
15
- endpoint: 'https://openrouter.ai/api/v1/chat/completions',
24
+ endpoints: ['https://openrouter.ai/api/v1/chat/completions'],
16
25
  name: 'openrouter',
17
26
  },
18
27
  };
@@ -40,20 +49,26 @@ export async function* callAI(providerName, model, messages, options = {}) {
40
49
  body.tool_choice = 'auto';
41
50
  }
42
51
 
43
- let endpoint = provider.endpoint;
44
52
  const extraHeaders = {};
45
- if (providerName === 'huggingface') {
46
- endpoint = provider.endpoint + '/' + modelName + '/v1/chat/completions';
47
- if (key) extraHeaders['Authorization'] = 'Bearer ' + key;
48
- } else if (providerName === 'openrouter') {
53
+ if (providerName === 'openrouter') {
49
54
  extraHeaders['HTTP-Referer'] = 'https://clarity-ai.local';
50
55
  extraHeaders['X-Title'] = 'CLARITY AI';
51
56
  }
52
57
 
53
- const stream = streamResponse(endpoint, body, key || 'none', extraHeaders, options.signal);
54
- for await (const event of stream) {
55
- yield event;
58
+ let lastErr;
59
+ for (const endpoint of provider.endpoints) {
60
+ try {
61
+ const stream = streamResponse(endpoint, body, key || 'none', extraHeaders, options.signal);
62
+ for await (const event of stream) {
63
+ yield event;
64
+ }
65
+ return;
66
+ } catch (err) {
67
+ lastErr = err;
68
+ continue;
69
+ }
56
70
  }
71
+ throw lastErr;
57
72
  }
58
73
 
59
74
  export async function callAISync(providerName, model, messages, options = {}) {