@everworker/oneringai 0.2.1 → 0.2.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 CHANGED
@@ -55,6 +55,15 @@
55
55
 
56
56
  ---
57
57
 
58
+ ## HOSEA APP
59
+ We realize that library alone in these times is not enough to get you excited, so we built a FREE FOREVER desktop app on top of this library to showcase its power! It's as easy to start using as cloning this library's repo, and then `cd apps/hosea` and then `npm install` and then `npm run dev`. Or watch the video first:
60
+
61
+ ![Watch the demo](https://img.youtube.com/vi/_LzDiuOQD8Y/maxresdefault.jpg)](https://www.youtube.com/watch?v=_LzDiuOQD8Y)
62
+
63
+ Or read the more detailed installation / setup instructions [here](https://github.com/Integrail/oneringai/blob/main/apps/hosea/README.md)
64
+
65
+ Better to see once and then dig in the code! :)
66
+
58
67
  ## Features
59
68
 
60
69
  - ✨ **Unified API** - One interface for 10+ AI providers (OpenAI, Anthropic, Google, Groq, DeepSeek, and more)
@@ -342,14 +342,32 @@ var AuthCodePKCEFlow = class {
342
342
  if (this.config.usePKCE !== false && verifierData) {
343
343
  params.append("code_verifier", verifierData.verifier);
344
344
  }
345
- const response = await fetch(this.config.tokenUrl, {
345
+ let response = await fetch(this.config.tokenUrl, {
346
346
  method: "POST",
347
347
  headers: {
348
348
  "Content-Type": "application/x-www-form-urlencoded"
349
349
  },
350
350
  body: params
351
351
  });
352
- if (!response.ok) {
352
+ if (!response.ok && this.config.clientSecret) {
353
+ const errorText = await response.text();
354
+ if (isPublicClientError(errorText)) {
355
+ params.delete("client_secret");
356
+ response = await fetch(this.config.tokenUrl, {
357
+ method: "POST",
358
+ headers: {
359
+ "Content-Type": "application/x-www-form-urlencoded"
360
+ },
361
+ body: params
362
+ });
363
+ if (!response.ok) {
364
+ const retryError = await response.text();
365
+ throw new Error(`Token exchange failed: ${response.status} ${response.statusText} - ${retryError}`);
366
+ }
367
+ } else {
368
+ throw new Error(`Token exchange failed: ${response.status} ${response.statusText} - ${errorText}`);
369
+ }
370
+ } else if (!response.ok) {
353
371
  const error = await response.text();
354
372
  throw new Error(`Token exchange failed: ${response.status} ${response.statusText} - ${error}`);
355
373
  }
@@ -395,14 +413,32 @@ var AuthCodePKCEFlow = class {
395
413
  if (this.config.clientSecret) {
396
414
  params.append("client_secret", this.config.clientSecret);
397
415
  }
398
- const response = await fetch(this.config.tokenUrl, {
416
+ let response = await fetch(this.config.tokenUrl, {
399
417
  method: "POST",
400
418
  headers: {
401
419
  "Content-Type": "application/x-www-form-urlencoded"
402
420
  },
403
421
  body: params
404
422
  });
405
- if (!response.ok) {
423
+ if (!response.ok && this.config.clientSecret) {
424
+ const errorText = await response.text();
425
+ if (isPublicClientError(errorText)) {
426
+ params.delete("client_secret");
427
+ response = await fetch(this.config.tokenUrl, {
428
+ method: "POST",
429
+ headers: {
430
+ "Content-Type": "application/x-www-form-urlencoded"
431
+ },
432
+ body: params
433
+ });
434
+ if (!response.ok) {
435
+ const retryError = await response.text();
436
+ throw new Error(`Token refresh failed: ${response.status} ${response.statusText} - ${retryError}`);
437
+ }
438
+ } else {
439
+ throw new Error(`Token refresh failed: ${response.status} ${response.statusText} - ${errorText}`);
440
+ }
441
+ } else if (!response.ok) {
406
442
  const error = await response.text();
407
443
  throw new Error(`Token refresh failed: ${response.status} ${response.statusText} - ${error}`);
408
444
  }
@@ -457,6 +493,10 @@ var AuthCodePKCEFlow = class {
457
493
  }
458
494
  }
459
495
  };
496
+ function isPublicClientError(responseBody) {
497
+ const lower = responseBody.toLowerCase();
498
+ return lower.includes("aadsts700025") || lower.includes("invalid_client") && lower.includes("public");
499
+ }
460
500
 
461
501
  // src/connectors/oauth/flows/ClientCredentials.ts
462
502
  var ClientCredentialsFlow = class {