@closedrouter/cli 1.1.14 → 1.1.16
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
CHANGED
|
@@ -155,7 +155,7 @@ On macOS, Claude uses a compatible Electron runtime installed by Cockpit, or the
|
|
|
155
155
|
|
|
156
156
|
Antigravity uses the CCPA envelope conversion documented in `~/Projects/antigravity-mods`. The launcher briefly opens a loopback Node inspector and installs its language-server hook. A browser debugger replaces the launched renderer's model catalog with native custom-model entries, then detaches. Each entry carries a distinct routing alias and a positive context and output budget. The picker lists the supported pool models, and selecting one changes inference routing. App bundles and global hook configuration are not modified. Unsupported launcher builds fail before opening; `--open-only` remains available.
|
|
157
157
|
|
|
158
|
-
Cursor, Antigravity, and the hooked Claude view display the colored ClosedRouter logo beside model names. White-core neon-blue lightning bolts
|
|
158
|
+
Cursor, Antigravity, and the hooked Claude view display the colored ClosedRouter logo beside model names. White-core neon-blue lightning bolts fly around the active chat model button along a 3D orbit for a brief pass every five seconds, and immediately on hover or keyboard focus. The bolts keep their orientation; perspective enlarges the front pass and the button occludes the rear pass. Reduced-motion preferences keep the mark static; hidden windows pause the effect. Codex uses its custom model catalog and provider labels. Launch requests also carry the configured model ID in system context so native client identity prompts do not misidentify the underlying model. The relay resolves the requested model on each turn and preserves tools and streamed responses. Unsupported model IDs are rejected before forwarding. Catalogs are snapshots of the models available to the platform key at launch; provider quotas can change during a session.
|
|
159
159
|
|
|
160
160
|
macOS app bundles are discovered in `/Applications` and `~/Applications`. Common Windows and Linux installation paths are checked, with `--path` available for other installations. Live tests verified Cursor, Claude's Code and Cowork views, and Antigravity inference through ClosedRouter. Cursor and Antigravity switched between `gpt-5-nano` and `gpt-4.1-nano` in their native pickers. Cowork could answer through the gateway, but its workspace VM reported insufficient disk space on the test Mac; workspace actions were not verified. Gemma's full agent request previously received an upstream quota error. Desktop hooks fail closed when expected controllers change. See the [Codex provider configuration](https://developers.openai.com/codex/config-advanced) and [Electron fuse documentation](https://www.electronjs.org/docs/latest/tutorial/fuses) for configuration and inspector behavior.
|
|
161
161
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agy-desktop-account.d.ts","sourceRoot":"","sources":["../../src/commands/agy-desktop-account.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAEhE;8EAC8E;AAC9E,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,sBAAsB,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"agy-desktop-account.d.ts","sourceRoot":"","sources":["../../src/commands/agy-desktop-account.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAEhE;8EAC8E;AAC9E,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,sBAAsB,GAAG,MAAM,CAe/F"}
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
export declare const CLOSEDROUTER_LOGO = "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><rect width=\"24\" height=\"24\" rx=\"6\" fill=\"#D4FE51\"/><path d=\"M16.68 7.82A6.5 6.5 0 1 0 16.68 16.18\" fill=\"none\" stroke=\"#04080A\" stroke-width=\"2.6\" stroke-linecap=\"round\"/><circle cx=\"18.2\" cy=\"12\" r=\"1.9\" fill=\"#04080A\"/></svg>";
|
|
2
2
|
import type { DesktopAccountIdentity } from "./desktop-account";
|
|
3
|
-
export declare const CLOSEDROUTER_ELECTRIC_CSS = "\n[data-closedrouter-logo]{position:relative;isolation:isolate}\n[data-closedrouter-charged-control]{position:relative;perspective:
|
|
3
|
+
export declare const CLOSEDROUTER_ELECTRIC_CSS = "\n[data-closedrouter-logo]{position:relative;isolation:isolate}\n[data-closedrouter-charged-control]{position:relative;perspective:400px;transform-style:preserve-3d;overflow:visible!important}\n[data-closedrouter-electric]{position:absolute;inset:0;pointer-events:none;transform-style:preserve-3d;opacity:0}\n[data-cr-lightning-orbit]{position:absolute;left:50%;top:50%;width:0;height:0;transform-style:preserve-3d}\n[data-cr-lightning-bolt]{position:absolute;width:20px;height:30px;left:-10px;top:-15px;overflow:visible;filter:drop-shadow(0 0 3px #58caff) drop-shadow(0 0 7px #159aff)}\n@media(prefers-reduced-motion:no-preference){[data-closedrouter-electric]{opacity:1}}\n";
|
|
4
|
+
/** Position a bolt along a tilted orbit in world space. Perspective belongs to
|
|
5
|
+
* the button; the bolt keeps its orientation as its x, y and depth change. */
|
|
6
|
+
export declare function lightningOrbitKeyframes(width: number, height: number, phase: number): Keyframe[];
|
|
4
7
|
/** Add the provider mark to native controls without changing click handlers,
|
|
5
8
|
* model IDs, keyboard behavior, or the application's typography. */
|
|
6
|
-
export declare function installModelBranding(models: string[], artwork: string, electricCss: string): void;
|
|
9
|
+
export declare function installModelBranding(models: string[], artwork: string, electricCss: string, orbitKeyframes: typeof lightningOrbitKeyframes): void;
|
|
7
10
|
export declare function installProviderAccountUi(account: DesktopAccountIdentity, artwork: string): void;
|
|
8
11
|
export declare function modelBrandingHook(models: string[], account?: DesktopAccountIdentity): string;
|
|
9
12
|
//# sourceMappingURL=model-branding.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model-branding.d.ts","sourceRoot":"","sources":["../../src/commands/model-branding.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,iBAAiB,mUAAqS,CAAC;AACpU,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAEhE,eAAO,MAAM,yBAAyB,
|
|
1
|
+
{"version":3,"file":"model-branding.d.ts","sourceRoot":"","sources":["../../src/commands/model-branding.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,iBAAiB,mUAAqS,CAAC;AACpU,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAEhE,eAAO,MAAM,yBAAyB,wqBAOrC,CAAC;AAEF;8EAC8E;AAC9E,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,QAAQ,EAAE,CAiBhG;AAED;oEACoE;AACpE,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,cAAc,EAAE,OAAO,uBAAuB,GAAG,IAAI,CAsFjJ;AAED,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,sBAAsB,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAoC/F;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,OAAO,CAAC,EAAE,sBAAsB,GAAG,MAAM,CAS5F"}
|
package/dist/index.js
CHANGED
|
@@ -10191,7 +10191,7 @@ function patchAntigravityAccount(source, account) {
|
|
|
10191
10191
|
if (!onboarding.test(source))
|
|
10192
10192
|
throw new Error("This Antigravity build has an unsupported startup onboarding controller.");
|
|
10193
10193
|
source = source.replace(onboarding, "agentOnboardingState:2");
|
|
10194
|
-
return source;
|
|
10194
|
+
return "document.documentElement.dataset.closedrouterAccount='true';" + source;
|
|
10195
10195
|
}
|
|
10196
10196
|
|
|
10197
10197
|
// src/commands/agy-desktop-catalog.ts
|
|
@@ -10264,22 +10264,29 @@ app.on('web-contents-created', (_event, contents) => {
|
|
|
10264
10264
|
var CLOSEDROUTER_LOGO = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><rect width="24" height="24" rx="6" fill="#D4FE51"/><path d="M16.68 7.82A6.5 6.5 0 1 0 16.68 16.18" fill="none" stroke="#04080A" stroke-width="2.6" stroke-linecap="round"/><circle cx="18.2" cy="12" r="1.9" fill="#04080A"/></svg>';
|
|
10265
10265
|
var CLOSEDROUTER_ELECTRIC_CSS = `
|
|
10266
10266
|
[data-closedrouter-logo]{position:relative;isolation:isolate}
|
|
10267
|
-
[data-closedrouter-charged-control]{position:relative;perspective:
|
|
10267
|
+
[data-closedrouter-charged-control]{position:relative;perspective:400px;transform-style:preserve-3d;overflow:visible!important}
|
|
10268
10268
|
[data-closedrouter-electric]{position:absolute;inset:0;pointer-events:none;transform-style:preserve-3d;opacity:0}
|
|
10269
10269
|
[data-cr-lightning-orbit]{position:absolute;left:50%;top:50%;width:0;height:0;transform-style:preserve-3d}
|
|
10270
|
-
[data-cr-lightning-bolt]{position:absolute;width:
|
|
10271
|
-
[data-
|
|
10272
|
-
[data-cr-lightning-bolt="back"]{transform:rotateY(180deg) translateX(var(--cr-lightning-radius,70px)) rotateZ(24deg)}
|
|
10273
|
-
@keyframes cr-electric-depth{0%{opacity:0;transform:rotateX(22deg) rotateY(-150deg)}2%{opacity:1}8%{opacity:1;transform:rotateX(22deg) rotateY(25deg)}16%{opacity:.85;transform:rotateX(22deg) rotateY(210deg)}20%,100%{opacity:0;transform:rotateX(22deg) rotateY(210deg)}}
|
|
10274
|
-
@keyframes cr-electric-hover{0%{opacity:.1;transform:rotateX(-18deg) rotateY(-150deg)}2%{opacity:1}8%{opacity:1;transform:rotateX(-18deg) rotateY(25deg)}16%{opacity:.85;transform:rotateX(-18deg) rotateY(210deg)}20%,100%{opacity:0;transform:rotateX(-18deg) rotateY(210deg)}}
|
|
10275
|
-
@media(prefers-reduced-motion:no-preference){
|
|
10276
|
-
[data-cr-lightning-orbit]{animation:cr-electric-depth 5s linear infinite}
|
|
10277
|
-
[data-closedrouter-electric]{opacity:1}
|
|
10278
|
-
button:hover>[data-closedrouter-electric] [data-cr-lightning-orbit],button:focus-visible>[data-closedrouter-electric] [data-cr-lightning-orbit]{animation-name:cr-electric-hover}
|
|
10279
|
-
}
|
|
10280
|
-
html[data-closedrouter-page-hidden] [data-cr-lightning-orbit]{animation-play-state:paused}
|
|
10270
|
+
[data-cr-lightning-bolt]{position:absolute;width:20px;height:30px;left:-10px;top:-15px;overflow:visible;filter:drop-shadow(0 0 3px #58caff) drop-shadow(0 0 7px #159aff)}
|
|
10271
|
+
@media(prefers-reduced-motion:no-preference){[data-closedrouter-electric]{opacity:1}}
|
|
10281
10272
|
`;
|
|
10282
|
-
function
|
|
10273
|
+
function lightningOrbitKeyframes(width, height, phase) {
|
|
10274
|
+
const frames = [];
|
|
10275
|
+
for (let step = 0;step <= 40; step++) {
|
|
10276
|
+
const progress = step / 40;
|
|
10277
|
+
const angle = (progress + phase) * Math.PI * 2;
|
|
10278
|
+
const x = (width / 2 + 12) * Math.cos(angle);
|
|
10279
|
+
const y = (height / 2 + 6) * Math.sin(angle) * Math.sin(Math.PI / 15);
|
|
10280
|
+
const z = 46 * Math.sin(angle) * Math.cos(Math.PI / 15);
|
|
10281
|
+
const scale = 400 / (400 - z);
|
|
10282
|
+
const behindButton = z < -1 && Math.abs(x * scale) < width / 2 && Math.abs(y * scale) < height / 2;
|
|
10283
|
+
const fade = Math.min(1, progress * 20, (1 - progress) * 20);
|
|
10284
|
+
frames.push({ offset: progress / 5, transform: `translate3d(${x}px,${y}px,${z}px)`, opacity: behindButton ? 0 : fade * (z < 0 ? 0.55 : 1) });
|
|
10285
|
+
}
|
|
10286
|
+
frames.push({ ...frames[0], offset: 1, opacity: 0 });
|
|
10287
|
+
return frames;
|
|
10288
|
+
}
|
|
10289
|
+
function installModelBranding(models, artwork, electricCss, orbitKeyframes) {
|
|
10283
10290
|
if (document.querySelector("[data-closedrouter-branding]"))
|
|
10284
10291
|
return;
|
|
10285
10292
|
const marker = document.createElement("meta");
|
|
@@ -10288,10 +10295,36 @@ function installModelBranding(models, artwork, electricCss) {
|
|
|
10288
10295
|
const style = document.createElement("style");
|
|
10289
10296
|
style.textContent = electricCss;
|
|
10290
10297
|
document.head.append(style);
|
|
10298
|
+
const motion = matchMedia("(prefers-reduced-motion: reduce)");
|
|
10299
|
+
const charged = new Map;
|
|
10300
|
+
const animate = (button) => {
|
|
10301
|
+
const previous = charged.get(button) || [];
|
|
10302
|
+
const time = previous[0]?.currentTime;
|
|
10303
|
+
previous.forEach((animation) => animation.cancel());
|
|
10304
|
+
const { width, height } = button.getBoundingClientRect();
|
|
10305
|
+
const animations = motion.matches ? [] : [...button.querySelectorAll("[data-cr-lightning-bolt]")].map((bolt, index) => {
|
|
10306
|
+
const animation = bolt.animate(orbitKeyframes(width, height, index / 2), { duration: 5000, iterations: Infinity, easing: "linear" });
|
|
10307
|
+
if (typeof time === "number")
|
|
10308
|
+
animation.currentTime = time;
|
|
10309
|
+
if (document.hidden)
|
|
10310
|
+
animation.pause();
|
|
10311
|
+
return animation;
|
|
10312
|
+
});
|
|
10313
|
+
charged.set(button, animations);
|
|
10314
|
+
};
|
|
10315
|
+
const resize = new ResizeObserver((entries) => entries.forEach((entry) => animate(entry.target)));
|
|
10316
|
+
motion.addEventListener("change", () => charged.forEach((_animations, button) => animate(button)));
|
|
10291
10317
|
document.addEventListener("visibilitychange", () => {
|
|
10292
10318
|
document.documentElement.toggleAttribute("data-closedrouter-page-hidden", document.hidden);
|
|
10319
|
+
charged.forEach((animations) => animations.forEach((animation) => document.hidden ? animation.pause() : animation.play()));
|
|
10293
10320
|
});
|
|
10294
10321
|
const paint = () => {
|
|
10322
|
+
for (const [button, animations] of charged)
|
|
10323
|
+
if (!button.isConnected) {
|
|
10324
|
+
animations.forEach((animation) => animation.cancel());
|
|
10325
|
+
resize.unobserve(button);
|
|
10326
|
+
charged.delete(button);
|
|
10327
|
+
}
|
|
10295
10328
|
for (const element of document.querySelectorAll('button,[role="button"],[role="option"],[role="menuitem"],[role="menuitemradio"],[data-testid="model-selector-item"]')) {
|
|
10296
10329
|
const text = element.innerText.trim().split(`
|
|
10297
10330
|
`)[0];
|
|
@@ -10318,7 +10351,6 @@ function installModelBranding(models, artwork, electricCss) {
|
|
|
10318
10351
|
if (element.matches("button") && !element.closest('[role="menu"],[role="listbox"],[role="dialog"]') && document.querySelector('[contenteditable="true"],textarea')) {
|
|
10319
10352
|
logo.dataset.closedrouterSupercharged = "true";
|
|
10320
10353
|
element.dataset.closedrouterChargedControl = "true";
|
|
10321
|
-
element.style.setProperty("--cr-lightning-radius", `${Math.max(35, element.getBoundingClientRect().width / 2 + 10)}px`);
|
|
10322
10354
|
const layer = document.createElement("span");
|
|
10323
10355
|
layer.dataset.closedrouterElectric = "true";
|
|
10324
10356
|
layer.setAttribute("aria-hidden", "true");
|
|
@@ -10329,11 +10361,26 @@ function installModelBranding(models, artwork, electricCss) {
|
|
|
10329
10361
|
bolt.setAttribute("viewBox", "0 0 30 44");
|
|
10330
10362
|
bolt.setAttribute("data-cr-lightning-bolt", position);
|
|
10331
10363
|
const path = "M23 2 11 13 19 15 5 30 13 29 7 42 M11 13 3 11 M19 15 27 23";
|
|
10332
|
-
|
|
10364
|
+
for (const [color, width] of [["#42bdff", "4.2"], ["#f5fcff", "1.7"]]) {
|
|
10365
|
+
const line = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
10366
|
+
line.setAttribute("d", path);
|
|
10367
|
+
line.setAttribute("fill", "none");
|
|
10368
|
+
line.setAttribute("stroke", color);
|
|
10369
|
+
line.setAttribute("stroke-width", width);
|
|
10370
|
+
line.setAttribute("stroke-linecap", "round");
|
|
10371
|
+
line.setAttribute("stroke-linejoin", "round");
|
|
10372
|
+
bolt.append(line);
|
|
10373
|
+
}
|
|
10333
10374
|
orbit.append(bolt);
|
|
10334
10375
|
}
|
|
10335
10376
|
layer.append(orbit);
|
|
10336
10377
|
element.append(layer);
|
|
10378
|
+
const restart = () => charged.get(element)?.forEach((animation) => {
|
|
10379
|
+
animation.currentTime = 0;
|
|
10380
|
+
});
|
|
10381
|
+
element.addEventListener("mouseenter", restart);
|
|
10382
|
+
element.addEventListener("focus", restart);
|
|
10383
|
+
resize.observe(element);
|
|
10337
10384
|
}
|
|
10338
10385
|
element.prepend(logo);
|
|
10339
10386
|
}
|
|
@@ -10375,7 +10422,8 @@ function installProviderAccountUi(account, artwork) {
|
|
|
10375
10422
|
const paint = () => {
|
|
10376
10423
|
let providerSession = document.documentElement.dataset.closedrouterAccount === "true";
|
|
10377
10424
|
for (const button of document.querySelectorAll("button")) {
|
|
10378
|
-
|
|
10425
|
+
const text = button.innerText;
|
|
10426
|
+
if (!text.includes(account.name) || !(text.includes("Gateway") || providerSession && account.email && text.includes(account.email)))
|
|
10379
10427
|
continue;
|
|
10380
10428
|
providerSession = true;
|
|
10381
10429
|
document.documentElement.dataset.closedrouterAccount = "true";
|
|
@@ -10418,7 +10466,7 @@ function installProviderAccountUi(account, artwork) {
|
|
|
10418
10466
|
paint();
|
|
10419
10467
|
}
|
|
10420
10468
|
function modelBrandingHook(models, account) {
|
|
10421
|
-
const script = `(${installModelBranding.toString()})(${JSON.stringify(models)},${JSON.stringify(CLOSEDROUTER_LOGO)},${JSON.stringify(CLOSEDROUTER_ELECTRIC_CSS)});` + (account ? `(${installProviderAccountUi.toString()})(${JSON.stringify(account)},${JSON.stringify(CLOSEDROUTER_LOGO)})` : "");
|
|
10469
|
+
const script = `(${installModelBranding.toString()})(${JSON.stringify(models)},${JSON.stringify(CLOSEDROUTER_LOGO)},${JSON.stringify(CLOSEDROUTER_ELECTRIC_CSS)},${lightningOrbitKeyframes.toString()});` + (account ? `(${installProviderAccountUi.toString()})(${JSON.stringify(account)},${JSON.stringify(CLOSEDROUTER_LOGO)})` : "");
|
|
10422
10470
|
return `
|
|
10423
10471
|
require('electron').app.on('web-contents-created', (_event, contents) => {
|
|
10424
10472
|
contents.on('did-finish-load', () => {
|
package/package.json
CHANGED