neoagent 2.3.1-beta.103 → 2.3.1-beta.104
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/lib/manager.js
CHANGED
|
@@ -797,7 +797,7 @@ async function cmdLoginClaudeCode() {
|
|
|
797
797
|
const data = JSON.parse(raw);
|
|
798
798
|
const token = data?.claudeAiOauthTokens?.accessToken;
|
|
799
799
|
if (token) {
|
|
800
|
-
upsertEnvValue('
|
|
800
|
+
upsertEnvValue('CLAUDE_CODE_OAUTH_TOKEN', token);
|
|
801
801
|
logOk('Imported access token from Claude CLI credentials store');
|
|
802
802
|
logInfo('Restarting NeoAgent to apply credentials...');
|
|
803
803
|
cmdRestart();
|
|
@@ -806,13 +806,34 @@ async function cmdLoginClaudeCode() {
|
|
|
806
806
|
} catch { }
|
|
807
807
|
}
|
|
808
808
|
|
|
809
|
-
//
|
|
809
|
+
// Browser-based PKCE OAuth flow.
|
|
810
|
+
// client_id is the metadata URL per claude.ai's dynamic client registration.
|
|
811
|
+
// Redirect URIs registered: http://localhost/callback and http://127.0.0.1/callback (port 80).
|
|
812
|
+
// Per RFC 8252 §7.3, servers SHOULD allow any loopback port — we try high ports first
|
|
813
|
+
// and fall back to 80 if everything else is occupied.
|
|
810
814
|
const http = require('http');
|
|
811
815
|
const { URL: NodeURL } = require('url');
|
|
816
|
+
const net = require('net');
|
|
812
817
|
|
|
813
|
-
const clientId = '
|
|
814
|
-
const
|
|
815
|
-
|
|
818
|
+
const clientId = 'https://claude.ai/oauth/claude-code-client-metadata';
|
|
819
|
+
const SCOPES = 'user:inference user:profile org:create_api_key user:sessions:claude_code offline_access';
|
|
820
|
+
|
|
821
|
+
// Find a free port (prefer high ports to avoid permission issues; fall back to 80)
|
|
822
|
+
const preferredPorts = [65432, 58080, 54321, 49152, 80];
|
|
823
|
+
let redirectPort = null;
|
|
824
|
+
|
|
825
|
+
for (const p of preferredPorts) {
|
|
826
|
+
const free = await new Promise((res) => {
|
|
827
|
+
const probe = net.createServer();
|
|
828
|
+
probe.listen(p, '127.0.0.1', () => { probe.close(() => res(true)); });
|
|
829
|
+
probe.on('error', () => res(false));
|
|
830
|
+
});
|
|
831
|
+
if (free) { redirectPort = p; break; }
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
if (!redirectPort) throw new Error('Could not find a free local port for the OAuth callback.');
|
|
835
|
+
|
|
836
|
+
const redirectUri = `http://127.0.0.1${redirectPort === 80 ? '' : `:${redirectPort}`}/callback`;
|
|
816
837
|
|
|
817
838
|
// Generate PKCE verifier and challenge
|
|
818
839
|
const codeVerifier = crypto.randomBytes(48).toString('base64url');
|
|
@@ -827,7 +848,7 @@ async function cmdLoginClaudeCode() {
|
|
|
827
848
|
authUrl.searchParams.set('response_type', 'code');
|
|
828
849
|
authUrl.searchParams.set('client_id', clientId);
|
|
829
850
|
authUrl.searchParams.set('redirect_uri', redirectUri);
|
|
830
|
-
authUrl.searchParams.set('scope',
|
|
851
|
+
authUrl.searchParams.set('scope', SCOPES);
|
|
831
852
|
authUrl.searchParams.set('code_challenge', codeChallenge);
|
|
832
853
|
authUrl.searchParams.set('code_challenge_method', 'S256');
|
|
833
854
|
authUrl.searchParams.set('state', state);
|
|
@@ -851,7 +872,7 @@ async function cmdLoginClaudeCode() {
|
|
|
851
872
|
|
|
852
873
|
const server = http.createServer((req, res) => {
|
|
853
874
|
try {
|
|
854
|
-
const reqUrl = new NodeURL(req.url,
|
|
875
|
+
const reqUrl = new NodeURL(req.url, redirectUri);
|
|
855
876
|
const code = reqUrl.searchParams.get('code');
|
|
856
877
|
const returnedState = reqUrl.searchParams.get('state');
|
|
857
878
|
const error = reqUrl.searchParams.get('error');
|
|
@@ -897,7 +918,7 @@ async function cmdLoginClaudeCode() {
|
|
|
897
918
|
});
|
|
898
919
|
|
|
899
920
|
logInfo('Exchanging authorization code for access token...');
|
|
900
|
-
const tokenRes = await fetch('https://claude.ai/
|
|
921
|
+
const tokenRes = await fetch('https://claude.ai/oauth/token', {
|
|
901
922
|
method: 'POST',
|
|
902
923
|
headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' },
|
|
903
924
|
body: JSON.stringify({
|
|
@@ -920,11 +941,11 @@ async function cmdLoginClaudeCode() {
|
|
|
920
941
|
throw new Error('Token exchange succeeded but no access_token was returned.');
|
|
921
942
|
}
|
|
922
943
|
|
|
923
|
-
upsertEnvValue('
|
|
944
|
+
upsertEnvValue('CLAUDE_CODE_OAUTH_TOKEN', accessToken);
|
|
924
945
|
if (tokenData.refresh_token) {
|
|
925
946
|
upsertEnvValue('CLAUDE_CODE_REFRESH_TOKEN', tokenData.refresh_token);
|
|
926
947
|
}
|
|
927
|
-
logOk('Saved Claude Code
|
|
948
|
+
logOk('Saved Claude Code OAuth token to .env');
|
|
928
949
|
logInfo('Restarting NeoAgent to apply credentials...');
|
|
929
950
|
cmdRestart();
|
|
930
951
|
}
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
2f506dae7123235dcafdcda0f78d6a13
|
|
@@ -37,6 +37,6 @@ _flutter.buildConfig = {"engineRevision":"42d3d75a56efe1a2e9902f52dc8006099c45d9
|
|
|
37
37
|
|
|
38
38
|
_flutter.loader.load({
|
|
39
39
|
serviceWorkerSettings: {
|
|
40
|
-
serviceWorkerVersion: "
|
|
40
|
+
serviceWorkerVersion: "2650676693" /* Flutter's service worker is deprecated and will be removed in a future Flutter release. */
|
|
41
41
|
}
|
|
42
42
|
});
|
|
@@ -129338,7 +129338,7 @@ r===$&&A.b()
|
|
|
129338
129338
|
o.push(A.ii(p,A.iY(!1,new A.a3(B.tM,A.dT(new A.cI(B.he,new A.a5V(r,p),p),p,p),p),!1,B.I,!0),p,p,0,0,0,p))}r=!1
|
|
129339
129339
|
if(!s.ay)if(!s.ch){r=s.e
|
|
129340
129340
|
r===$&&A.b()
|
|
129341
|
-
r=B.b.t("
|
|
129341
|
+
r=B.b.t("mpacvqjv-54ec71e").length!==0&&r.b}if(r){r=s.d
|
|
129342
129342
|
r===$&&A.b()
|
|
129343
129343
|
r=r.ag&&!r.V?84:0
|
|
129344
129344
|
q=s.e
|
|
@@ -134146,7 +134146,7 @@ $S:236}
|
|
|
134146
134146
|
A.Ys.prototype={}
|
|
134147
134147
|
A.Rr.prototype={
|
|
134148
134148
|
mT(a){var s=this
|
|
134149
|
-
if(B.b.t("
|
|
134149
|
+
if(B.b.t("mpacvqjv-54ec71e").length===0||s.a!=null)return
|
|
134150
134150
|
s.A5()
|
|
134151
134151
|
s.a=A.q1(B.PP,new A.b58(s))},
|
|
134152
134152
|
A5(){var s=0,r=A.l(t.H),q,p=2,o=[],n=this,m,l,k,j,i,h,g,f
|
|
@@ -134164,7 +134164,7 @@ if(!t.f.b(k)){s=1
|
|
|
134164
134164
|
break}i=J.Z(k,"buildId")
|
|
134165
134165
|
h=i==null?null:B.b.t(J.r(i))
|
|
134166
134166
|
j=h==null?"":h
|
|
134167
|
-
if(J.bm(j)===0||J.d(j,"
|
|
134167
|
+
if(J.bm(j)===0||J.d(j,"mpacvqjv-54ec71e")){s=1
|
|
134168
134168
|
break}n.b=!0
|
|
134169
134169
|
n.D()
|
|
134170
134170
|
p=2
|
|
@@ -134181,7 +134181,7 @@ case 2:return A.i(o.at(-1),r)}})
|
|
|
134181
134181
|
return A.k($async$A5,r)},
|
|
134182
134182
|
vb(){var s=0,r=A.l(t.H),q,p=2,o=[],n=this,m,l,k,j,i,h,g,f,e,d,c,b,a,a0,a1
|
|
134183
134183
|
var $async$vb=A.h(function(a2,a3){if(a2===1){o.push(a3)
|
|
134184
|
-
s=p}for(;;)switch(s){case 0:if(B.b.t("
|
|
134184
|
+
s=p}for(;;)switch(s){case 0:if(B.b.t("mpacvqjv-54ec71e").length===0||n.c){s=1
|
|
134185
134185
|
break}n.c=!0
|
|
134186
134186
|
n.D()
|
|
134187
134187
|
p=4
|
|
@@ -33,7 +33,7 @@ class ClaudeCodeProvider extends AnthropicProvider {
|
|
|
33
33
|
'claude-haiku-4-5-20251001': 200000,
|
|
34
34
|
};
|
|
35
35
|
|
|
36
|
-
const authToken = config.apiKey || process.env.
|
|
36
|
+
const authToken = config.apiKey || process.env.CLAUDE_CODE_OAUTH_TOKEN || readClaudeCliToken();
|
|
37
37
|
if (!authToken) {
|
|
38
38
|
console.warn('[ClaudeCode] No access token. Run `neoagent login claude-code` to authenticate.');
|
|
39
39
|
}
|
|
@@ -83,7 +83,7 @@ const AI_PROVIDER_DEFINITIONS = Object.freeze({
|
|
|
83
83
|
id: 'claude-code',
|
|
84
84
|
label: 'Claude Code',
|
|
85
85
|
description: 'Claude models via Claude Code subscription. Login with `neoagent login claude-code`.',
|
|
86
|
-
envKey: '
|
|
86
|
+
envKey: 'CLAUDE_CODE_OAUTH_TOKEN',
|
|
87
87
|
supportsApiKey: true,
|
|
88
88
|
supportsBaseUrl: false,
|
|
89
89
|
defaultEnabled: false,
|