opencode-anthropic-fix 0.1.32 → 0.2.0

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.
Files changed (37) hide show
  1. package/README.md +2 -0
  2. package/cli.mjs +42 -35
  3. package/index.mjs +399 -3591
  4. package/lib/config.test.mjs +298 -1
  5. package/lib/diagnose.mjs +184 -0
  6. package/lib/diagnose.test.mjs +122 -0
  7. package/lib/env.mjs +19 -0
  8. package/lib/env.test.mjs +25 -0
  9. package/lib/mimicry/cache.mjs +62 -0
  10. package/lib/mimicry/cache.test.mjs +112 -0
  11. package/lib/mimicry/headers.mjs +530 -0
  12. package/lib/mimicry/headers.test.mjs +50 -0
  13. package/lib/mimicry/models.mjs +146 -0
  14. package/lib/mimicry/models.test.mjs +132 -0
  15. package/lib/mimicry/request-body.mjs +684 -0
  16. package/lib/mimicry/request-body.test.mjs +34 -0
  17. package/lib/mimicry/request-helpers.mjs +243 -0
  18. package/lib/mimicry/request-helpers.test.mjs +155 -0
  19. package/lib/mimicry/response-stream.mjs +429 -0
  20. package/lib/mimicry/response-stream.test.mjs +127 -0
  21. package/lib/mimicry/system-prompt.mjs +638 -0
  22. package/lib/mimicry/system-prompt.test.mjs +73 -0
  23. package/lib/redact.mjs +147 -0
  24. package/lib/redact.test.mjs +154 -0
  25. package/lib/refresh-lock.test.mjs +52 -0
  26. package/lib/retry/overload-loop.mjs +83 -0
  27. package/lib/retry/overload-loop.test.mjs +107 -0
  28. package/lib/session-metrics.mjs +75 -0
  29. package/lib/session-metrics.test.mjs +67 -0
  30. package/lib/storage.test.mjs +82 -0
  31. package/lib/token-economy/microcompact.mjs +35 -0
  32. package/lib/token-economy/microcompact.test.mjs +28 -0
  33. package/lib/token-economy/transforms.mjs +637 -0
  34. package/lib/token-economy/transforms.test.mjs +192 -0
  35. package/lib/tuning.mjs +70 -0
  36. package/lib/tuning.test.mjs +89 -0
  37. package/package.json +4 -1
