poe-code 4.0.19 → 4.0.21
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/credentials.compile-check.d.ts +1 -0
- package/dist/credentials.compile-check.js +2 -0
- package/dist/credentials.compile-check.js.map +1 -0
- package/dist/credentials.d.ts +2 -0
- package/dist/credentials.js +2586 -0
- package/dist/credentials.js.map +7 -0
- package/dist/index.js +165 -59
- package/dist/index.js.map +3 -3
- package/dist/metafile.json +1 -1
- package/package.json +5 -1
- package/packages/poe-oauth/dist/index.d.ts +5 -2
- package/packages/poe-oauth/dist/index.js +3 -1
- package/packages/poe-oauth/dist/loopback-authorization.d.ts +7 -0
- package/packages/poe-oauth/dist/loopback-authorization.js +59 -26
- package/packages/poe-oauth/dist/oauth-client.d.ts +17 -0
- package/packages/poe-oauth/dist/oauth-client.js +70 -24
- package/packages/poe-oauth/dist/pkce.d.ts +2 -0
- package/packages/poe-oauth/dist/pkce.js +27 -1
package/dist/index.js
CHANGED
|
@@ -69270,6 +69270,35 @@ var init_authorization_state2 = __esm({
|
|
|
69270
69270
|
|
|
69271
69271
|
// packages/poe-oauth/src/loopback-authorization.ts
|
|
69272
69272
|
import http2 from "node:http";
|
|
69273
|
+
function validateOAuthAuthorizationCallback(options) {
|
|
69274
|
+
let url;
|
|
69275
|
+
try {
|
|
69276
|
+
url = typeof options.callbackUrl === "string" ? new URL(options.callbackUrl) : options.callbackUrl;
|
|
69277
|
+
} catch {
|
|
69278
|
+
throw new Error("Poe OAuth callbackUrl must be an absolute URL.");
|
|
69279
|
+
}
|
|
69280
|
+
const callback = {
|
|
69281
|
+
code: url.searchParams.get("code"),
|
|
69282
|
+
state: url.searchParams.get("state"),
|
|
69283
|
+
iss: url.searchParams.get("iss")
|
|
69284
|
+
};
|
|
69285
|
+
const expected = {
|
|
69286
|
+
state: validateExpectedState(options.expectedState),
|
|
69287
|
+
issuer: options.expectedIssuer ?? null,
|
|
69288
|
+
requireIssuer: options.requireIssuer ?? false
|
|
69289
|
+
};
|
|
69290
|
+
validateAuthorizationCallbackBinding2(callback, expected);
|
|
69291
|
+
const authorizationError = url.searchParams.get("error");
|
|
69292
|
+
if (authorizationError !== null) {
|
|
69293
|
+
const description = url.searchParams.get("error_description");
|
|
69294
|
+
const safeError = sanitizeAuthorizationError(authorizationError, expected.state);
|
|
69295
|
+
const safeDescription = description === null ? null : sanitizeAuthorizationError(description, expected.state);
|
|
69296
|
+
throw new Error(
|
|
69297
|
+
safeDescription === null ? `OAuth authorization failed: ${safeError}` : `OAuth authorization failed: ${safeError} \u2014 ${safeDescription}`
|
|
69298
|
+
);
|
|
69299
|
+
}
|
|
69300
|
+
return validateAuthorizationCallbackParameters2(callback, expected);
|
|
69301
|
+
}
|
|
69273
69302
|
async function createLoopbackAuthorizationSession2(options = {}) {
|
|
69274
69303
|
const callbackPath = options.callbackPath ?? "/callback";
|
|
69275
69304
|
const server = options.createServer ? options.createServer() : http2.createServer();
|
|
@@ -69316,45 +69345,24 @@ function waitForAuthorizationCode2(server, authorizationUrl, options, callbackPa
|
|
|
69316
69345
|
res.end("Not found");
|
|
69317
69346
|
return;
|
|
69318
69347
|
}
|
|
69319
|
-
const error3 = url.searchParams.get("error");
|
|
69320
|
-
if (error3 !== null) {
|
|
69321
|
-
try {
|
|
69322
|
-
validateAuthorizationCallbackBinding2(
|
|
69323
|
-
{
|
|
69324
|
-
state: url.searchParams.get("state"),
|
|
69325
|
-
iss: url.searchParams.get("iss")
|
|
69326
|
-
},
|
|
69327
|
-
expectedAuthorization
|
|
69328
|
-
);
|
|
69329
|
-
} catch (validationError) {
|
|
69330
|
-
res.writeHead(400);
|
|
69331
|
-
res.end(
|
|
69332
|
-
validationError instanceof Error ? validationError.message : "Invalid OAuth callback"
|
|
69333
|
-
);
|
|
69334
|
-
return;
|
|
69335
|
-
}
|
|
69336
|
-
const description = url.searchParams.get("error_description") ?? error3;
|
|
69337
|
-
res.writeHead(400);
|
|
69338
|
-
res.end(`Authorization failed: ${description}`);
|
|
69339
|
-
settle(() => reject(new Error(`OAuth authorization failed: ${error3} \u2014 ${description}`)));
|
|
69340
|
-
return;
|
|
69341
|
-
}
|
|
69342
69348
|
try {
|
|
69343
|
-
const code =
|
|
69344
|
-
|
|
69345
|
-
|
|
69346
|
-
|
|
69347
|
-
|
|
69348
|
-
|
|
69349
|
-
expectedAuthorization
|
|
69350
|
-
);
|
|
69349
|
+
const code = validateOAuthAuthorizationCallback({
|
|
69350
|
+
callbackUrl: url,
|
|
69351
|
+
expectedState: expectedAuthorization.state ?? "",
|
|
69352
|
+
expectedIssuer: expectedAuthorization.issuer ?? void 0,
|
|
69353
|
+
requireIssuer: expectedAuthorization.requireIssuer
|
|
69354
|
+
});
|
|
69351
69355
|
res.writeHead(200, { "Content-Type": "text/html" });
|
|
69352
69356
|
res.end(buildSuccessPage2(options.landingPage));
|
|
69353
69357
|
settle(() => resolve16(code));
|
|
69354
|
-
} catch (
|
|
69358
|
+
} catch (error3) {
|
|
69359
|
+
const validationError = error3 instanceof Error ? error3 : new Error(String(error3));
|
|
69355
69360
|
res.writeHead(400);
|
|
69356
|
-
res.end(
|
|
69357
|
-
|
|
69361
|
+
res.end(validationError.message);
|
|
69362
|
+
if (url.searchParams.has("error") && !validationError.message.startsWith("OAuth authorization failed:")) {
|
|
69363
|
+
return;
|
|
69364
|
+
}
|
|
69365
|
+
settle(() => reject(validationError));
|
|
69358
69366
|
}
|
|
69359
69367
|
});
|
|
69360
69368
|
if (options.readLine !== void 0) {
|
|
@@ -69439,6 +69447,18 @@ function validateAuthorizationCallbackBinding2(callback, expected) {
|
|
|
69439
69447
|
throw new Error("OAuth callback issuer mismatch");
|
|
69440
69448
|
}
|
|
69441
69449
|
}
|
|
69450
|
+
function validateExpectedState(state) {
|
|
69451
|
+
if (state.length === 0 || state.trim() !== state) {
|
|
69452
|
+
throw new Error("Poe OAuth expectedState must not be blank or contain surrounding whitespace.");
|
|
69453
|
+
}
|
|
69454
|
+
return state;
|
|
69455
|
+
}
|
|
69456
|
+
function sanitizeAuthorizationError(value, expectedState) {
|
|
69457
|
+
if (value.includes(expectedState)) {
|
|
69458
|
+
return "authorization_error";
|
|
69459
|
+
}
|
|
69460
|
+
return value;
|
|
69461
|
+
}
|
|
69442
69462
|
function escapeHtml4(text5) {
|
|
69443
69463
|
return text5.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """);
|
|
69444
69464
|
}
|
|
@@ -69468,7 +69488,33 @@ function generateCodeVerifier2() {
|
|
|
69468
69488
|
return crypto7.randomBytes(32).toString("base64url");
|
|
69469
69489
|
}
|
|
69470
69490
|
function generateCodeChallenge2(verifier) {
|
|
69471
|
-
return crypto7.createHash("sha256").update(verifier).digest("base64url");
|
|
69491
|
+
return crypto7.createHash("sha256").update(validateCodeVerifier(verifier)).digest("base64url");
|
|
69492
|
+
}
|
|
69493
|
+
function validateCodeVerifier(verifier) {
|
|
69494
|
+
if (verifier.length < 43 || verifier.length > 128 || !hasOnlyPkceCharacters(verifier)) {
|
|
69495
|
+
throw new Error(
|
|
69496
|
+
"Poe OAuth codeVerifier must contain 43 to 128 URL-safe PKCE characters."
|
|
69497
|
+
);
|
|
69498
|
+
}
|
|
69499
|
+
return verifier;
|
|
69500
|
+
}
|
|
69501
|
+
function validateCodeChallenge(challenge) {
|
|
69502
|
+
if (challenge.length !== 43 || !hasOnlyPkceCharacters(challenge)) {
|
|
69503
|
+
throw new Error("Poe OAuth codeChallenge must contain 43 URL-safe PKCE characters.");
|
|
69504
|
+
}
|
|
69505
|
+
return challenge;
|
|
69506
|
+
}
|
|
69507
|
+
function hasOnlyPkceCharacters(value) {
|
|
69508
|
+
for (const character of value) {
|
|
69509
|
+
const code = character.charCodeAt(0);
|
|
69510
|
+
const isDigit6 = code >= 48 && code <= 57;
|
|
69511
|
+
const isUppercase = code >= 65 && code <= 90;
|
|
69512
|
+
const isLowercase = code >= 97 && code <= 122;
|
|
69513
|
+
if (!isDigit6 && !isUppercase && !isLowercase && character !== "-" && character !== "_") {
|
|
69514
|
+
return false;
|
|
69515
|
+
}
|
|
69516
|
+
}
|
|
69517
|
+
return true;
|
|
69472
69518
|
}
|
|
69473
69519
|
var init_pkce2 = __esm({
|
|
69474
69520
|
"packages/poe-oauth/src/pkce.ts"() {
|
|
@@ -69482,7 +69528,15 @@ function createOAuthClient(config2) {
|
|
|
69482
69528
|
const clientId = validateClientId(config2.clientId);
|
|
69483
69529
|
const normalizedConfig = {
|
|
69484
69530
|
...config2,
|
|
69485
|
-
clientId
|
|
69531
|
+
clientId,
|
|
69532
|
+
authorizationEndpoint: validateHttpUrl(
|
|
69533
|
+
config2.authorizationEndpoint ?? DEFAULT_AUTHORIZATION_ENDPOINT,
|
|
69534
|
+
"authorizationEndpoint"
|
|
69535
|
+
),
|
|
69536
|
+
tokenEndpoint: validateHttpUrl(
|
|
69537
|
+
config2.tokenEndpoint ?? DEFAULT_TOKEN_ENDPOINT,
|
|
69538
|
+
"tokenEndpoint"
|
|
69539
|
+
)
|
|
69486
69540
|
};
|
|
69487
69541
|
return {
|
|
69488
69542
|
authorize: () => startAuthorization(normalizedConfig, fetchFn)
|
|
@@ -69506,8 +69560,8 @@ async function startAuthorization(config2, fetchFn) {
|
|
|
69506
69560
|
}
|
|
69507
69561
|
});
|
|
69508
69562
|
const redirectUri = loopbackSession.redirectUri;
|
|
69509
|
-
const authorizationUrl =
|
|
69510
|
-
|
|
69563
|
+
const authorizationUrl = createOAuthAuthorizationUrl({
|
|
69564
|
+
authorizationEndpoint,
|
|
69511
69565
|
clientId: config2.clientId,
|
|
69512
69566
|
redirectUri,
|
|
69513
69567
|
codeChallenge,
|
|
@@ -69521,13 +69575,13 @@ async function startAuthorization(config2, fetchFn) {
|
|
|
69521
69575
|
resultPromise ??= (async () => {
|
|
69522
69576
|
try {
|
|
69523
69577
|
const code = await loopbackSession.waitForCode(authorizationUrl);
|
|
69524
|
-
return await
|
|
69578
|
+
return await exchangeOAuthCode({
|
|
69525
69579
|
tokenEndpoint,
|
|
69526
69580
|
code,
|
|
69527
69581
|
codeVerifier,
|
|
69528
69582
|
clientId: config2.clientId,
|
|
69529
69583
|
redirectUri,
|
|
69530
|
-
fetchFn
|
|
69584
|
+
fetch: fetchFn
|
|
69531
69585
|
});
|
|
69532
69586
|
} finally {
|
|
69533
69587
|
loopbackSession.close();
|
|
@@ -69537,40 +69591,65 @@ async function startAuthorization(config2, fetchFn) {
|
|
|
69537
69591
|
};
|
|
69538
69592
|
return { authorizationUrl, waitForResult: waitForResult3 };
|
|
69539
69593
|
}
|
|
69540
|
-
function
|
|
69541
|
-
const
|
|
69594
|
+
function createOAuthAuthorizationUrl(options) {
|
|
69595
|
+
const clientId = validateClientId(options.clientId);
|
|
69596
|
+
const redirectUri = validateHttpUrl(options.redirectUri, "redirectUri");
|
|
69597
|
+
const state = validateOpaqueValue(options.state, "state");
|
|
69598
|
+
const codeChallenge = validateCodeChallenge(options.codeChallenge);
|
|
69599
|
+
const authorizationEndpoint = validateHttpUrl(
|
|
69600
|
+
options.authorizationEndpoint ?? DEFAULT_AUTHORIZATION_ENDPOINT,
|
|
69601
|
+
"authorizationEndpoint"
|
|
69602
|
+
);
|
|
69603
|
+
const url = new URL(authorizationEndpoint);
|
|
69542
69604
|
url.searchParams.set("response_type", "code");
|
|
69543
|
-
url.searchParams.set("client_id",
|
|
69605
|
+
url.searchParams.set("client_id", clientId);
|
|
69544
69606
|
url.searchParams.set("scope", "apikey:create");
|
|
69545
|
-
url.searchParams.set("code_challenge",
|
|
69607
|
+
url.searchParams.set("code_challenge", codeChallenge);
|
|
69546
69608
|
url.searchParams.set("code_challenge_method", "S256");
|
|
69547
|
-
url.searchParams.set("redirect_uri",
|
|
69548
|
-
url.searchParams.set("state",
|
|
69609
|
+
url.searchParams.set("redirect_uri", redirectUri);
|
|
69610
|
+
url.searchParams.set("state", state);
|
|
69549
69611
|
return url.toString();
|
|
69550
69612
|
}
|
|
69551
|
-
async function
|
|
69613
|
+
async function exchangeOAuthCode(options) {
|
|
69614
|
+
const clientId = validateClientId(options.clientId);
|
|
69615
|
+
const redirectUri = validateHttpUrl(options.redirectUri, "redirectUri");
|
|
69616
|
+
const code = validateOpaqueValue(options.code, "code");
|
|
69617
|
+
const codeVerifier = validateCodeVerifier(options.codeVerifier);
|
|
69618
|
+
const tokenEndpoint = validateHttpUrl(
|
|
69619
|
+
options.tokenEndpoint ?? DEFAULT_TOKEN_ENDPOINT,
|
|
69620
|
+
"tokenEndpoint"
|
|
69621
|
+
);
|
|
69622
|
+
const fetchFn = options.fetch ?? globalThis.fetch;
|
|
69552
69623
|
const body = new URLSearchParams({
|
|
69553
69624
|
grant_type: "authorization_code",
|
|
69554
|
-
code
|
|
69555
|
-
code_verifier:
|
|
69556
|
-
client_id:
|
|
69557
|
-
redirect_uri:
|
|
69558
|
-
});
|
|
69559
|
-
const response = await params.fetchFn(params.tokenEndpoint, {
|
|
69560
|
-
method: "POST",
|
|
69561
|
-
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
69562
|
-
body: body.toString()
|
|
69625
|
+
code,
|
|
69626
|
+
code_verifier: codeVerifier,
|
|
69627
|
+
client_id: clientId,
|
|
69628
|
+
redirect_uri: redirectUri
|
|
69563
69629
|
});
|
|
69630
|
+
let response;
|
|
69631
|
+
try {
|
|
69632
|
+
response = await fetchFn(tokenEndpoint, {
|
|
69633
|
+
method: "POST",
|
|
69634
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
69635
|
+
body: body.toString()
|
|
69636
|
+
});
|
|
69637
|
+
} catch {
|
|
69638
|
+
throw new Error("Token exchange request failed");
|
|
69639
|
+
}
|
|
69564
69640
|
if (!response.ok) {
|
|
69565
69641
|
const text5 = await response.text();
|
|
69566
69642
|
const description = parseErrorDescription(text5);
|
|
69567
|
-
|
|
69643
|
+
if (description !== null && !description.includes(codeVerifier) && !description.includes(code)) {
|
|
69644
|
+
throw new Error(description);
|
|
69645
|
+
}
|
|
69646
|
+
throw new Error(`Token exchange failed (${response.status})`);
|
|
69568
69647
|
}
|
|
69569
69648
|
let value;
|
|
69570
69649
|
try {
|
|
69571
69650
|
value = await response.json();
|
|
69572
69651
|
} catch (error3) {
|
|
69573
|
-
throw new Error(`Token exchange failed: invalid JSON response from ${
|
|
69652
|
+
throw new Error(`Token exchange failed: invalid JSON response from ${tokenEndpoint}`, {
|
|
69574
69653
|
cause: error3
|
|
69575
69654
|
});
|
|
69576
69655
|
}
|
|
@@ -69626,6 +69705,27 @@ function validateClientId(clientId) {
|
|
|
69626
69705
|
}
|
|
69627
69706
|
return clientId;
|
|
69628
69707
|
}
|
|
69708
|
+
function validateHttpUrl(value, field) {
|
|
69709
|
+
if (value.trim() !== value || value.length === 0) {
|
|
69710
|
+
throw new Error(`Poe OAuth ${field} must be an absolute HTTP(S) URL.`);
|
|
69711
|
+
}
|
|
69712
|
+
let url;
|
|
69713
|
+
try {
|
|
69714
|
+
url = new URL(value);
|
|
69715
|
+
} catch {
|
|
69716
|
+
throw new Error(`Poe OAuth ${field} must be an absolute HTTP(S) URL.`);
|
|
69717
|
+
}
|
|
69718
|
+
if (url.protocol !== "https:" && url.protocol !== "http:" || url.hash.length > 0) {
|
|
69719
|
+
throw new Error(`Poe OAuth ${field} must be an absolute HTTP(S) URL without a fragment.`);
|
|
69720
|
+
}
|
|
69721
|
+
return url.toString();
|
|
69722
|
+
}
|
|
69723
|
+
function validateOpaqueValue(value, field) {
|
|
69724
|
+
if (value.length === 0 || value.trim() !== value) {
|
|
69725
|
+
throw new Error(`Poe OAuth ${field} must not be blank or contain surrounding whitespace.`);
|
|
69726
|
+
}
|
|
69727
|
+
return value;
|
|
69728
|
+
}
|
|
69629
69729
|
function isValidExpiresIn(value) {
|
|
69630
69730
|
if (typeof value !== "number" || !Number.isFinite(value) || !Number.isInteger(value) || value < 0) {
|
|
69631
69731
|
return false;
|
|
@@ -69652,6 +69752,8 @@ var init_src30 = __esm({
|
|
|
69652
69752
|
"use strict";
|
|
69653
69753
|
init_check_auth();
|
|
69654
69754
|
init_oauth_client();
|
|
69755
|
+
init_loopback_authorization2();
|
|
69756
|
+
init_pkce2();
|
|
69655
69757
|
}
|
|
69656
69758
|
});
|
|
69657
69759
|
|
|
@@ -151176,7 +151278,7 @@ var init_package2 = __esm({
|
|
|
151176
151278
|
"package.json"() {
|
|
151177
151279
|
package_default2 = {
|
|
151178
151280
|
name: "poe-code",
|
|
151179
|
-
version: "4.0.
|
|
151281
|
+
version: "4.0.21",
|
|
151180
151282
|
description: "CLI tool to configure Poe API for developer workflows.",
|
|
151181
151283
|
license: "MIT",
|
|
151182
151284
|
type: "module",
|
|
@@ -151195,6 +151297,10 @@ var init_package2 = __esm({
|
|
|
151195
151297
|
types: "./dist/agent.d.ts",
|
|
151196
151298
|
import: "./dist/agent.js"
|
|
151197
151299
|
},
|
|
151300
|
+
"./credentials": {
|
|
151301
|
+
types: "./dist/credentials.d.ts",
|
|
151302
|
+
import: "./dist/credentials.js"
|
|
151303
|
+
},
|
|
151198
151304
|
"./skills": {
|
|
151199
151305
|
types: "./dist/skills.d.ts",
|
|
151200
151306
|
import: "./dist/skills.js"
|