@kweaver-ai/kweaver-sdk 0.6.5 → 0.6.7
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 +5 -2
- package/README.zh.md +4 -2
- package/dist/api/toolboxes.js +4 -4
- package/dist/auth/eacp-modify-password.d.ts +25 -0
- package/dist/auth/eacp-modify-password.js +84 -0
- package/dist/auth/oauth.d.ts +65 -21
- package/dist/auth/oauth.js +216 -220
- package/dist/cli.js +2 -1
- package/dist/commands/auth.js +259 -94
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/package.json +1 -11
package/dist/commands/auth.js
CHANGED
|
@@ -1,18 +1,8 @@
|
|
|
1
1
|
import { isNoAuth } from "../config/no-auth.js";
|
|
2
|
-
import { autoSelectBusinessDomain, clearPlatformSession, deletePlatform, deleteUser, getActiveUser, getConfigDir, getCurrentPlatform, getPlatformAlias, hasPlatform, listPlatforms, listUserProfiles, loadClientConfig, loadTokenConfig, resolveBusinessDomain, resolvePlatformIdentifier, resolveUserId, saveNoAuthPlatform, setActiveUser, setCurrentPlatform, setPlatformAlias, } from "../config/store.js";
|
|
2
|
+
import { autoSelectBusinessDomain, clearPlatformSession, deletePlatform, deleteUser, getActiveUser, getConfigDir, getCurrentPlatform, getPlatformAlias, hasPlatform, listPlatforms, listUserProfiles, loadClientConfig, loadTokenConfig, loadUserTokenConfig, resolveBusinessDomain, resolvePlatformIdentifier, resolveUserId, saveNoAuthPlatform, setActiveUser, setCurrentPlatform, setPlatformAlias, } from "../config/store.js";
|
|
3
3
|
import { decodeJwtPayload } from "../config/jwt.js";
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
async function isPlaywrightPackageResolvable() {
|
|
7
|
-
try {
|
|
8
|
-
const modName = "playwright";
|
|
9
|
-
await import(/* webpackIgnore: true */ modName);
|
|
10
|
-
return true;
|
|
11
|
-
}
|
|
12
|
-
catch {
|
|
13
|
-
return false;
|
|
14
|
-
}
|
|
15
|
-
}
|
|
4
|
+
import { eacpModifyPassword } from "../auth/eacp-modify-password.js";
|
|
5
|
+
import { buildCopyCommand, formatHttpError, InitialPasswordChangeRequiredError, normalizeBaseUrl, oauth2Login, oauth2PasswordSigninLogin, promptForUsername, promptForPassword, refreshTokenLogin, } from "../auth/oauth.js";
|
|
16
6
|
export async function runAuthCommand(args) {
|
|
17
7
|
const target = args[0];
|
|
18
8
|
const rest = args.slice(1);
|
|
@@ -28,6 +18,7 @@ kweaver auth users [url|alias] List all user profiles (with usernames) for
|
|
|
28
18
|
kweaver auth switch [url|alias] --user <id|username> Switch active user for a platform
|
|
29
19
|
kweaver auth logout [url|alias] [--user <id>] Logout (clear local token)
|
|
30
20
|
kweaver auth delete <url|alias> [--user <id>] Delete saved credentials
|
|
21
|
+
kweaver auth change-password [<url>] [-u <account>] [-o <old>] [-n <new>] Change password
|
|
31
22
|
|
|
32
23
|
Login options:
|
|
33
24
|
--alias <name> Save platform with a short alias (use with use / status / logout)
|
|
@@ -39,24 +30,25 @@ Login options:
|
|
|
39
30
|
Requires --client-id and --client-secret.
|
|
40
31
|
Get these from the callback page after browser login or \`auth export\`.
|
|
41
32
|
--port <n> Local callback port (default: 9010). Use when 9010 is occupied.
|
|
42
|
-
--no-browser Do not open a browser
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
-
|
|
46
|
-
|
|
47
|
-
--
|
|
33
|
+
--no-browser Do not open a browser. Without -u/-p: print the auth URL and prompt for the
|
|
34
|
+
callback URL or code (stdin). With -u and/or -p: route through HTTP sign-in
|
|
35
|
+
(any missing credential is prompted; password is hidden when stdin is a TTY).
|
|
36
|
+
-u, --username Username for HTTP /oauth2/signin (POST). If -p is omitted, password is prompted.
|
|
37
|
+
-p, --password Password for HTTP /oauth2/signin (POST). If -u is omitted, username is prompted.
|
|
38
|
+
--http-signin Force HTTP /oauth2/signin (no browser). Missing -u/-p are prompted from stdin.
|
|
39
|
+
--new-password <pwd> After HTTP sign-in error 401001017 (initial password), set the new password non-interactively, then retry login.
|
|
48
40
|
--insecure, -k Skip TLS certificate verification (self-signed / dev HTTPS only)
|
|
49
41
|
--no-auth Save platform without OAuth (servers with no authentication). Same as detecting OAuth 404 during login.`);
|
|
50
42
|
return 0;
|
|
51
43
|
}
|
|
52
44
|
if (target === "login") {
|
|
53
45
|
if (rest[0] === "--help" || rest[0] === "-h") {
|
|
54
|
-
console.log(`kweaver auth login <platform-url> [--alias <name>] [--no-auth] [--no-browser] [-u user] [-p pass] [--
|
|
46
|
+
console.log(`kweaver auth login <platform-url> [--alias <name>] [--no-auth] [--no-browser] [-u user] [-p pass] [--new-password <pwd>] [--http-signin] [--refresh-token T --client-id ID --client-secret S]`);
|
|
55
47
|
return 0;
|
|
56
48
|
}
|
|
57
49
|
const url = rest[0];
|
|
58
50
|
if (!url || url.startsWith("-")) {
|
|
59
|
-
console.error("Usage: kweaver auth login <platform-url> [--alias <name>] [-u user] [-p pass]
|
|
51
|
+
console.error("Usage: kweaver auth login <platform-url> [--alias <name>] [-u user] [-p pass]");
|
|
60
52
|
return 1;
|
|
61
53
|
}
|
|
62
54
|
return runAuthCommand([url, ...rest.slice(1)]);
|
|
@@ -73,14 +65,16 @@ Login options:
|
|
|
73
65
|
if (target === "switch") {
|
|
74
66
|
return runAuthSwitchCommand(rest);
|
|
75
67
|
}
|
|
68
|
+
if (target === "change-password") {
|
|
69
|
+
return runAuthChangePasswordCommand(rest);
|
|
70
|
+
}
|
|
76
71
|
const LOGIN_SUBCOMMANDS = new Set(["status", "list", "use", "delete", "logout", "export", "whoami", "users", "switch"]);
|
|
77
72
|
if (target && !LOGIN_SUBCOMMANDS.has(target)) {
|
|
78
73
|
try {
|
|
79
74
|
const normalizedTarget = normalizeBaseUrl(target);
|
|
80
75
|
const alias = readOption(args, "--alias");
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
const usePlaywright = args.includes("--playwright");
|
|
76
|
+
let username = readOption(args, "--username") ?? readOption(args, "-u");
|
|
77
|
+
let password = readOption(args, "--password") ?? readOption(args, "-p");
|
|
84
78
|
const httpSignin = args.includes("--http-signin");
|
|
85
79
|
const oauthProduct = readOption(args, "--oauth-product");
|
|
86
80
|
const signinPublicKeyFile = readOption(args, "--signin-public-key-file");
|
|
@@ -92,6 +86,7 @@ Login options:
|
|
|
92
86
|
const tlsInsecure = args.includes("--insecure") || args.includes("-k");
|
|
93
87
|
const noAuth = args.includes("--no-auth");
|
|
94
88
|
const noBrowser = args.includes("--no-browser");
|
|
89
|
+
const newPasswordFlag = readOption(args, "--new-password");
|
|
95
90
|
if (args.includes("--redirect-uri")) {
|
|
96
91
|
console.error("Warning: --redirect-uri is deprecated and ignored. The redirect URI is always http://127.0.0.1:<port>/callback.");
|
|
97
92
|
}
|
|
@@ -99,13 +94,15 @@ Login options:
|
|
|
99
94
|
"--alias", "--client-id", "--client-secret", "--refresh-token",
|
|
100
95
|
"--port", "--no-browser", "--username", "-u", "--password", "-p",
|
|
101
96
|
"--http-signin",
|
|
97
|
+
"--new-password",
|
|
102
98
|
"--oauth-product",
|
|
103
99
|
"--signin-public-key-file",
|
|
104
|
-
"--
|
|
100
|
+
"--insecure", "-k", "--no-auth", "--redirect-uri",
|
|
105
101
|
]);
|
|
106
102
|
const KNOWN_VALUE_FLAGS = new Set([
|
|
107
103
|
"--alias", "--client-id", "--client-secret", "--refresh-token",
|
|
108
104
|
"--port", "--username", "-u", "--password", "-p", "--redirect-uri",
|
|
105
|
+
"--new-password",
|
|
109
106
|
"--oauth-product",
|
|
110
107
|
"--signin-public-key-file",
|
|
111
108
|
]);
|
|
@@ -130,30 +127,38 @@ Login options:
|
|
|
130
127
|
if (noAuth && noBrowser) {
|
|
131
128
|
console.error("--no-auth does not require a browser; --no-browser is ignored.");
|
|
132
129
|
}
|
|
133
|
-
if (noAuth && (username || password ||
|
|
134
|
-
console.error("--no-auth cannot be used with
|
|
130
|
+
if (noAuth && (username || password || httpSignin)) {
|
|
131
|
+
console.error("--no-auth cannot be used with HTTP sign-in or -u/-p.");
|
|
135
132
|
return 1;
|
|
136
133
|
}
|
|
137
|
-
if (
|
|
138
|
-
console.error("--
|
|
134
|
+
if (newPasswordFlag !== undefined && (!username || !password)) {
|
|
135
|
+
console.error("--new-password requires -u/--username and -p/--password (HTTP sign-in).");
|
|
139
136
|
return 1;
|
|
140
137
|
}
|
|
141
|
-
if (
|
|
142
|
-
|
|
143
|
-
|
|
138
|
+
if (noBrowser && httpSignin) {
|
|
139
|
+
// HTTP sign-in already runs without a browser; --no-browser is a no-op signal here.
|
|
140
|
+
console.error("--http-signin already runs without a browser; --no-browser is redundant and ignored.");
|
|
144
141
|
}
|
|
145
142
|
if (httpSignin && refreshToken) {
|
|
146
143
|
console.error("--http-signin cannot be used with --refresh-token.");
|
|
147
144
|
return 1;
|
|
148
145
|
}
|
|
149
|
-
if (httpSignin && (!username || !password)) {
|
|
150
|
-
console.error("--http-signin requires -u/--username and -p/--password.");
|
|
151
|
-
return 1;
|
|
152
|
-
}
|
|
153
146
|
if (noBrowser && refreshToken) {
|
|
154
147
|
console.error("--no-browser cannot be used with --refresh-token.");
|
|
155
148
|
return 1;
|
|
156
149
|
}
|
|
150
|
+
// Headless credential login: if the user signalled HTTP sign-in (--http-signin,
|
|
151
|
+
// or partial -u/-p, or --no-browser combined with -u/-p) but didn't provide both
|
|
152
|
+
// credentials inline, prompt for the missing one(s) on stderr. Password is read
|
|
153
|
+
// without echo when stdin is a TTY.
|
|
154
|
+
const wantsCredentialLogin = !noAuth && !refreshToken &&
|
|
155
|
+
(httpSignin || (noBrowser && (username || password)) || (!!username !== !!password));
|
|
156
|
+
if (wantsCredentialLogin) {
|
|
157
|
+
if (!username)
|
|
158
|
+
username = await promptForUsername("Username");
|
|
159
|
+
if (!password)
|
|
160
|
+
password = await promptForPassword("Password");
|
|
161
|
+
}
|
|
157
162
|
let token;
|
|
158
163
|
if (noAuth) {
|
|
159
164
|
token = saveNoAuthPlatform(normalizedTarget, { tlsInsecure });
|
|
@@ -169,30 +174,9 @@ Login options:
|
|
|
169
174
|
clientId, clientSecret, refreshToken, tlsInsecure,
|
|
170
175
|
});
|
|
171
176
|
}
|
|
172
|
-
else if (username && password && httpSignin) {
|
|
173
|
-
console.log("Logging in (HTTP /oauth2/signin)...");
|
|
174
|
-
token = await oauth2PasswordSigninLogin(normalizedTarget, {
|
|
175
|
-
username,
|
|
176
|
-
password,
|
|
177
|
-
tlsInsecure,
|
|
178
|
-
port: customPort,
|
|
179
|
-
clientId: clientId ?? undefined,
|
|
180
|
-
clientSecret: clientSecret ?? undefined,
|
|
181
|
-
oauthProduct: oauthProduct ?? undefined,
|
|
182
|
-
signinPublicKeyPemPath: signinPublicKeyFile ?? undefined,
|
|
183
|
-
});
|
|
184
|
-
}
|
|
185
|
-
else if (username && password && usePlaywright) {
|
|
186
|
-
console.log("Logging in (headless, Playwright)...");
|
|
187
|
-
token = await playwrightLogin(normalizedTarget, {
|
|
188
|
-
username,
|
|
189
|
-
password,
|
|
190
|
-
tlsInsecure,
|
|
191
|
-
port: customPort,
|
|
192
|
-
});
|
|
193
|
-
}
|
|
194
177
|
else if (username && password) {
|
|
195
|
-
|
|
178
|
+
console.log("Logging in (HTTP /oauth2/signin)...");
|
|
179
|
+
token = await loginWithInitialPasswordRecovery(normalizedTarget, {
|
|
196
180
|
username,
|
|
197
181
|
password,
|
|
198
182
|
tlsInsecure,
|
|
@@ -201,40 +185,7 @@ Login options:
|
|
|
201
185
|
clientSecret: clientSecret ?? undefined,
|
|
202
186
|
oauthProduct: oauthProduct ?? undefined,
|
|
203
187
|
signinPublicKeyPemPath: signinPublicKeyFile ?? undefined,
|
|
204
|
-
};
|
|
205
|
-
console.log("Logging in (HTTP /oauth2/signin)...");
|
|
206
|
-
try {
|
|
207
|
-
token = await oauth2PasswordSigninLogin(normalizedTarget, signinOpts);
|
|
208
|
-
}
|
|
209
|
-
catch (err) {
|
|
210
|
-
if (!isStudiowebShellUnavailableError(err)) {
|
|
211
|
-
throw err;
|
|
212
|
-
}
|
|
213
|
-
const playwrightOk = await isPlaywrightPackageResolvable();
|
|
214
|
-
if (playwrightOk) {
|
|
215
|
-
process.stderr.write("Studio web sign-in shell is not available; falling back to Playwright headless login.\n");
|
|
216
|
-
console.log("Logging in (headless, Playwright)...");
|
|
217
|
-
token = await playwrightLogin(normalizedTarget, {
|
|
218
|
-
username,
|
|
219
|
-
password,
|
|
220
|
-
tlsInsecure,
|
|
221
|
-
port: customPort,
|
|
222
|
-
});
|
|
223
|
-
}
|
|
224
|
-
else {
|
|
225
|
-
console.error("Studio web sign-in shell is not available on this platform, and the Playwright package is not installed.");
|
|
226
|
-
console.error("Install Playwright for headless browser login: npm install playwright && npx playwright install chromium");
|
|
227
|
-
console.error("Alternatively, use OAuth without credentials:");
|
|
228
|
-
console.error(` kweaver auth login ${normalizedTarget} --no-browser`);
|
|
229
|
-
throw err;
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
else if (usePlaywright) {
|
|
234
|
-
console.log("Opening browser for login (Playwright)...");
|
|
235
|
-
token = await playwrightLogin(normalizedTarget, {
|
|
236
|
-
tlsInsecure, port: customPort,
|
|
237
|
-
});
|
|
188
|
+
}, { newPasswordFlag, tlsInsecure });
|
|
238
189
|
}
|
|
239
190
|
else {
|
|
240
191
|
if (noBrowser) {
|
|
@@ -456,7 +407,7 @@ Login options:
|
|
|
456
407
|
console.log(`Run \`kweaver auth login ${logoutTarget}\` to sign in again.`);
|
|
457
408
|
return 0;
|
|
458
409
|
}
|
|
459
|
-
console.error("Usage: kweaver auth login <platform-url> [--alias <name>] [-u user] [-p pass]
|
|
410
|
+
console.error("Usage: kweaver auth login <platform-url> [--alias <name>] [-u user] [-p pass]");
|
|
460
411
|
console.error(" kweaver auth whoami [platform-url|alias] [--json]");
|
|
461
412
|
console.error(" kweaver auth export [platform-url|alias] [--json]");
|
|
462
413
|
console.error(" kweaver auth status [platform-url|alias]");
|
|
@@ -684,3 +635,217 @@ function readOption(args, name) {
|
|
|
684
635
|
}
|
|
685
636
|
return args[index + 1];
|
|
686
637
|
}
|
|
638
|
+
const EACP_NEW_PWD_MIN = 6;
|
|
639
|
+
const EACP_NEW_PWD_MAX = 100;
|
|
640
|
+
function validateNewPasswordLengthForEacp(pwd) {
|
|
641
|
+
if (pwd.length < EACP_NEW_PWD_MIN || pwd.length > EACP_NEW_PWD_MAX) {
|
|
642
|
+
throw new Error(`New password must be between ${EACP_NEW_PWD_MIN} and ${EACP_NEW_PWD_MAX} characters.`);
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
function formatEacpModifyFailure(status, json, body) {
|
|
646
|
+
if (json && typeof json === "object" && json !== null) {
|
|
647
|
+
const o = json;
|
|
648
|
+
const msg = typeof o.message === "string" && o.message.trim() !== ""
|
|
649
|
+
? o.message
|
|
650
|
+
: typeof o.cause === "string"
|
|
651
|
+
? o.cause
|
|
652
|
+
: "";
|
|
653
|
+
if (msg)
|
|
654
|
+
return `Password change failed (HTTP ${status}): ${msg}`;
|
|
655
|
+
}
|
|
656
|
+
return `Password change failed (HTTP ${status}): ${body.slice(0, 500)}`;
|
|
657
|
+
}
|
|
658
|
+
async function promptYesNo(message) {
|
|
659
|
+
const { createInterface } = await import("node:readline");
|
|
660
|
+
const rl = createInterface({ input: process.stdin, output: process.stderr });
|
|
661
|
+
return await new Promise((resolve, reject) => {
|
|
662
|
+
let answered = false;
|
|
663
|
+
rl.on("close", () => {
|
|
664
|
+
if (!answered)
|
|
665
|
+
reject(new Error("Login cancelled."));
|
|
666
|
+
});
|
|
667
|
+
rl.question(`${message} [Y/n] `, (answer) => {
|
|
668
|
+
answered = true;
|
|
669
|
+
rl.close();
|
|
670
|
+
const a = answer.trim().toLowerCase();
|
|
671
|
+
resolve(a === "" || a === "y" || a === "yes");
|
|
672
|
+
});
|
|
673
|
+
});
|
|
674
|
+
}
|
|
675
|
+
async function loginWithInitialPasswordRecovery(normalizedTarget, signinOpts, recovery) {
|
|
676
|
+
try {
|
|
677
|
+
return await oauth2PasswordSigninLogin(normalizedTarget, signinOpts);
|
|
678
|
+
}
|
|
679
|
+
catch (e) {
|
|
680
|
+
if (!(e instanceof InitialPasswordChangeRequiredError))
|
|
681
|
+
throw e;
|
|
682
|
+
const err = e;
|
|
683
|
+
const account = signinOpts.username;
|
|
684
|
+
const oldPwd = signinOpts.password;
|
|
685
|
+
let newPwd = recovery.newPasswordFlag;
|
|
686
|
+
if (newPwd !== undefined) {
|
|
687
|
+
validateNewPasswordLengthForEacp(newPwd);
|
|
688
|
+
}
|
|
689
|
+
else if (process.stderr.isTTY) {
|
|
690
|
+
process.stderr.write(`${err.serverMessage}\n`);
|
|
691
|
+
const ok = await promptYesNo(`Account "${account}" must change its initial password. Proceed with password change now?`);
|
|
692
|
+
if (!ok) {
|
|
693
|
+
throw new Error("Initial password change declined. Run again when ready.");
|
|
694
|
+
}
|
|
695
|
+
const np1 = await promptForPassword("New password (6-100 characters)");
|
|
696
|
+
const np2 = await promptForPassword("Confirm new password");
|
|
697
|
+
if (np1 !== np2) {
|
|
698
|
+
throw new Error("New passwords do not match.");
|
|
699
|
+
}
|
|
700
|
+
validateNewPasswordLengthForEacp(np1);
|
|
701
|
+
newPwd = np1;
|
|
702
|
+
}
|
|
703
|
+
else {
|
|
704
|
+
throw new Error("This account must change its initial password (error 401001017). Re-run with --new-password <password> (non-interactive).");
|
|
705
|
+
}
|
|
706
|
+
const mod = await eacpModifyPassword(normalizedTarget, {
|
|
707
|
+
account,
|
|
708
|
+
oldPassword: oldPwd,
|
|
709
|
+
newPassword: newPwd,
|
|
710
|
+
tlsInsecure: recovery.tlsInsecure,
|
|
711
|
+
});
|
|
712
|
+
if (!mod.ok) {
|
|
713
|
+
throw new Error(formatEacpModifyFailure(mod.status, mod.json, mod.body));
|
|
714
|
+
}
|
|
715
|
+
return oauth2PasswordSigninLogin(normalizedTarget, {
|
|
716
|
+
...signinOpts,
|
|
717
|
+
password: newPwd,
|
|
718
|
+
});
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
async function runAuthChangePasswordCommand(args) {
|
|
722
|
+
if (args[0] === "--help" || args[0] === "-h") {
|
|
723
|
+
console.log(`kweaver auth change-password [<platform-url>] [options]
|
|
724
|
+
|
|
725
|
+
Change the EACP account password via POST /api/eacp/v1/auth1/modifypassword.
|
|
726
|
+
No saved OAuth token is required.
|
|
727
|
+
|
|
728
|
+
Options:
|
|
729
|
+
-u, --account <name> Account / login name. On TTY, defaults to the current active user
|
|
730
|
+
after a confirmation prompt. Required in non-interactive mode.
|
|
731
|
+
-o, --old-password <pwd> Current password (omit on TTY to be prompted)
|
|
732
|
+
-n, --new-password <pwd> New password, 6-100 characters (omit on TTY to be prompted)
|
|
733
|
+
--insecure, -k Skip TLS certificate verification (defaults to the platform's saved
|
|
734
|
+
preference set at login with -k; pass to override per-call)
|
|
735
|
+
|
|
736
|
+
Platform URL is optional; defaults to the current active platform (kweaver auth use).`);
|
|
737
|
+
return 0;
|
|
738
|
+
}
|
|
739
|
+
const KNOWN_CP_FLAGS = new Set([
|
|
740
|
+
"-u",
|
|
741
|
+
"--account",
|
|
742
|
+
"-o",
|
|
743
|
+
"--old-password",
|
|
744
|
+
"-n",
|
|
745
|
+
"--new-password",
|
|
746
|
+
"--insecure",
|
|
747
|
+
"-k",
|
|
748
|
+
"--help",
|
|
749
|
+
"-h",
|
|
750
|
+
]);
|
|
751
|
+
const KNOWN_CP_VALUE = new Set([
|
|
752
|
+
"-u",
|
|
753
|
+
"--account",
|
|
754
|
+
"-o",
|
|
755
|
+
"--old-password",
|
|
756
|
+
"-n",
|
|
757
|
+
"--new-password",
|
|
758
|
+
]);
|
|
759
|
+
// First positional (if present and not a flag) is the platform URL or alias.
|
|
760
|
+
const positional = args[0] && !args[0].startsWith("-") ? args[0] : undefined;
|
|
761
|
+
const flagArgs = positional ? args.slice(1) : args;
|
|
762
|
+
for (let i = 0; i < flagArgs.length; i++) {
|
|
763
|
+
const a = flagArgs[i];
|
|
764
|
+
if (a.startsWith("-") && !KNOWN_CP_FLAGS.has(a)) {
|
|
765
|
+
console.error(`Unknown option: ${a}`);
|
|
766
|
+
console.error("Run 'kweaver auth change-password --help' for usage.");
|
|
767
|
+
return 1;
|
|
768
|
+
}
|
|
769
|
+
if (KNOWN_CP_VALUE.has(a))
|
|
770
|
+
i++;
|
|
771
|
+
}
|
|
772
|
+
const normalizedTarget = resolvePlatformArg(positional ? [positional] : []);
|
|
773
|
+
if (!normalizedTarget) {
|
|
774
|
+
console.error("No platform resolved. Pass <platform-url|alias> or run `kweaver auth use <url|alias>` first.");
|
|
775
|
+
return 1;
|
|
776
|
+
}
|
|
777
|
+
let account = readOption(flagArgs, "--account") ?? readOption(flagArgs, "-u");
|
|
778
|
+
let oldPassword = readOption(flagArgs, "--old-password") ?? readOption(flagArgs, "-o");
|
|
779
|
+
let newPassword = readOption(flagArgs, "--new-password") ?? readOption(flagArgs, "-n");
|
|
780
|
+
const explicitTlsInsecure = flagArgs.includes("--insecure") || flagArgs.includes("-k");
|
|
781
|
+
// Resolve the active user's saved token; we use it both to default the account
|
|
782
|
+
// and to inherit the platform's saved tlsInsecure preference (set at login with -k).
|
|
783
|
+
const activeUser = getActiveUser(normalizedTarget);
|
|
784
|
+
const activeToken = activeUser ? loadUserTokenConfig(normalizedTarget, activeUser) : null;
|
|
785
|
+
const tlsInsecure = explicitTlsInsecure || activeToken?.tlsInsecure === true;
|
|
786
|
+
const interactive = process.stdin.isTTY === true && process.stderr.isTTY === true;
|
|
787
|
+
const accountWasExplicit = !!account?.trim();
|
|
788
|
+
// Account resolution (with safety guards):
|
|
789
|
+
// - Explicit -u always wins.
|
|
790
|
+
// - Non-TTY + no -u: REFUSE. Silently using the active account in CI / pipes
|
|
791
|
+
// would let scripts modify the wrong account's password without warning.
|
|
792
|
+
// - TTY + no -u: default to the active user's displayName, but require an
|
|
793
|
+
// interactive yes/no confirmation before proceeding.
|
|
794
|
+
if (!accountWasExplicit) {
|
|
795
|
+
const defaultAccount = activeToken?.displayName?.trim();
|
|
796
|
+
if (!defaultAccount) {
|
|
797
|
+
console.error("Cannot determine current account on the platform. Pass -u/--account, or log in first (kweaver auth login ...).");
|
|
798
|
+
return 1;
|
|
799
|
+
}
|
|
800
|
+
if (!interactive) {
|
|
801
|
+
console.error(`Refusing to default account in non-interactive mode. Pass -u/--account explicitly (would have used "${defaultAccount}").`);
|
|
802
|
+
return 1;
|
|
803
|
+
}
|
|
804
|
+
const ok = await promptYesNo(`Change password for account "${defaultAccount}" on ${normalizedTarget}?`);
|
|
805
|
+
if (!ok) {
|
|
806
|
+
console.error("Aborted by user.");
|
|
807
|
+
return 1;
|
|
808
|
+
}
|
|
809
|
+
account = defaultAccount;
|
|
810
|
+
}
|
|
811
|
+
const trimmedAccount = account.trim();
|
|
812
|
+
try {
|
|
813
|
+
if (!interactive) {
|
|
814
|
+
if (!oldPassword || !newPassword) {
|
|
815
|
+
console.error("In non-interactive mode, --old-password and --new-password are required.");
|
|
816
|
+
return 1;
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
else {
|
|
820
|
+
if (!oldPassword) {
|
|
821
|
+
oldPassword = await promptForPassword("Old password");
|
|
822
|
+
}
|
|
823
|
+
if (!newPassword) {
|
|
824
|
+
const n1 = await promptForPassword("New password (6-100 characters)");
|
|
825
|
+
const n2 = await promptForPassword("Confirm new password");
|
|
826
|
+
if (n1 !== n2) {
|
|
827
|
+
console.error("New passwords do not match.");
|
|
828
|
+
return 1;
|
|
829
|
+
}
|
|
830
|
+
newPassword = n1;
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
validateNewPasswordLengthForEacp(newPassword);
|
|
834
|
+
const result = await eacpModifyPassword(normalizedTarget, {
|
|
835
|
+
account: trimmedAccount,
|
|
836
|
+
oldPassword: oldPassword,
|
|
837
|
+
newPassword: newPassword,
|
|
838
|
+
tlsInsecure,
|
|
839
|
+
});
|
|
840
|
+
if (!result.ok) {
|
|
841
|
+
console.error(`${formatEacpModifyFailure(result.status, result.json, result.body)} (account="${trimmedAccount}")`);
|
|
842
|
+
return 1;
|
|
843
|
+
}
|
|
844
|
+
console.log(`Password changed for ${trimmedAccount} on ${normalizedTarget}`);
|
|
845
|
+
return 0;
|
|
846
|
+
}
|
|
847
|
+
catch (e) {
|
|
848
|
+
console.error(`${formatHttpError(e)}\n(account="${trimmedAccount}")`);
|
|
849
|
+
return 1;
|
|
850
|
+
}
|
|
851
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -62,4 +62,5 @@ export type { TokenConfig, ContextLoaderEntry, ContextLoaderConfig, } from "./co
|
|
|
62
62
|
export type { UserProfile } from "./config/store.js";
|
|
63
63
|
export { NO_AUTH_TOKEN, isNoAuth, saveNoAuthPlatform, autoSelectBusinessDomain, getConfigDir, getCurrentPlatform, getActiveUser, setActiveUser, listUsers, listUserProfiles, resolveUserId, extractUserId, } from "./config/store.js";
|
|
64
64
|
export { decodeJwtPayload, extractUserIdFromJwt } from "./config/jwt.js";
|
|
65
|
-
export { DEFAULT_SIGNIN_RSA_MODULUS_HEX, oauth2PasswordSigninLogin, parseSigninPageHtmlProps, rsaModulusHexToSpkiPem, STUDIOWEB_LOGIN_PUBLIC_KEY_PEM, } from "./auth/oauth.js";
|
|
65
|
+
export { DEFAULT_SIGNIN_RSA_MODULUS_HEX, InitialPasswordChangeRequiredError, oauth2PasswordSigninLogin, parseSigninPageHtmlProps, rsaModulusHexToSpkiPem, STUDIOWEB_LOGIN_PUBLIC_KEY_PEM, } from "./auth/oauth.js";
|
|
66
|
+
export { eacpModifyPassword, encryptModifyPwd } from "./auth/eacp-modify-password.js";
|
package/dist/index.js
CHANGED
|
@@ -50,4 +50,5 @@ export { NO_AUTH_TOKEN, isNoAuth, saveNoAuthPlatform, autoSelectBusinessDomain,
|
|
|
50
50
|
// ── JWT utilities ─────────────────────────────────────────────────────────────
|
|
51
51
|
export { decodeJwtPayload, extractUserIdFromJwt } from "./config/jwt.js";
|
|
52
52
|
// ── OAuth (advanced — CLI uses these internally; optional for custom login tools) ─
|
|
53
|
-
export { DEFAULT_SIGNIN_RSA_MODULUS_HEX, oauth2PasswordSigninLogin, parseSigninPageHtmlProps, rsaModulusHexToSpkiPem, STUDIOWEB_LOGIN_PUBLIC_KEY_PEM, } from "./auth/oauth.js";
|
|
53
|
+
export { DEFAULT_SIGNIN_RSA_MODULUS_HEX, InitialPasswordChangeRequiredError, oauth2PasswordSigninLogin, parseSigninPageHtmlProps, rsaModulusHexToSpkiPem, STUDIOWEB_LOGIN_PUBLIC_KEY_PEM, } from "./auth/oauth.js";
|
|
54
|
+
export { eacpModifyPassword, encryptModifyPwd } from "./auth/eacp-modify-password.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kweaver-ai/kweaver-sdk",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.7",
|
|
4
4
|
"description": "KWeaver TypeScript SDK — CLI tool and programmatic API for knowledge networks and Decision Agents.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -51,21 +51,11 @@
|
|
|
51
51
|
"@types/node": "^24.6.0",
|
|
52
52
|
"@types/react": "^19.2.14",
|
|
53
53
|
"@types/yargs": "^17.0.35",
|
|
54
|
-
"playwright": "^1.58.2",
|
|
55
54
|
"tsx": "^4.20.5",
|
|
56
55
|
"typescript": "^5.9.3"
|
|
57
56
|
},
|
|
58
|
-
"peerDependencies": {
|
|
59
|
-
"playwright": ">=1.40.0"
|
|
60
|
-
},
|
|
61
|
-
"peerDependenciesMeta": {
|
|
62
|
-
"playwright": {
|
|
63
|
-
"optional": true
|
|
64
|
-
}
|
|
65
|
-
},
|
|
66
57
|
"dependencies": {
|
|
67
58
|
"@kweaver-ai/bkn": "^0.1.0",
|
|
68
|
-
"@playwright/test": "^1.58.2",
|
|
69
59
|
"chardet": "^2.1.1",
|
|
70
60
|
"columnify": "^1.6.0",
|
|
71
61
|
"csv-parse": "^6.2.1",
|