package/README.md CHANGED
@@ -597,6 +597,8 @@ Account credentials are stored with restrictive file permissions (owner read/wri
597
597
 
598
598
  ## Troubleshooting
599
599
 
600
+ Run `opencode-anthropic-auth diagnose` to write a redacted, shareable diagnostic bundle, or add `--stdout` to print it.
601
+
600
602
  ### "Provider not showing up"
601
603
 
602
604
  Make sure the plugin is installed in `~/.config/opencode/plugin/`. Restart OpenCode after installing.
package/cli.mjs CHANGED
@@ -29,13 +29,17 @@
29
29
  */
30
30
 
31
31
  import { loadAccounts, saveAccounts, getStoragePath, createDefaultStats } from "./lib/storage.mjs";
32
- import { loadConfig, saveConfig, getConfigPath, VALID_STRATEGIES, CLIENT_ID } from "./lib/config.mjs";
33
- import { authorize, exchange, revoke } from "./lib/oauth.mjs";
32
+ import { loadConfig, saveConfig, getConfigPath, VALID_STRATEGIES } from "./lib/config.mjs";
33
+ import { authorize, exchange, refreshToken, revoke } from "./lib/oauth.mjs";
34
+ import { adjustActiveIndexAfterRemoval } from "./lib/account-state.mjs";
34
35
  import { AsyncLocalStorage } from "node:async_hooks";
36
+ import { writeFile } from "node:fs/promises";
37
+ import path from "node:path";
35
38
  import { pathToFileURL } from "node:url";
36
39
  import { exec } from "node:child_process";
37
40
  import { createInterface } from "node:readline/promises";
38
41
  import { stdin, stdout } from "node:process";
42
+ import { buildDiagnosticBundle } from "./lib/diagnose.mjs";
39
43
 
40
44
  // ---------------------------------------------------------------------------
41
45
  // Color helpers — zero dependencies, respects NO_COLOR / TTY
@@ -146,18 +150,7 @@ function rpad(str, width) {
146
150
  */
147
151
  export async function refreshAccessToken(account) {
148
152
  try {
149
- const resp = await fetch("https://platform.claude.com/v1/oauth/token", {
150
- method: "POST",
151
- headers: { "Content-Type": "application/json" },
152
- body: JSON.stringify({
153
- grant_type: "refresh_token",
154
- refresh_token: account.refreshToken,
155
- client_id: CLIENT_ID,
156
- }),
157
- signal: AbortSignal.timeout(5000),
158
- });
159
- if (!resp.ok) return null;
160
- const json = await resp.json();
153
+ const json = await refreshToken(account.refreshToken, { signal: AbortSignal.timeout(5000) });
161
154
  account.access = json.access_token;
162
155
  account.expires = Date.now() + json.expires_in * 1000;
163
156
  if (json.refresh_token) account.refreshToken = json.refresh_token;
@@ -483,13 +476,7 @@ export async function cmdLogout(arg, opts = {}) {
483
476
  stored.accounts.splice(idx, 1);
484
477
 
485
478
  // Adjust active index
486
- if (stored.accounts.length === 0) {
487
- stored.activeIndex = 0;
488
- } else if (stored.activeIndex >= stored.accounts.length) {
489
- stored.activeIndex = stored.accounts.length - 1;
490
- } else if (stored.activeIndex > idx) {
491
- stored.activeIndex--;
492
- }
479
+ adjustActiveIndexAfterRemoval(stored, idx);
493
480
 
494
481
  await saveAccounts(stored);
495
482
  console.log(c.green(`Logged out account #${n} (${label}).`));
@@ -1019,13 +1006,7 @@ export async function cmdRemove(arg, opts = {}) {
1019
1006
  stored.accounts.splice(idx, 1);
1020
1007
 
1021
1008
  // Adjust active index
1022
- if (stored.accounts.length === 0) {
1023
- stored.activeIndex = 0;
1024
- } else if (stored.activeIndex >= stored.accounts.length) {
1025
- stored.activeIndex = stored.accounts.length - 1;
1026
- } else if (stored.activeIndex > idx) {
1027
- stored.activeIndex--;
1028
- }
1009
+ adjustActiveIndexAfterRemoval(stored, idx);
1029
1010
 
1030
1011
  await saveAccounts(stored);
1031
1012
  console.log(c.green(`Removed account #${n} (${label}).`));
@@ -1514,13 +1495,7 @@ export async function cmdManage() {
1514
1495
  if (confirm.trim().toLowerCase() === "y") {
1515
1496
  stored.accounts.splice(idx, 1);
1516
1497
  // Adjust active index
1517
- if (stored.accounts.length === 0) {
1518
- stored.activeIndex = 0;
1519
- } else if (stored.activeIndex >= stored.accounts.length) {
1520
- stored.activeIndex = stored.accounts.length - 1;
1521
- } else if (stored.activeIndex > idx) {
1522
- stored.activeIndex--;
1523
- }
1498
+ adjustActiveIndexAfterRemoval(stored, idx);
1524
1499
  await saveAccounts(stored);
1525
1500
  console.log(c.green(`Removed account #${num}.`));
1526
1501
  } else {
@@ -1557,6 +1532,34 @@ export async function cmdManage() {
1557
1532
  return 0;
1558
1533
  }
1559
1534
 
1535
+ /**
1536
+ * Write or print a redacted diagnostic bundle.
1537
+ *
1538
+ * @param {string | undefined} _arg
1539
+ * @param {{ stdout?: boolean }} [opts]
1540
+ * @returns {Promise<number>} exit code
1541
+ */
1542
+ export async function cmdDiagnose(_arg, opts = {}) {
1543
+ try {
1544
+ const bundle = await buildDiagnosticBundle();
1545
+ const json = JSON.stringify(bundle, null, 2);
1546
+ if (opts.stdout) {
1547
+ console.log(json);
1548
+ return 0;
1549
+ }
1550
+
1551
+ const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
1552
+ const outputPath = path.resolve(process.cwd(), `opencode-anthropic-diagnose-${timestamp}.json`);
1553
+ await writeFile(outputPath, `${json}\n`, "utf8");
1554
+ console.log(outputPath);
1555
+ return 0;
1556
+ } catch (error) {
1557
+ const message = error instanceof Error ? error.message : String(error);
1558
+ console.error(c.red(`Failed to create diagnostic bundle: ${message}`));
1559
+ return 1;
1560
+ }
1561
+ }
1562
+
1560
1563
  /**
1561
1564
  * Show help text.
1562
1565
  */
@@ -1588,6 +1591,7 @@ ${c.dim("Account Commands:")}
1588
1591
  ${pad(c.cyan("strategy") + " [name]", 22)}Show or change selection strategy
1589
1592
  ${pad(c.cyan("config"), 22)}Show configuration and file paths
1590
1593
  ${pad(c.cyan("manage"), 22)}Interactive account management menu
1594
+ ${pad(c.cyan("diagnose"), 22)}Write a redacted diagnostic bundle ${c.dim("(dg; --stdout to print)")}
1591
1595
  ${pad(c.cyan("help"), 22)}Show this help message
1592
1596
 
1593
1597
  ${c.dim("Options:")}
@@ -1732,6 +1736,9 @@ async function dispatch(argv) {
1732
1736
  case "manage":
1733
1737
  case "mg":
1734
1738
  return cmdManage();
1739
+ case "diagnose":
1740
+ case "dg":
1741
+ return cmdDiagnose(arg, { stdout: flags.includes("--stdout") });
1735
1742
  case "help":
1736
1743
  case "-h":
1737
1744
  case "--help":