@closedrouter/cli 1.1.0 → 1.1.2
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 +1 -1
- package/dist/commands/start.d.ts +1 -0
- package/dist/commands/start.d.ts.map +1 -1
- package/dist/index.js +26 -11
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -142,7 +142,7 @@ cr start opencode --model gpt-4o-mini
|
|
|
142
142
|
cr start claude --model claude-sonnet-4-6 -- --resume
|
|
143
143
|
```
|
|
144
144
|
|
|
145
|
-
Claude Code sends an explicit `claude_oauth` provider choice to ClosedRouter so its requests use the local Claude subscription bridge. Codex gets a separate `~/.codex/closedrouter-launch.config.toml` profile using the Responses API.
|
|
145
|
+
Claude Code sends an explicit `claude_oauth` provider choice to ClosedRouter so its requests use the local Claude subscription bridge. Codex gets a separate `~/.codex/closedrouter-launch.config.toml` profile using the Responses API. Gemini gets an app-owned authentication settings file under `~/.closedrouter/`, and OpenCode receives inline launch configuration. The launchers do not change the tools' main configuration files.
|
|
146
146
|
|
|
147
147
|
Cursor SDK keys can also be connected in the web account dialog or imported from `CURSOR_API_KEY`. ClosedRouter discovers models using Cursor's SDK and sends text-only, tools-disabled SDK runs through its normal gateway and telemetry path. This credential type is separate from Cursor OAuth tokens imported from the editor.
|
|
148
148
|
|
package/dist/commands/start.d.ts
CHANGED
|
@@ -26,6 +26,7 @@ export interface LaunchPlan {
|
|
|
26
26
|
}
|
|
27
27
|
export declare function isGatewayModelAvailable(availableModels: string[], model: string): boolean;
|
|
28
28
|
export declare function buildLaunchPlan(tool: CliTool, serverUrl: string, apiKey: string, model: string, toolArgs?: string[], homeDir?: string, executablePath?: string): LaunchPlan;
|
|
29
|
+
export declare function modelSupportsHarness(model: Record<string, any>, tool: StartTool): boolean;
|
|
29
30
|
export declare function startCommand(options?: StartCommandOptions): Promise<void>;
|
|
30
31
|
export {};
|
|
31
32
|
//# sourceMappingURL=start.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../../src/commands/start.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAWH,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,GAAG,UAAU,CAAC;AAC7E,KAAK,OAAO,GAAG,SAAS,CAAC;AAEzB,MAAM,WAAW,mBAAmB;IAClC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,UAAU,UAAU;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB,UAAU,CAAC,EAAE,UAAU,CAAC;CACzB;AAED,wBAAgB,uBAAuB,CAAC,eAAe,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAEzF;AA6BD,wBAAgB,eAAe,CAC7B,IAAI,EAAE,OAAO,EACb,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,QAAQ,GAAE,MAAM,EAAO,EACvB,OAAO,SAAY,EACnB,cAAc,CAAC,EAAE,MAAM,GACtB,UAAU,
|
|
1
|
+
{"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../../src/commands/start.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAWH,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,GAAG,UAAU,CAAC;AAC7E,KAAK,OAAO,GAAG,SAAS,CAAC;AAEzB,MAAM,WAAW,mBAAmB;IAClC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,UAAU,UAAU;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB,UAAU,CAAC,EAAE,UAAU,CAAC;CACzB;AAED,wBAAgB,uBAAuB,CAAC,eAAe,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAEzF;AA6BD,wBAAgB,eAAe,CAC7B,IAAI,EAAE,OAAO,EACb,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,QAAQ,GAAE,MAAM,EAAO,EACvB,OAAO,SAAY,EACnB,cAAc,CAAC,EAAE,MAAM,GACtB,UAAU,CAqGZ;AAmBD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,IAAI,EAAE,SAAS,GAAG,OAAO,CAMzF;AA4ED,wBAAsB,YAAY,CAAC,OAAO,GAAE,mBAAwB,GAAG,OAAO,CAAC,IAAI,CAAC,CAsCnF"}
|
package/dist/index.js
CHANGED
|
@@ -8657,7 +8657,7 @@ function buildLaunchPlan(tool, serverUrl, apiKey, model, toolArgs = [], homeDir
|
|
|
8657
8657
|
assertNoManagedCodexArgs(toolArgs);
|
|
8658
8658
|
const codexHome = process.env.CODEX_HOME || join9(homeDir, ".codex");
|
|
8659
8659
|
const profileName = "closedrouter-launch";
|
|
8660
|
-
const
|
|
8660
|
+
const configPath = join9(codexHome, `${profileName}.config.toml`);
|
|
8661
8661
|
const configLines = [
|
|
8662
8662
|
`model = ${tomlString(model)}`,
|
|
8663
8663
|
`model_provider = ${tomlString(profileName)}`,
|
|
@@ -8675,7 +8675,7 @@ function buildLaunchPlan(tool, serverUrl, apiKey, model, toolArgs = [], homeDir
|
|
|
8675
8675
|
command,
|
|
8676
8676
|
args: ["--profile", profileName, ...toolArgs],
|
|
8677
8677
|
env,
|
|
8678
|
-
configFile: { path:
|
|
8678
|
+
configFile: { path: configPath, contents: configLines.join(`
|
|
8679
8679
|
`) }
|
|
8680
8680
|
};
|
|
8681
8681
|
}
|
|
@@ -8683,7 +8683,19 @@ function buildLaunchPlan(tool, serverUrl, apiKey, model, toolArgs = [], homeDir
|
|
|
8683
8683
|
env.GEMINI_API_KEY = apiKey;
|
|
8684
8684
|
env.GEMINI_MODEL = model;
|
|
8685
8685
|
env.GOOGLE_GEMINI_BASE_URL = baseUrl;
|
|
8686
|
-
|
|
8686
|
+
const configPath = join9(homeDir, ".closedrouter", "gemini-launch.settings.json");
|
|
8687
|
+
env.GEMINI_CLI_SYSTEM_SETTINGS_PATH = configPath;
|
|
8688
|
+
return {
|
|
8689
|
+
tool,
|
|
8690
|
+
command,
|
|
8691
|
+
args: [...toolArgs],
|
|
8692
|
+
env,
|
|
8693
|
+
configFile: {
|
|
8694
|
+
path: configPath,
|
|
8695
|
+
contents: `${JSON.stringify({ security: { auth: { selectedType: "gemini-api-key" } } }, null, 2)}
|
|
8696
|
+
`
|
|
8697
|
+
}
|
|
8698
|
+
};
|
|
8687
8699
|
}
|
|
8688
8700
|
if (tool === "aider") {
|
|
8689
8701
|
env.OPENAI_API_BASE = `${baseUrl}/v1`;
|
|
@@ -8695,7 +8707,6 @@ function buildLaunchPlan(tool, serverUrl, apiKey, model, toolArgs = [], homeDir
|
|
|
8695
8707
|
env
|
|
8696
8708
|
};
|
|
8697
8709
|
}
|
|
8698
|
-
const configPath = join9(homeDir, ".closedrouter", "opencode-launch.json");
|
|
8699
8710
|
const config = {
|
|
8700
8711
|
$schema: "https://opencode.ai/config.json",
|
|
8701
8712
|
provider: {
|
|
@@ -8710,15 +8721,13 @@ function buildLaunchPlan(tool, serverUrl, apiKey, model, toolArgs = [], homeDir
|
|
|
8710
8721
|
}
|
|
8711
8722
|
}
|
|
8712
8723
|
};
|
|
8713
|
-
env.
|
|
8724
|
+
env.OPENCODE_CONFIG_CONTENT = JSON.stringify(config);
|
|
8714
8725
|
env.CLOSEDROUTER_API_KEY = apiKey;
|
|
8715
8726
|
return {
|
|
8716
8727
|
tool,
|
|
8717
8728
|
command,
|
|
8718
8729
|
args: ["--model", `closedrouter/${model}`, ...toolArgs],
|
|
8719
|
-
env
|
|
8720
|
-
configFile: { path: configPath, contents: `${JSON.stringify(config, null, 2)}
|
|
8721
|
-
` }
|
|
8730
|
+
env
|
|
8722
8731
|
};
|
|
8723
8732
|
}
|
|
8724
8733
|
function writeOwnedConfig(file) {
|
|
@@ -8737,6 +8746,12 @@ function writeOwnedConfig(file) {
|
|
|
8737
8746
|
function modelId(model) {
|
|
8738
8747
|
return String(model.id || model.name || "");
|
|
8739
8748
|
}
|
|
8749
|
+
function modelSupportsHarness(model, tool) {
|
|
8750
|
+
if (tool === "claude")
|
|
8751
|
+
return true;
|
|
8752
|
+
const parameters = model.supported_parameters;
|
|
8753
|
+
return (model.status === undefined || model.status === "available") && (model.available_tool_account_count === undefined || model.available_tool_account_count > 0) && (!Array.isArray(parameters) || parameters.includes("tools"));
|
|
8754
|
+
}
|
|
8740
8755
|
async function selectTool(tool) {
|
|
8741
8756
|
const cleaned = tool?.toLowerCase();
|
|
8742
8757
|
if (cleaned) {
|
|
@@ -8813,7 +8828,7 @@ async function startCommand(options = {}) {
|
|
|
8813
8828
|
const apiKey = await ensurePlatformKey(tool, client, options);
|
|
8814
8829
|
client.setApiKey(apiKey);
|
|
8815
8830
|
const models = await client.listGatewayModels({ preferApiKey: true });
|
|
8816
|
-
const availableModels = models.map(modelId).filter(Boolean).sort();
|
|
8831
|
+
const availableModels = models.filter((item) => modelSupportsHarness(item, tool)).map(modelId).filter(Boolean).sort();
|
|
8817
8832
|
let model = options.model?.trim();
|
|
8818
8833
|
if (!model) {
|
|
8819
8834
|
if (availableModels.length === 0) {
|
|
@@ -8831,7 +8846,7 @@ async function startCommand(options = {}) {
|
|
|
8831
8846
|
model = String(choice);
|
|
8832
8847
|
}
|
|
8833
8848
|
if (!isGatewayModelAvailable(availableModels, model)) {
|
|
8834
|
-
throw new Error(`Model '${model}' is not available
|
|
8849
|
+
throw new Error(`Model '${model}' is not available for ${tool} with this platform key. Agent clients require a provider that supports gateway function tools. Choose another model from ClosedRouter's model catalog.`);
|
|
8835
8850
|
}
|
|
8836
8851
|
if (tool === "claude")
|
|
8837
8852
|
await ensureClaudeBridge(client, serverUrl, apiKey);
|
|
@@ -8888,7 +8903,7 @@ process.on("warning", (warning) => {
|
|
|
8888
8903
|
console.warn(warning.name, warning.message);
|
|
8889
8904
|
});
|
|
8890
8905
|
var program2 = new Command;
|
|
8891
|
-
program2.name("closedrouter").description("ClosedRouter CLI: Import local AI subscriptions & API keys into your shared token pool").version("1.1.
|
|
8906
|
+
program2.name("closedrouter").description("ClosedRouter CLI: Import local AI subscriptions & API keys into your shared token pool").version("1.1.2").option("-s, --server <url>", "ClosedRouter server base URL (default: http://localhost:8000)").action(async (options) => {
|
|
8892
8907
|
await onboardCommand({ server: options.server });
|
|
8893
8908
|
});
|
|
8894
8909
|
program2.command("onboard").description("Run the full interactive onboarding wizard").option("-s, --server <url>", "ClosedRouter server base URL").option("-a, --all", "Automatically import all discovered accounts").option("--shared", "Contribute accounts to the shared team pool").action(async (options) => {
|
package/package.json
CHANGED