@cleocode/cleo 2026.6.2 → 2026.6.3
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/dist/cli/index.js +38 -13
- package/dist/cli/index.js.map +2 -2
- package/package.json +12 -12
package/dist/cli/index.js
CHANGED
|
@@ -55892,7 +55892,7 @@ import {
|
|
|
55892
55892
|
refreshPkceToken
|
|
55893
55893
|
} from "@cleocode/core/llm/oauth/pkce.js";
|
|
55894
55894
|
import { getKimiCodeMshHeaders } from "@cleocode/core/llm/provider-registry/builtin/kimi-code.js";
|
|
55895
|
-
import { getProviderProfile } from "@cleocode/core/llm/provider-registry/index.js";
|
|
55895
|
+
import { getProviderProfile, listProviders } from "@cleocode/core/llm/provider-registry/index.js";
|
|
55896
55896
|
async function runLlmLogin(provider, opts) {
|
|
55897
55897
|
const meta = { operation: "llm.login", timestamp: (/* @__PURE__ */ new Date()).toISOString() };
|
|
55898
55898
|
const profile = await getProviderProfile(provider);
|
|
@@ -55901,31 +55901,43 @@ async function runLlmLogin(provider, opts) {
|
|
|
55901
55901
|
return _runKimiCodeLogin(opts, meta);
|
|
55902
55902
|
}
|
|
55903
55903
|
if (oauthMode === "pkce") {
|
|
55904
|
-
return _runPkceLogin(
|
|
55904
|
+
return _runPkceLogin(profile.name, profile.oauth, opts, meta);
|
|
55905
55905
|
}
|
|
55906
55906
|
return {
|
|
55907
55907
|
success: false,
|
|
55908
55908
|
error: {
|
|
55909
55909
|
code: "E_NOT_IMPLEMENTED",
|
|
55910
55910
|
codeName: "E_NOT_IMPLEMENTED",
|
|
55911
|
-
message: `OAuth login for '${provider}' is not yet wired.
|
|
55911
|
+
message: `OAuth login for '${provider}' is not yet wired. ${await _supportedOauthProvidersHint()} For any other provider, add an API key with 'cleo llm add <provider> --api-key-stdin'.`
|
|
55912
55912
|
},
|
|
55913
55913
|
meta
|
|
55914
55914
|
};
|
|
55915
55915
|
}
|
|
55916
|
+
async function _supportedOauthProvidersHint() {
|
|
55917
|
+
try {
|
|
55918
|
+
const profiles = await listProviders();
|
|
55919
|
+
const oauthable = profiles.flatMap((p) => p.oauth ? [`'${p.name}' (${p.oauth.mode})`] : []);
|
|
55920
|
+
return oauthable.length > 0 ? `Providers with OAuth login: ${oauthable.join(", ")}.` : "No providers currently expose OAuth login.";
|
|
55921
|
+
} catch {
|
|
55922
|
+
return "Providers with OAuth login: 'anthropic' (pkce), 'openai' (pkce), 'kimi-code' (device-code).";
|
|
55923
|
+
}
|
|
55924
|
+
}
|
|
55916
55925
|
async function _runPkceLogin(provider, oauthCfg, opts, meta) {
|
|
55917
55926
|
const { codeVerifier, codeChallenge } = await generatePkcePair();
|
|
55918
55927
|
const state = _generateState();
|
|
55919
55928
|
const isHeadless = opts.headless || process.env["CLEO_HEADLESS"] === "1";
|
|
55920
|
-
const
|
|
55921
|
-
const
|
|
55929
|
+
const fixedPort = isHeadless ? null : _parseFixedLoopbackPort(oauthCfg.redirectUri);
|
|
55930
|
+
const port = isHeadless ? 0 : fixedPort ?? await _findFreePort();
|
|
55931
|
+
const randomRedirect = `http://localhost:${port}/callback`;
|
|
55932
|
+
const redirectUri = isHeadless ? oauthCfg.redirectUri ?? "http://localhost" : fixedPort != null ? oauthCfg.redirectUri ?? randomRedirect : randomRedirect;
|
|
55922
55933
|
const authUrl = buildAuthorizationUrl({
|
|
55923
55934
|
authorizationEndpoint: oauthCfg.authorizationEndpoint ?? "",
|
|
55924
55935
|
clientId: oauthCfg.clientId,
|
|
55925
55936
|
redirectUri,
|
|
55926
55937
|
scope: oauthCfg.scope ?? "",
|
|
55927
55938
|
codeChallenge,
|
|
55928
|
-
state
|
|
55939
|
+
state,
|
|
55940
|
+
extraParams: oauthCfg.extraAuthParams
|
|
55929
55941
|
});
|
|
55930
55942
|
let code;
|
|
55931
55943
|
if (isHeadless) {
|
|
@@ -55962,6 +55974,7 @@ async function _runPkceLogin(provider, oauthCfg, opts, meta) {
|
|
|
55962
55974
|
process.stderr.write("\r Authorization approved. \n\n");
|
|
55963
55975
|
const label = opts.label ?? "oauth-login";
|
|
55964
55976
|
const expiresAt = typeof tokens.expiresIn === "number" ? Date.now() + tokens.expiresIn * 1e3 : void 0;
|
|
55977
|
+
const oauthExtraHeaders = provider === "anthropic" ? { "anthropic-beta": "oauth-2025-04-20" } : void 0;
|
|
55965
55978
|
try {
|
|
55966
55979
|
await addCredential({
|
|
55967
55980
|
provider,
|
|
@@ -55972,7 +55985,7 @@ async function _runPkceLogin(provider, oauthCfg, opts, meta) {
|
|
|
55972
55985
|
expiresAt,
|
|
55973
55986
|
priority: 10,
|
|
55974
55987
|
source: "oauth-pkce",
|
|
55975
|
-
|
|
55988
|
+
...oauthExtraHeaders ? { extraHeaders: oauthExtraHeaders } : {}
|
|
55976
55989
|
});
|
|
55977
55990
|
} catch (err) {
|
|
55978
55991
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -55992,6 +56005,18 @@ async function _runPkceLogin(provider, oauthCfg, opts, meta) {
|
|
|
55992
56005
|
meta
|
|
55993
56006
|
};
|
|
55994
56007
|
}
|
|
56008
|
+
function _parseFixedLoopbackPort(redirectUri) {
|
|
56009
|
+
if (!redirectUri) return null;
|
|
56010
|
+
try {
|
|
56011
|
+
const u = new URL(redirectUri);
|
|
56012
|
+
const isLoopback = u.hostname === "localhost" || u.hostname === "127.0.0.1";
|
|
56013
|
+
if (!isLoopback || !u.port) return null;
|
|
56014
|
+
const port = Number(u.port);
|
|
56015
|
+
return Number.isInteger(port) && port > 0 ? port : null;
|
|
56016
|
+
} catch {
|
|
56017
|
+
return null;
|
|
56018
|
+
}
|
|
56019
|
+
}
|
|
55995
56020
|
async function _headlessPkceFlow(provider, authUrl) {
|
|
55996
56021
|
process.stderr.write("\n");
|
|
55997
56022
|
process.stderr.write(` Provider: ${provider}
|
|
@@ -56278,11 +56303,11 @@ __export(llm_exports, {
|
|
|
56278
56303
|
});
|
|
56279
56304
|
import { pushWarning as pushWarning7 } from "@cleocode/core";
|
|
56280
56305
|
async function getListProviders() {
|
|
56281
|
-
const { listProviders } = await import(
|
|
56306
|
+
const { listProviders: listProviders2 } = await import(
|
|
56282
56307
|
/* webpackIgnore: true */
|
|
56283
56308
|
"@cleocode/core/llm/provider-registry"
|
|
56284
56309
|
);
|
|
56285
|
-
return
|
|
56310
|
+
return listProviders2;
|
|
56286
56311
|
}
|
|
56287
56312
|
async function readApiKeyFromStdin() {
|
|
56288
56313
|
if (process.stdin.isTTY) return "";
|
|
@@ -56593,8 +56618,8 @@ var init_llm3 = __esm({
|
|
|
56593
56618
|
}
|
|
56594
56619
|
},
|
|
56595
56620
|
async run() {
|
|
56596
|
-
const
|
|
56597
|
-
const profiles = await
|
|
56621
|
+
const listProviders2 = await getListProviders();
|
|
56622
|
+
const profiles = await listProviders2();
|
|
56598
56623
|
const providers = profiles.map((p) => ({
|
|
56599
56624
|
name: p.name,
|
|
56600
56625
|
displayName: p.displayName,
|
|
@@ -56654,12 +56679,12 @@ var init_llm3 = __esm({
|
|
|
56654
56679
|
loginCommand = defineCommand({
|
|
56655
56680
|
meta: {
|
|
56656
56681
|
name: "login",
|
|
56657
|
-
description: "Authenticate
|
|
56682
|
+
description: "Authenticate an LLM provider via OAuth. PKCE (browser): anthropic, openai/codex. Device-code: kimi-code. Example: `cleo llm login openai`. For any other provider use `cleo llm add <provider> --api-key-stdin`. Prompts/URLs go to stderr; the result is a human line on a terminal or a JSON envelope when piped/--json."
|
|
56658
56683
|
},
|
|
56659
56684
|
args: {
|
|
56660
56685
|
provider: {
|
|
56661
56686
|
type: "positional",
|
|
56662
|
-
description: "Provider to authenticate
|
|
56687
|
+
description: "Provider to authenticate: anthropic | openai | codex | kimi-code",
|
|
56663
56688
|
required: true
|
|
56664
56689
|
},
|
|
56665
56690
|
label: {
|