cc-agy 1.0.0 → 1.1.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/assets/kit/apple-touch-icon.png +0 -0
- package/assets/kit/cc-agy-app-icon-128.png +0 -0
- package/assets/kit/cc-agy-app-icon-32.png +0 -0
- package/assets/kit/cc-agy-app-icon-512.png +0 -0
- package/assets/kit/cc-agy-app-icon-64.png +0 -0
- package/assets/kit/cc-agy-app-icon.svg +45 -0
- package/assets/kit/cc-agy-black-128.png +0 -0
- package/assets/kit/cc-agy-black-32.png +0 -0
- package/assets/kit/cc-agy-black-512.png +0 -0
- package/assets/kit/cc-agy-black-64.png +0 -0
- package/assets/kit/cc-agy-black.svg +11 -0
- package/assets/kit/cc-agy-favicon-128.png +0 -0
- package/assets/kit/cc-agy-favicon-32.png +0 -0
- package/assets/kit/cc-agy-favicon-512.png +0 -0
- package/assets/kit/cc-agy-favicon-64.png +0 -0
- package/assets/kit/cc-agy-favicon.svg +45 -0
- package/assets/kit/cc-agy-mono-38bdf8-128.png +0 -0
- package/assets/kit/cc-agy-mono-38bdf8-32.png +0 -0
- package/assets/kit/cc-agy-mono-38bdf8-512.png +0 -0
- package/assets/kit/cc-agy-mono-38bdf8-64.png +0 -0
- package/assets/kit/cc-agy-mono-38bdf8.svg +11 -0
- package/assets/kit/cc-agy-square-128.png +0 -0
- package/assets/kit/cc-agy-square-32.png +0 -0
- package/assets/kit/cc-agy-square-512.png +0 -0
- package/assets/kit/cc-agy-square-64.png +0 -0
- package/assets/kit/cc-agy-square.svg +45 -0
- package/assets/kit/cc-agy-white-128.png +0 -0
- package/assets/kit/cc-agy-white-32.png +0 -0
- package/assets/kit/cc-agy-white-512.png +0 -0
- package/assets/kit/cc-agy-white-64.png +0 -0
- package/assets/kit/cc-agy-white.svg +11 -0
- package/assets/kit/favicon-16.png +0 -0
- package/assets/kit/favicon-32.png +0 -0
- package/assets/kit/favicon-48.png +0 -0
- package/assets/kit/favicon.ico +0 -0
- package/assets/kit/favicon.svg +45 -0
- package/assets/kit/head-snippet.html +5 -0
- package/assets/kit/icon-192.png +0 -0
- package/assets/kit/icon-512.png +0 -0
- package/assets/kit/maskable-512.png +0 -0
- package/assets/kit/site.webmanifest +24 -0
- package/assets/logo.png +0 -0
- package/assets/logo.svg +45 -0
- package/bin/cc-agy.js +273 -17
- package/package.json +2 -1
- package/scripts/patch-combo.py +83 -36
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="100%" height="100%">
|
|
2
|
+
<defs>
|
|
3
|
+
<!-- Claude Code Amber / Terracotta Gradient -->
|
|
4
|
+
<linearGradient id="claudeAmber" x1="0%" y1="100%" x2="100%" y2="0%">
|
|
5
|
+
<stop offset="0%" stop-color="#D97706" />
|
|
6
|
+
<stop offset="100%" stop-color="#F59E0B" />
|
|
7
|
+
</linearGradient>
|
|
8
|
+
|
|
9
|
+
<!-- Antigravity TPU Cyan Gradient -->
|
|
10
|
+
<linearGradient id="agyCyan" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
11
|
+
<stop offset="0%" stop-color="#00F0FF" />
|
|
12
|
+
<stop offset="100%" stop-color="#0284C7" />
|
|
13
|
+
</linearGradient>
|
|
14
|
+
|
|
15
|
+
<!-- Subtle Premium Glow -->
|
|
16
|
+
<filter id="softGlow" x="-20%" y="-20%" width="140%" height="140%">
|
|
17
|
+
<feGaussianBlur stdDeviation="8" result="blur" />
|
|
18
|
+
<feMerge>
|
|
19
|
+
<feMergeNode in="blur" opacity="0.3" />
|
|
20
|
+
<feMergeNode in="SourceGraphic" />
|
|
21
|
+
</feMerge>
|
|
22
|
+
</filter>
|
|
23
|
+
</defs>
|
|
24
|
+
|
|
25
|
+
<!-- PURE TRANSPARENT BACKGROUND -->
|
|
26
|
+
|
|
27
|
+
<!-- Perfectly Centered Scaled Encircled Mark -->
|
|
28
|
+
<g transform="translate(256, 256) scale(1.6) translate(-248, -256)" filter="url(#softGlow)">
|
|
29
|
+
<!-- Claude Code CLI Prompt Chevron -->
|
|
30
|
+
<path d="M 148 180
|
|
31
|
+
L 236 256
|
|
32
|
+
L 148 332
|
|
33
|
+
L 180 360
|
|
34
|
+
L 296 256
|
|
35
|
+
L 180 152 Z"
|
|
36
|
+
fill="url(#claudeAmber)" />
|
|
37
|
+
|
|
38
|
+
<!-- Antigravity Acceleration Node -->
|
|
39
|
+
<polygon points="268,256 348,188 348,324"
|
|
40
|
+
fill="url(#agyCyan)" />
|
|
41
|
+
|
|
42
|
+
<!-- Center Zero-Cost Nexus Flare -->
|
|
43
|
+
<circle cx="256" cy="256" r="10" fill="#FFFFFF" />
|
|
44
|
+
</g>
|
|
45
|
+
</svg>
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<svg fill="#000000" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" width="100%" height="100%"><title>cc-agy Logo</title>
|
|
2
|
+
|
|
3
|
+
<!-- Concept 3: Escape Velocity Delta (60 degree equilateral geometry) -->
|
|
4
|
+
<g fill="#000000" fill-rule="evenodd">
|
|
5
|
+
<!-- Outer Delta Frame with exact 60-degree angles -->
|
|
6
|
+
<path d="M 128 45.72 L 224 212 L 176 212 L 128 128.86 L 80 212 L 32 212 Z
|
|
7
|
+
M 128 85 L 152 126.57 L 104 126.57 Z" />
|
|
8
|
+
<!-- Dynamic Forward Agent Vector -->
|
|
9
|
+
<polygon points="108,180 156,180 172,164 156,148 108,148 124,164" />
|
|
10
|
+
</g>
|
|
11
|
+
</svg>
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="100%" height="100%">
|
|
2
|
+
<defs>
|
|
3
|
+
<!-- Claude Code Amber / Terracotta Gradient -->
|
|
4
|
+
<linearGradient id="claudeAmber" x1="0%" y1="100%" x2="100%" y2="0%">
|
|
5
|
+
<stop offset="0%" stop-color="#D97706" />
|
|
6
|
+
<stop offset="100%" stop-color="#F59E0B" />
|
|
7
|
+
</linearGradient>
|
|
8
|
+
|
|
9
|
+
<!-- Antigravity TPU Cyan Gradient -->
|
|
10
|
+
<linearGradient id="agyCyan" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
11
|
+
<stop offset="0%" stop-color="#00F0FF" />
|
|
12
|
+
<stop offset="100%" stop-color="#0284C7" />
|
|
13
|
+
</linearGradient>
|
|
14
|
+
|
|
15
|
+
<!-- Subtle Premium Glow -->
|
|
16
|
+
<filter id="softGlow" x="-20%" y="-20%" width="140%" height="140%">
|
|
17
|
+
<feGaussianBlur stdDeviation="8" result="blur" />
|
|
18
|
+
<feMerge>
|
|
19
|
+
<feMergeNode in="blur" opacity="0.3" />
|
|
20
|
+
<feMergeNode in="SourceGraphic" />
|
|
21
|
+
</feMerge>
|
|
22
|
+
</filter>
|
|
23
|
+
</defs>
|
|
24
|
+
|
|
25
|
+
<!-- PURE TRANSPARENT BACKGROUND -->
|
|
26
|
+
|
|
27
|
+
<!-- Perfectly Centered Scaled Encircled Mark -->
|
|
28
|
+
<g transform="translate(256, 256) scale(1.6) translate(-248, -256)" filter="url(#softGlow)">
|
|
29
|
+
<!-- Claude Code CLI Prompt Chevron -->
|
|
30
|
+
<path d="M 148 180
|
|
31
|
+
L 236 256
|
|
32
|
+
L 148 332
|
|
33
|
+
L 180 360
|
|
34
|
+
L 296 256
|
|
35
|
+
L 180 152 Z"
|
|
36
|
+
fill="url(#claudeAmber)" />
|
|
37
|
+
|
|
38
|
+
<!-- Antigravity Acceleration Node -->
|
|
39
|
+
<polygon points="268,256 348,188 348,324"
|
|
40
|
+
fill="url(#agyCyan)" />
|
|
41
|
+
|
|
42
|
+
<!-- Center Zero-Cost Nexus Flare -->
|
|
43
|
+
<circle cx="256" cy="256" r="10" fill="#FFFFFF" />
|
|
44
|
+
</g>
|
|
45
|
+
</svg>
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<svg fill="#38bdf8" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" width="100%" height="100%"><title>cc-agy Logo</title>
|
|
2
|
+
|
|
3
|
+
<!-- Concept 3: Escape Velocity Delta (60 degree equilateral geometry) -->
|
|
4
|
+
<g fill="#38bdf8" fill-rule="evenodd">
|
|
5
|
+
<!-- Outer Delta Frame with exact 60-degree angles -->
|
|
6
|
+
<path d="M 128 45.72 L 224 212 L 176 212 L 128 128.86 L 80 212 L 32 212 Z
|
|
7
|
+
M 128 85 L 152 126.57 L 104 126.57 Z" />
|
|
8
|
+
<!-- Dynamic Forward Agent Vector -->
|
|
9
|
+
<polygon points="108,180 156,180 172,164 156,148 108,148 124,164" />
|
|
10
|
+
</g>
|
|
11
|
+
</svg>
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="100%" height="100%">
|
|
2
|
+
<defs>
|
|
3
|
+
<!-- Claude Code Amber / Terracotta Gradient -->
|
|
4
|
+
<linearGradient id="claudeAmber" x1="0%" y1="100%" x2="100%" y2="0%">
|
|
5
|
+
<stop offset="0%" stop-color="#D97706" />
|
|
6
|
+
<stop offset="100%" stop-color="#F59E0B" />
|
|
7
|
+
</linearGradient>
|
|
8
|
+
|
|
9
|
+
<!-- Antigravity TPU Cyan Gradient -->
|
|
10
|
+
<linearGradient id="agyCyan" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
11
|
+
<stop offset="0%" stop-color="#00F0FF" />
|
|
12
|
+
<stop offset="100%" stop-color="#0284C7" />
|
|
13
|
+
</linearGradient>
|
|
14
|
+
|
|
15
|
+
<!-- Subtle Premium Glow -->
|
|
16
|
+
<filter id="softGlow" x="-20%" y="-20%" width="140%" height="140%">
|
|
17
|
+
<feGaussianBlur stdDeviation="8" result="blur" />
|
|
18
|
+
<feMerge>
|
|
19
|
+
<feMergeNode in="blur" opacity="0.3" />
|
|
20
|
+
<feMergeNode in="SourceGraphic" />
|
|
21
|
+
</feMerge>
|
|
22
|
+
</filter>
|
|
23
|
+
</defs>
|
|
24
|
+
|
|
25
|
+
<!-- PURE TRANSPARENT BACKGROUND -->
|
|
26
|
+
|
|
27
|
+
<!-- Perfectly Centered Scaled Encircled Mark -->
|
|
28
|
+
<g transform="translate(256, 256) scale(1.6) translate(-248, -256)" filter="url(#softGlow)">
|
|
29
|
+
<!-- Claude Code CLI Prompt Chevron -->
|
|
30
|
+
<path d="M 148 180
|
|
31
|
+
L 236 256
|
|
32
|
+
L 148 332
|
|
33
|
+
L 180 360
|
|
34
|
+
L 296 256
|
|
35
|
+
L 180 152 Z"
|
|
36
|
+
fill="url(#claudeAmber)" />
|
|
37
|
+
|
|
38
|
+
<!-- Antigravity Acceleration Node -->
|
|
39
|
+
<polygon points="268,256 348,188 348,324"
|
|
40
|
+
fill="url(#agyCyan)" />
|
|
41
|
+
|
|
42
|
+
<!-- Center Zero-Cost Nexus Flare -->
|
|
43
|
+
<circle cx="256" cy="256" r="10" fill="#FFFFFF" />
|
|
44
|
+
</g>
|
|
45
|
+
</svg>
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<svg fill="#ffffff" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" width="100%" height="100%"><title>cc-agy Logo</title>
|
|
2
|
+
|
|
3
|
+
<!-- Concept 3: Escape Velocity Delta (60 degree equilateral geometry) -->
|
|
4
|
+
<g fill="#ffffff" fill-rule="evenodd">
|
|
5
|
+
<!-- Outer Delta Frame with exact 60-degree angles -->
|
|
6
|
+
<path d="M 128 45.72 L 224 212 L 176 212 L 128 128.86 L 80 212 L 32 212 Z
|
|
7
|
+
M 128 85 L 152 126.57 L 104 126.57 Z" />
|
|
8
|
+
<!-- Dynamic Forward Agent Vector -->
|
|
9
|
+
<polygon points="108,180 156,180 172,164 156,148 108,148 124,164" />
|
|
10
|
+
</g>
|
|
11
|
+
</svg>
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="100%" height="100%">
|
|
2
|
+
<defs>
|
|
3
|
+
<!-- Claude Code Amber / Terracotta Gradient -->
|
|
4
|
+
<linearGradient id="claudeAmber" x1="0%" y1="100%" x2="100%" y2="0%">
|
|
5
|
+
<stop offset="0%" stop-color="#D97706" />
|
|
6
|
+
<stop offset="100%" stop-color="#F59E0B" />
|
|
7
|
+
</linearGradient>
|
|
8
|
+
|
|
9
|
+
<!-- Antigravity TPU Cyan Gradient -->
|
|
10
|
+
<linearGradient id="agyCyan" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
11
|
+
<stop offset="0%" stop-color="#00F0FF" />
|
|
12
|
+
<stop offset="100%" stop-color="#0284C7" />
|
|
13
|
+
</linearGradient>
|
|
14
|
+
|
|
15
|
+
<!-- Subtle Premium Glow -->
|
|
16
|
+
<filter id="softGlow" x="-20%" y="-20%" width="140%" height="140%">
|
|
17
|
+
<feGaussianBlur stdDeviation="8" result="blur" />
|
|
18
|
+
<feMerge>
|
|
19
|
+
<feMergeNode in="blur" opacity="0.3" />
|
|
20
|
+
<feMergeNode in="SourceGraphic" />
|
|
21
|
+
</feMerge>
|
|
22
|
+
</filter>
|
|
23
|
+
</defs>
|
|
24
|
+
|
|
25
|
+
<!-- PURE TRANSPARENT BACKGROUND -->
|
|
26
|
+
|
|
27
|
+
<!-- Perfectly Centered Scaled Encircled Mark -->
|
|
28
|
+
<g transform="translate(256, 256) scale(1.6) translate(-248, -256)" filter="url(#softGlow)">
|
|
29
|
+
<!-- Claude Code CLI Prompt Chevron -->
|
|
30
|
+
<path d="M 148 180
|
|
31
|
+
L 236 256
|
|
32
|
+
L 148 332
|
|
33
|
+
L 180 360
|
|
34
|
+
L 296 256
|
|
35
|
+
L 180 152 Z"
|
|
36
|
+
fill="url(#claudeAmber)" />
|
|
37
|
+
|
|
38
|
+
<!-- Antigravity Acceleration Node -->
|
|
39
|
+
<polygon points="268,256 348,188 348,324"
|
|
40
|
+
fill="url(#agyCyan)" />
|
|
41
|
+
|
|
42
|
+
<!-- Center Zero-Cost Nexus Flare -->
|
|
43
|
+
<circle cx="256" cy="256" r="10" fill="#FFFFFF" />
|
|
44
|
+
</g>
|
|
45
|
+
</svg>
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "cc-agy Logo",
|
|
3
|
+
"icons": [
|
|
4
|
+
{
|
|
5
|
+
"src": "/icon-192.png",
|
|
6
|
+
"sizes": "192x192",
|
|
7
|
+
"type": "image/png"
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
"src": "/icon-512.png",
|
|
11
|
+
"sizes": "512x512",
|
|
12
|
+
"type": "image/png"
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"src": "/maskable-512.png",
|
|
16
|
+
"sizes": "512x512",
|
|
17
|
+
"type": "image/png",
|
|
18
|
+
"purpose": "maskable"
|
|
19
|
+
}
|
|
20
|
+
],
|
|
21
|
+
"theme_color": "#090D16",
|
|
22
|
+
"background_color": "#090D16",
|
|
23
|
+
"display": "standalone"
|
|
24
|
+
}
|
package/assets/logo.png
ADDED
|
Binary file
|
package/assets/logo.svg
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="100%" height="100%">
|
|
2
|
+
<defs>
|
|
3
|
+
<!-- Claude Code Amber / Terracotta Gradient -->
|
|
4
|
+
<linearGradient id="claudeAmber" x1="0%" y1="100%" x2="100%" y2="0%">
|
|
5
|
+
<stop offset="0%" stop-color="#D97706" />
|
|
6
|
+
<stop offset="100%" stop-color="#F59E0B" />
|
|
7
|
+
</linearGradient>
|
|
8
|
+
|
|
9
|
+
<!-- Antigravity TPU Cyan Gradient -->
|
|
10
|
+
<linearGradient id="agyCyan" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
11
|
+
<stop offset="0%" stop-color="#00F0FF" />
|
|
12
|
+
<stop offset="100%" stop-color="#0284C7" />
|
|
13
|
+
</linearGradient>
|
|
14
|
+
|
|
15
|
+
<!-- Subtle Premium Glow -->
|
|
16
|
+
<filter id="softGlow" x="-20%" y="-20%" width="140%" height="140%">
|
|
17
|
+
<feGaussianBlur stdDeviation="8" result="blur" />
|
|
18
|
+
<feMerge>
|
|
19
|
+
<feMergeNode in="blur" opacity="0.3" />
|
|
20
|
+
<feMergeNode in="SourceGraphic" />
|
|
21
|
+
</feMerge>
|
|
22
|
+
</filter>
|
|
23
|
+
</defs>
|
|
24
|
+
|
|
25
|
+
<!-- PURE TRANSPARENT BACKGROUND -->
|
|
26
|
+
|
|
27
|
+
<!-- Perfectly Centered Scaled Encircled Mark -->
|
|
28
|
+
<g transform="translate(256, 256) scale(1.6) translate(-248, -256)" filter="url(#softGlow)">
|
|
29
|
+
<!-- Claude Code CLI Prompt Chevron -->
|
|
30
|
+
<path d="M 148 180
|
|
31
|
+
L 236 256
|
|
32
|
+
L 148 332
|
|
33
|
+
L 180 360
|
|
34
|
+
L 296 256
|
|
35
|
+
L 180 152 Z"
|
|
36
|
+
fill="url(#claudeAmber)" />
|
|
37
|
+
|
|
38
|
+
<!-- Antigravity Acceleration Node -->
|
|
39
|
+
<polygon points="268,256 348,188 348,324"
|
|
40
|
+
fill="url(#agyCyan)" />
|
|
41
|
+
|
|
42
|
+
<!-- Center Zero-Cost Nexus Flare -->
|
|
43
|
+
<circle cx="256" cy="256" r="10" fill="#FFFFFF" />
|
|
44
|
+
</g>
|
|
45
|
+
</svg>
|
package/bin/cc-agy.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
3
|
* cc-agy: Autonomous Self-Healing CLI Wrapper & Gateway Controller
|
|
4
|
-
* Seamlessly connects Claude Code to Google Antigravity (Gemini 3.8 Flash High)
|
|
4
|
+
* Seamlessly connects Claude Code to Google Antigravity (Gemini 3.8 Flash High & Claude on TPU)
|
|
5
5
|
* Author: Farhat Iqbal (@farhatkoka)
|
|
6
6
|
*/
|
|
7
7
|
|
|
@@ -10,6 +10,7 @@ const fs = require('fs');
|
|
|
10
10
|
const path = require('path');
|
|
11
11
|
const os = require('os');
|
|
12
12
|
const http = require('http');
|
|
13
|
+
const readline = require('readline');
|
|
13
14
|
|
|
14
15
|
const BOLD = '\x1b[1m';
|
|
15
16
|
const GREEN = '\x1b[32m';
|
|
@@ -17,14 +18,90 @@ const BLUE = '\x1b[34m';
|
|
|
17
18
|
const YELLOW = '\x1b[33m';
|
|
18
19
|
const RED = '\x1b[31m';
|
|
19
20
|
const CYAN = '\x1b[36m';
|
|
21
|
+
const DIM = '\x1b[2m';
|
|
20
22
|
const NC = '\x1b[0m';
|
|
21
23
|
|
|
22
24
|
const HOME = os.homedir();
|
|
23
25
|
const AGY_TOKEN_PATH = path.join(HOME, '.gemini', 'antigravity-cli', 'antigravity-oauth-token');
|
|
24
26
|
const CLAUDE_SETTINGS_PATH = path.join(HOME, '.claude', 'settings.json');
|
|
25
27
|
const SYSTEMD_SERVICE_PATH = path.join(HOME, '.config', 'systemd', 'user', 'omniroute.service');
|
|
28
|
+
const CONFIG_DIR = path.join(HOME, '.config', 'cc-agy');
|
|
29
|
+
const CONFIG_PATH = path.join(CONFIG_DIR, 'config.json');
|
|
26
30
|
const HEALTH_URL = 'http://127.0.0.1:20128/api/monitoring/health';
|
|
27
31
|
|
|
32
|
+
const AGY_MODELS = [
|
|
33
|
+
{
|
|
34
|
+
id: 'gemini-3.8-flash-high',
|
|
35
|
+
name: 'Gemini 3.8 Flash High',
|
|
36
|
+
description: 'Google Deep Thinking (TPU v5p Reasoning Engine)',
|
|
37
|
+
aliases: ['1', 'flash', 'high', 'flash-high', 'gemini']
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
id: 'gemini-3.8-flash-medium',
|
|
41
|
+
name: 'Gemini 3.8 Flash Medium',
|
|
42
|
+
description: 'Balanced latency & test-time reasoning',
|
|
43
|
+
aliases: ['2', 'medium', 'med', 'flash-medium']
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
id: 'gemini-3.8-flash-low',
|
|
47
|
+
name: 'Gemini 3.8 Flash Low',
|
|
48
|
+
description: 'Distilled sub-second speed',
|
|
49
|
+
aliases: ['3', 'low', 'flash-low']
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
id: 'claude-sonnet-4-6',
|
|
53
|
+
name: 'Claude Sonnet 4.6 (Thinking)',
|
|
54
|
+
description: 'Anthropic flagship agentic reasoning on TPU',
|
|
55
|
+
aliases: ['4', 'sonnet', 'sonnet-4-6']
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
id: 'claude-opus-4-6-thinking',
|
|
59
|
+
name: 'Claude Opus 4.6 (Thinking)',
|
|
60
|
+
description: 'Anthropic maximum depth reasoning',
|
|
61
|
+
aliases: ['5', 'opus', 'opus-4-6', 'opus-thinking']
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
id: 'gpt-oss-120b-medium',
|
|
65
|
+
name: 'GPT-OSS 120B (Medium)',
|
|
66
|
+
description: 'Open-weights high-density reasoning',
|
|
67
|
+
aliases: ['6', 'gpt', 'oss', '120b']
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
id: 'claude-auto',
|
|
71
|
+
name: 'Claude-Auto Priority Cascade',
|
|
72
|
+
description: 'Dynamic failover: Flash High -> Sonnet 4.6 -> Flash Lite',
|
|
73
|
+
aliases: ['7', 'auto', 'cascade', 'default']
|
|
74
|
+
}
|
|
75
|
+
];
|
|
76
|
+
|
|
77
|
+
function loadConfig() {
|
|
78
|
+
try {
|
|
79
|
+
if (fs.existsSync(CONFIG_PATH)) {
|
|
80
|
+
return JSON.parse(fs.readFileSync(CONFIG_PATH, 'utf8'));
|
|
81
|
+
}
|
|
82
|
+
} catch {}
|
|
83
|
+
return { defaultModel: 'gemini-3.8-flash-high' };
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function saveConfig(cfg) {
|
|
87
|
+
try {
|
|
88
|
+
fs.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
89
|
+
fs.writeFileSync(CONFIG_PATH, JSON.stringify(cfg, null, 2), 'utf8');
|
|
90
|
+
} catch (err) {
|
|
91
|
+
console.error(`${RED}[-] Failed to persist config:${NC}`, err.message);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function resolveModel(query) {
|
|
96
|
+
if (!query) return null;
|
|
97
|
+
const q = query.trim().toLowerCase();
|
|
98
|
+
for (const m of AGY_MODELS) {
|
|
99
|
+
if (m.id.toLowerCase() === q) return m;
|
|
100
|
+
if (m.aliases.includes(q)) return m;
|
|
101
|
+
}
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
|
|
28
105
|
function checkHealth(timeoutMs = 1500) {
|
|
29
106
|
return new Promise((resolve) => {
|
|
30
107
|
const req = http.get(HEALTH_URL, { timeout: timeoutMs }, (res) => {
|
|
@@ -58,7 +135,12 @@ function healNativeBinary() {
|
|
|
58
135
|
|
|
59
136
|
for (const scriptPath of possiblePaths) {
|
|
60
137
|
if (fs.existsSync(scriptPath)) {
|
|
61
|
-
|
|
138
|
+
// Purge any conflicting nested platform package to prevent 'Two copies installed' error
|
|
139
|
+
const nestedPkg = path.join(path.dirname(scriptPath), 'node_modules', '@anthropic-ai', 'claude-code-linux-x64');
|
|
140
|
+
if (fs.existsSync(nestedPkg)) {
|
|
141
|
+
try { fs.rmSync(nestedPkg, { recursive: true, force: true }); } catch {}
|
|
142
|
+
}
|
|
143
|
+
process.stdout.write(`${YELLOW}⚡ [cc-agy] Linking platform native ELF binary...${NC} `);
|
|
62
144
|
const res = spawnSync('node', [scriptPath], { encoding: 'utf-8' });
|
|
63
145
|
if (res.status === 0) {
|
|
64
146
|
console.log(`${GREEN}✔ Done.${NC}`);
|
|
@@ -130,19 +212,15 @@ async function runDoctor() {
|
|
|
130
212
|
console.log(`${BOLD}${CYAN} cc-agy: System Architecture & Diagnostic Telemetry ${NC}`);
|
|
131
213
|
console.log(`${BOLD}${CYAN}====================================================================${NC}\n`);
|
|
132
214
|
|
|
133
|
-
// 1. Antigravity OAuth Token
|
|
134
215
|
const hasToken = fs.existsSync(AGY_TOKEN_PATH);
|
|
135
216
|
console.log(`[1] Google Antigravity Token : ${hasToken ? `${GREEN}✔ Present (${AGY_TOKEN_PATH})${NC}` : `${RED}✖ Missing. Run 'agy' to sign in.${NC}`}`);
|
|
136
217
|
|
|
137
|
-
// 2. Gateway Service
|
|
138
218
|
const serviceActive = spawnSync('systemctl', ['--user', 'is-active', 'omniroute'], { encoding: 'utf-8' }).stdout?.trim() === 'active';
|
|
139
219
|
console.log(`[2] OmniRoute User Daemon : ${serviceActive ? `${GREEN}✔ active (systemd --user)${NC}` : `${YELLOW}⚠ inactive / not running${NC}`}`);
|
|
140
220
|
|
|
141
|
-
// 3. Local Endpoint Health
|
|
142
221
|
const healthy = await checkHealth(2000);
|
|
143
222
|
console.log(`[3] Gateway Health Endpoint : ${healthy ? `${GREEN}✔ http://127.0.0.1:20128 (healthy)${NC}` : `${RED}✖ Unreachable${NC}`}`);
|
|
144
223
|
|
|
145
|
-
// 4. Claude Code CLI Version & Binary
|
|
146
224
|
let claudeVersion = 'Unknown';
|
|
147
225
|
let binaryStatus = `${RED}✖ Broken / Unlinked${NC}`;
|
|
148
226
|
try {
|
|
@@ -156,15 +234,140 @@ async function runDoctor() {
|
|
|
156
234
|
console.log(`[4] Claude Code CLI Version : ${CYAN}${claudeVersion}${NC}`);
|
|
157
235
|
console.log(`[5] Platform Native Binary : ${binaryStatus}`);
|
|
158
236
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
console.log(`
|
|
162
|
-
console.log(` ${BOLD}Tier 3: Gemini 3.1 Flash Lite (Circuit Breaker)${NC}`);
|
|
237
|
+
const cfg = loadConfig();
|
|
238
|
+
const current = resolveModel(cfg.defaultModel) || AGY_MODELS[0];
|
|
239
|
+
console.log(`[6] Active Cognitive Model : ${BOLD}${CYAN}${current.name}${NC} (${current.id})`);
|
|
163
240
|
console.log(`[7] Token Billing / Cost : ${GREEN}Asymmetric Zero Marginal Cost ($0 / token)${NC}\n`);
|
|
164
241
|
}
|
|
165
242
|
|
|
243
|
+
async function handleModelCommand(targetArg) {
|
|
244
|
+
const cfg = loadConfig();
|
|
245
|
+
const currentId = cfg.defaultModel || 'gemini-3.8-flash-high';
|
|
246
|
+
|
|
247
|
+
if (targetArg) {
|
|
248
|
+
const matched = resolveModel(targetArg);
|
|
249
|
+
if (!matched) {
|
|
250
|
+
console.log(`\n${RED}[-] Unknown model alias: '${targetArg}'${NC}`);
|
|
251
|
+
console.log(` Available aliases: flash, medium, low, sonnet, opus, gpt, auto\n`);
|
|
252
|
+
process.exit(1);
|
|
253
|
+
}
|
|
254
|
+
cfg.defaultModel = matched.id;
|
|
255
|
+
saveConfig(cfg);
|
|
256
|
+
console.log(`\n${GREEN}✔ Active Antigravity Model switched to:${NC} ${BOLD}${matched.name}${NC} (${matched.id})\n`);
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// Interactive Model Selector Menu
|
|
261
|
+
console.log(`\n${BOLD}${CYAN}====================================================================${NC}`);
|
|
262
|
+
console.log(`${BOLD}${CYAN} cc-agy: Antigravity Model Switcher (TPU v5p Compute) ${NC}`);
|
|
263
|
+
console.log(`${BOLD}${CYAN}====================================================================${NC}\n`);
|
|
264
|
+
|
|
265
|
+
AGY_MODELS.forEach((m, idx) => {
|
|
266
|
+
const isActive = m.id === currentId;
|
|
267
|
+
const marker = isActive ? `${GREEN}● [ACTIVE]${NC}` : ` `;
|
|
268
|
+
const num = `${BOLD}[${idx + 1}]${NC}`;
|
|
269
|
+
console.log(` ${num} ${BOLD}${m.name.padEnd(28)}${NC} ${marker}`);
|
|
270
|
+
console.log(` ${DIM}${m.description}${NC}`);
|
|
271
|
+
console.log(` ${DIM}ID: ${m.id} | Aliases: ${m.aliases.join(', ')}${NC}\n`);
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
const rl = readline.createInterface({
|
|
275
|
+
input: process.stdin,
|
|
276
|
+
output: process.stdout,
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
rl.question(`${BOLD}Select model [1-7] (or press Enter to keep current): ${NC}`, (answer) => {
|
|
280
|
+
rl.close();
|
|
281
|
+
const trimmed = answer.trim();
|
|
282
|
+
if (!trimmed) {
|
|
283
|
+
console.log(`${CYAN}Retaining current active model: ${currentId}${NC}\n`);
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
const matched = resolveModel(trimmed);
|
|
287
|
+
if (matched) {
|
|
288
|
+
cfg.defaultModel = matched.id;
|
|
289
|
+
saveConfig(cfg);
|
|
290
|
+
console.log(`\n${GREEN}✔ Active Antigravity Model set to:${NC} ${BOLD}${matched.name}${NC} (${matched.id})\n`);
|
|
291
|
+
} else {
|
|
292
|
+
console.log(`\n${RED}[-] Invalid selection. Keeping ${currentId}.${NC}\n`);
|
|
293
|
+
}
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
async function handleUpdateCommand() {
|
|
298
|
+
const pkgPath = path.join(__dirname, '..', 'package.json');
|
|
299
|
+
let pkg = { version: '1.1.0' };
|
|
300
|
+
try {
|
|
301
|
+
pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
|
|
302
|
+
} catch (e) {}
|
|
303
|
+
const currentVersion = pkg.version;
|
|
304
|
+
|
|
305
|
+
console.log(`\n${BOLD}${CYAN}cc-agy Update Engine${NC}`);
|
|
306
|
+
console.log(`Current installed version: ${BOLD}v${currentVersion}${NC}`);
|
|
307
|
+
|
|
308
|
+
// Query registry for latest published version
|
|
309
|
+
let latestNpm = null;
|
|
310
|
+
try {
|
|
311
|
+
const res = spawnSync('npm', ['view', 'cc-agy', 'version'], { encoding: 'utf8' });
|
|
312
|
+
if (res.status === 0 && res.stdout) {
|
|
313
|
+
latestNpm = res.stdout.trim();
|
|
314
|
+
}
|
|
315
|
+
} catch (e) {}
|
|
316
|
+
|
|
317
|
+
if (latestNpm) {
|
|
318
|
+
console.log(`Latest registry version: ${BOLD}v${latestNpm}${NC}`);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
const isGitRepo = fs.existsSync(path.join(__dirname, '..', '.git'));
|
|
322
|
+
|
|
323
|
+
if (isGitRepo) {
|
|
324
|
+
console.log(`\n${DIM}Repository checkout detected (${path.resolve(__dirname, '..')})${NC}`);
|
|
325
|
+
console.log(`Syncing latest commits from GitHub origin/main...`);
|
|
326
|
+
const pull = spawnSync('git', ['pull', '--rebase', 'origin', 'main'], {
|
|
327
|
+
cwd: path.join(__dirname, '..'),
|
|
328
|
+
stdio: 'inherit',
|
|
329
|
+
});
|
|
330
|
+
if (pull.status !== 0) {
|
|
331
|
+
console.log(`\n${RED}✖ Git pull failed. Please check local git working tree.${NC}\n`);
|
|
332
|
+
process.exit(1);
|
|
333
|
+
}
|
|
334
|
+
} else {
|
|
335
|
+
console.log(`\nUpdating global npm package: ${BOLD}npm install -g cc-agy@latest${NC}...`);
|
|
336
|
+
const npmUp = spawnSync('npm', ['install', '-g', 'cc-agy@latest'], {
|
|
337
|
+
stdio: 'inherit',
|
|
338
|
+
});
|
|
339
|
+
if (npmUp.status !== 0) {
|
|
340
|
+
console.log(`\n${RED}✖ npm update failed.${NC}\n`);
|
|
341
|
+
process.exit(1);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
// Synchronize database combos if omniroute is installed
|
|
346
|
+
const patchScript = path.join(__dirname, '..', 'scripts', 'patch-combo.py');
|
|
347
|
+
if (fs.existsSync(patchScript)) {
|
|
348
|
+
console.log(`\nSynchronizing Antigravity model combos in SQLite...`);
|
|
349
|
+
spawnSync('python3', [patchScript], { stdio: 'inherit' });
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// Ensure native binary link for claude-code
|
|
353
|
+
ensureNativeBinaryHealthy();
|
|
354
|
+
|
|
355
|
+
// Restart proxy daemon if running
|
|
356
|
+
console.log(`Verifying gateway daemon status...`);
|
|
357
|
+
spawnSync('systemctl', ['--user', 'restart', 'omniroute.service'], { stdio: 'ignore' });
|
|
358
|
+
|
|
359
|
+
let updatedVersion = currentVersion;
|
|
360
|
+
try {
|
|
361
|
+
const updatedPkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
|
|
362
|
+
updatedVersion = updatedPkg.version;
|
|
363
|
+
} catch (e) {}
|
|
364
|
+
|
|
365
|
+
console.log(`\n${GREEN}✔ cc-agy is now at v${updatedVersion}!${NC}\n`);
|
|
366
|
+
process.exit(0);
|
|
367
|
+
}
|
|
368
|
+
|
|
166
369
|
async function main() {
|
|
167
|
-
const args = process.argv.slice(2);
|
|
370
|
+
const args = [...process.argv.slice(2)];
|
|
168
371
|
const command = args[0];
|
|
169
372
|
|
|
170
373
|
if (command === 'doctor' || command === 'status') {
|
|
@@ -185,21 +388,44 @@ async function main() {
|
|
|
185
388
|
process.exit(ok ? 0 : 1);
|
|
186
389
|
}
|
|
187
390
|
|
|
391
|
+
if (command === 'update' || command === 'upgrade') {
|
|
392
|
+
await handleUpdateCommand();
|
|
393
|
+
return;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
if (command === 'model' || command === 'models' || command === 'switch') {
|
|
397
|
+
await handleModelCommand(args[1]);
|
|
398
|
+
return;
|
|
399
|
+
}
|
|
400
|
+
|
|
188
401
|
if (command === '--help' || command === '-h' || command === 'help') {
|
|
189
402
|
console.log(`
|
|
190
|
-
${BOLD}cc-agy${NC} - Claude Code + Google Antigravity (Gemini 3.8 Flash High)
|
|
403
|
+
${BOLD}cc-agy${NC} - Claude Code + Google Antigravity (Gemini 3.8 Flash High & Claude on TPU)
|
|
191
404
|
|
|
192
405
|
${BOLD}USAGE:${NC}
|
|
193
406
|
cc-agy [options] [claude-flags] Launch Claude Code connected to Antigravity
|
|
407
|
+
cc-agy model [alias] Switch default active model (or show interactive menu)
|
|
408
|
+
cc-agy update Self-update to the latest version & sync model combos
|
|
194
409
|
cc-agy doctor Run full diagnostic telemetry & healthcheck
|
|
195
410
|
cc-agy restart Restart local proxy daemon
|
|
196
411
|
cc-agy setup Force re-run provisioning and database patches
|
|
197
412
|
|
|
413
|
+
${BOLD}MODELS & ALIASES:${NC}
|
|
414
|
+
flash / high Gemini 3.8 Flash High (Deep Reasoning)
|
|
415
|
+
medium / med Gemini 3.8 Flash Medium
|
|
416
|
+
low Gemini 3.8 Flash Low (Sub-second)
|
|
417
|
+
sonnet Claude Sonnet 4.6 (Thinking on TPU)
|
|
418
|
+
opus Claude Opus 4.6 (Thinking on TPU)
|
|
419
|
+
gpt / oss GPT-OSS 120B (Medium)
|
|
420
|
+
auto Priority Cascade (High -> Sonnet -> Lite)
|
|
421
|
+
|
|
198
422
|
${BOLD}EXAMPLES:${NC}
|
|
199
|
-
cc-agy
|
|
423
|
+
cc-agy Launch with active model
|
|
424
|
+
cc-agy --model sonnet Launch a session with Claude Sonnet 4.6
|
|
425
|
+
cc-agy --model opus Launch a session with Claude Opus 4.6
|
|
426
|
+
cc-agy model Open interactive model switcher
|
|
427
|
+
cc-agy model sonnet Set default model to Sonnet 4.6
|
|
200
428
|
cc-agy --dangerously-skip-permissions
|
|
201
|
-
cc-agy -p "Review this file"
|
|
202
|
-
cc-agy doctor
|
|
203
429
|
`);
|
|
204
430
|
process.exit(0);
|
|
205
431
|
}
|
|
@@ -223,18 +449,48 @@ ${BOLD}EXAMPLES:${NC}
|
|
|
223
449
|
ensureNativeBinaryHealthy();
|
|
224
450
|
await ensureDaemonRunning();
|
|
225
451
|
|
|
226
|
-
//
|
|
452
|
+
// Model resolution: check command-line --model / -m override, otherwise use saved default
|
|
453
|
+
const cfg = loadConfig();
|
|
454
|
+
let selectedModelId = cfg.defaultModel || 'gemini-3.8-flash-high';
|
|
455
|
+
let modelIndex = -1;
|
|
456
|
+
|
|
457
|
+
for (let i = 0; i < args.length; i++) {
|
|
458
|
+
if (args[i] === '--model' || args[i] === '-m') {
|
|
459
|
+
if (args[i + 1]) {
|
|
460
|
+
const resolved = resolveModel(args[i + 1]);
|
|
461
|
+
if (resolved) {
|
|
462
|
+
selectedModelId = resolved.id;
|
|
463
|
+
} else {
|
|
464
|
+
selectedModelId = args[i + 1];
|
|
465
|
+
}
|
|
466
|
+
modelIndex = i;
|
|
467
|
+
}
|
|
468
|
+
break;
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
// Strip custom --model/-m from args to pass cleaned model id to claude
|
|
473
|
+
const forwardArgs = [...args];
|
|
474
|
+
if (modelIndex !== -1) {
|
|
475
|
+
forwardArgs.splice(modelIndex, 2);
|
|
476
|
+
}
|
|
477
|
+
forwardArgs.unshift('--model', selectedModelId);
|
|
478
|
+
|
|
479
|
+
// Inject gateway environment variables & disable broken background autoupdate
|
|
227
480
|
const apiKey = getLocalApiKey();
|
|
228
481
|
const env = {
|
|
229
482
|
...process.env,
|
|
230
483
|
ANTHROPIC_BASE_URL: 'http://localhost:20128',
|
|
231
484
|
ANTHROPIC_AUTH_TOKEN: apiKey,
|
|
232
485
|
ANTHROPIC_API_KEY: '',
|
|
486
|
+
ANTHROPIC_MODEL: selectedModelId,
|
|
233
487
|
CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY: '1',
|
|
488
|
+
DISABLE_AUTOUPDATER: '1',
|
|
489
|
+
CLAUDE_CODE_AUTOUPDATER_DISABLED_BY_HOST: '1',
|
|
234
490
|
};
|
|
235
491
|
|
|
236
492
|
// Launch Claude Code transparently
|
|
237
|
-
const child = spawn('claude',
|
|
493
|
+
const child = spawn('claude', forwardArgs, {
|
|
238
494
|
stdio: 'inherit',
|
|
239
495
|
env,
|
|
240
496
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cc-agy",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Decoupled Asymmetric Compute Gateway: Claude Code CLI + Google Antigravity (Gemini 3.8 Flash High) TPU compute at zero marginal token cost.",
|
|
5
5
|
"main": "bin/cc-agy.js",
|
|
6
6
|
"bin": {
|
|
@@ -38,6 +38,7 @@
|
|
|
38
38
|
"bin",
|
|
39
39
|
"scripts",
|
|
40
40
|
"systemd",
|
|
41
|
+
"assets",
|
|
41
42
|
"install.sh",
|
|
42
43
|
"uninstall.sh",
|
|
43
44
|
"README.md",
|
package/scripts/patch-combo.py
CHANGED
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
"""
|
|
3
3
|
patch-combo.py
|
|
4
4
|
Configures OmniRoute SQLite database for Claude Code + Antigravity compatibility:
|
|
5
|
-
1.
|
|
6
|
-
2.
|
|
7
|
-
3.
|
|
5
|
+
1. Provisions exact Google Antigravity models and aliases (Gemini 3.8 Flash High/Med/Low, Claude Sonnet 4.6, Claude Opus 4.6, GPT-OSS 120B).
|
|
6
|
+
2. Enables compatFilterFailOpen on combos to prevent fatal 400 capability errors.
|
|
7
|
+
3. Sets up fallback 'claude-auto' priority cascade.
|
|
8
|
+
4. Ensures local API keys have wildcard permissions for combo routing.
|
|
8
9
|
"""
|
|
9
10
|
|
|
10
11
|
import sys
|
|
@@ -12,6 +13,45 @@ import json
|
|
|
12
13
|
import sqlite3
|
|
13
14
|
from pathlib import Path
|
|
14
15
|
|
|
16
|
+
MODELS_CONFIG = [
|
|
17
|
+
{
|
|
18
|
+
'id': 'combo-gemini-3.8-high',
|
|
19
|
+
'name': 'gemini-3.8-flash-high',
|
|
20
|
+
'aliases': ['flash-high', 'flash', 'high', 'gemini'],
|
|
21
|
+
'target': 'agy/gemini-3.8-flash-high'
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
'id': 'combo-gemini-3.8-med',
|
|
25
|
+
'name': 'gemini-3.8-flash-medium',
|
|
26
|
+
'aliases': ['flash-medium', 'medium', 'med'],
|
|
27
|
+
'target': 'agy/gemini-3.8-flash-medium'
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
'id': 'combo-gemini-3.8-low',
|
|
31
|
+
'name': 'gemini-3.8-flash-low',
|
|
32
|
+
'aliases': ['flash-low', 'low'],
|
|
33
|
+
'target': 'agy/gemini-3.8-flash-low'
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
'id': 'combo-claude-sonnet-4-6',
|
|
37
|
+
'name': 'claude-sonnet-4-6',
|
|
38
|
+
'aliases': ['sonnet', 'sonnet-4-6'],
|
|
39
|
+
'target': 'agy/claude-sonnet-4-6'
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
'id': 'combo-claude-opus-4-6',
|
|
43
|
+
'name': 'claude-opus-4-6-thinking',
|
|
44
|
+
'aliases': ['opus', 'opus-4-6', 'opus-thinking'],
|
|
45
|
+
'target': 'agy/claude-opus-4-6-thinking'
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
'id': 'combo-gpt-oss-120b',
|
|
49
|
+
'name': 'gpt-oss-120b-medium',
|
|
50
|
+
'aliases': ['gpt', 'oss', 'gpt-oss'],
|
|
51
|
+
'target': 'agy/gpt-oss-120b-medium'
|
|
52
|
+
}
|
|
53
|
+
]
|
|
54
|
+
|
|
15
55
|
def patch_omniroute_db():
|
|
16
56
|
db_path = Path.home() / ".omniroute" / "storage.sqlite"
|
|
17
57
|
if not db_path.exists():
|
|
@@ -22,11 +62,32 @@ def patch_omniroute_db():
|
|
|
22
62
|
cur = conn.cursor()
|
|
23
63
|
|
|
24
64
|
try:
|
|
25
|
-
# 1.
|
|
65
|
+
# 1. Setup exact model combos and alias mappings
|
|
66
|
+
for m in MODELS_CONFIG:
|
|
67
|
+
combo_data = {
|
|
68
|
+
'name': m['name'],
|
|
69
|
+
'strategy': 'priority',
|
|
70
|
+
'config': {'compatFilterFailOpen': True},
|
|
71
|
+
'models': [{'id': m['id'] + '-m', 'kind': 'model', 'model': m['target'], 'providerId': 'agy', 'weight': 10}],
|
|
72
|
+
'version': 2
|
|
73
|
+
}
|
|
74
|
+
cur.execute("""INSERT OR REPLACE INTO combos (id, name, data, updated_at, created_at)
|
|
75
|
+
VALUES (?, ?, ?, datetime('now'), datetime('now'))""",
|
|
76
|
+
(m['id'], m['name'], json.dumps(combo_data)))
|
|
77
|
+
|
|
78
|
+
cur.execute("""INSERT OR REPLACE INTO model_combo_mappings (id, pattern, combo_id, priority, enabled, description, created_at, updated_at)
|
|
79
|
+
VALUES (?, ?, ?, 20, 1, ?, datetime('now'), datetime('now'))""",
|
|
80
|
+
('map-' + m['name'], m['name'], m['id'], 'Exact ' + m['name']))
|
|
81
|
+
|
|
82
|
+
for alias in m['aliases']:
|
|
83
|
+
cur.execute("""INSERT OR REPLACE INTO model_combo_mappings (id, pattern, combo_id, priority, enabled, description, created_at, updated_at)
|
|
84
|
+
VALUES (?, ?, ?, 15, 1, ?, datetime('now'), datetime('now'))""",
|
|
85
|
+
('map-alias-' + alias, alias, m['id'], 'Alias ' + alias))
|
|
86
|
+
|
|
87
|
+
# 2. Patch claude-auto priority fallback combo
|
|
26
88
|
row = cur.execute("SELECT id, data FROM combos WHERE name = 'claude-auto'").fetchone()
|
|
89
|
+
auto_id = "fc0a1ddb-af40-4c9d-b9ce-7e8166c3ddde"
|
|
27
90
|
if not row:
|
|
28
|
-
print("[-] Combo 'claude-auto' not found in database. Initializing default structure...")
|
|
29
|
-
combo_id = "claude-auto-default"
|
|
30
91
|
combo_data = {
|
|
31
92
|
"name": "claude-auto",
|
|
32
93
|
"strategy": "priority",
|
|
@@ -40,56 +101,42 @@ def patch_omniroute_db():
|
|
|
40
101
|
}
|
|
41
102
|
cur.execute(
|
|
42
103
|
"INSERT INTO combos (id, name, data, sort_order, created_at, updated_at) VALUES (?, ?, ?, 1, datetime('now'), datetime('now'))",
|
|
43
|
-
(
|
|
104
|
+
(auto_id, "claude-auto", json.dumps(combo_data))
|
|
44
105
|
)
|
|
45
106
|
else:
|
|
46
|
-
|
|
107
|
+
auto_id, raw_data = row
|
|
47
108
|
data = json.loads(raw_data)
|
|
48
|
-
|
|
49
|
-
# Ensure config has compatFilterFailOpen
|
|
50
109
|
if "config" not in data or not isinstance(data["config"], dict):
|
|
51
110
|
data["config"] = {}
|
|
52
111
|
data["config"]["compatFilterFailOpen"] = True
|
|
53
|
-
|
|
54
|
-
# Restructure priority tiering
|
|
55
112
|
data["strategy"] = "priority"
|
|
56
113
|
data["models"] = [
|
|
57
114
|
{"id": "claude-auto-m1", "kind": "model", "model": "agy/gemini-3.8-flash-high", "providerId": "agy", "weight": 10},
|
|
58
115
|
{"id": "claude-auto-m2", "kind": "model", "model": "agy/claude-sonnet-4-6", "providerId": "agy", "weight": 5},
|
|
59
116
|
{"id": "claude-auto-m3", "kind": "model", "model": "agy/gemini-3.1-flash-lite", "providerId": "agy", "weight": 1}
|
|
60
117
|
]
|
|
61
|
-
|
|
62
118
|
cur.execute("UPDATE combos SET data = ?, updated_at = datetime('now') WHERE name = 'claude-auto'", (json.dumps(data),))
|
|
63
119
|
|
|
64
|
-
#
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
(
|
|
70
|
-
json.dumps(["*", "combo/*", "claude-auto", "auto/*"]),
|
|
71
|
-
json.dumps(["admin", "manage", "read", "write"]),
|
|
72
|
-
key_val
|
|
73
|
-
)
|
|
74
|
-
)
|
|
120
|
+
# Fallback mappings for generic legacy requests
|
|
121
|
+
cur.execute("""INSERT OR REPLACE INTO model_combo_mappings (id, pattern, combo_id, priority, enabled, description, created_at, updated_at)
|
|
122
|
+
VALUES ('map-claude-fallback-sonnet', 'claude-3-5-sonnet*', ?, 5, 1, 'Default Sonnet to Auto', datetime('now'), datetime('now'))""", (auto_id,))
|
|
123
|
+
cur.execute("""INSERT OR REPLACE INTO model_combo_mappings (id, pattern, combo_id, priority, enabled, description, created_at, updated_at)
|
|
124
|
+
VALUES ('map-claude-fallback-opus', 'claude-opus-5*', ?, 5, 1, 'Default Opus to Auto', datetime('now'), datetime('now'))""", (auto_id,))
|
|
75
125
|
|
|
76
|
-
# 3.
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
("map-claude-opus", "claude-opus*", combo_id),
|
|
81
|
-
]
|
|
82
|
-
for map_id, pattern, cid in mappings:
|
|
126
|
+
# 3. Grant wildcard combo permissions to all local API keys
|
|
127
|
+
all_combos = [m['name'] for m in MODELS_CONFIG] + [a for m in MODELS_CONFIG for a in m['aliases']] + ['claude-auto', '*', 'combo/*', 'auto/*']
|
|
128
|
+
keys = cur.execute("SELECT key FROM api_keys").fetchall()
|
|
129
|
+
for (key_val,) in keys:
|
|
83
130
|
cur.execute(
|
|
84
|
-
"
|
|
85
|
-
|
|
86
|
-
(map_id, pattern, cid)
|
|
131
|
+
"UPDATE api_keys SET allowed_combos = ?, scopes = ? WHERE key = ?",
|
|
132
|
+
(json.dumps(all_combos), json.dumps(["admin", "manage", "read", "write"]), key_val)
|
|
87
133
|
)
|
|
88
134
|
|
|
89
135
|
conn.commit()
|
|
90
136
|
print("[+] OmniRoute SQLite database successfully patched:")
|
|
91
|
-
print(" -
|
|
92
|
-
print(" - '
|
|
137
|
+
print(" - 6 exact Antigravity models and aliases mapped")
|
|
138
|
+
print(" - 'claude-auto' cascade configured (Gemini 3.8 Flash High -> Sonnet 4.6 -> Flash Lite)")
|
|
139
|
+
print(" - 'compatFilterFailOpen' enabled across all combos")
|
|
93
140
|
print(" - Local API key permissions synchronized")
|
|
94
141
|
return True
|
|
95
142
|
|